Step-by-Step Guide to Creating a Custom Log Wrapper in WebDriverIO
In this guide, well enhance console logging in WebDriverIO by creating a global log wrapper with custom features like color-coding and promise handling. Logging is an essential part of debugging and understanding what your code is doing under the hood. While console.log()
works well, enhancing it with custom formatting and color coding can make your logs more readable and informative. In this blog, well walk through how to create a global wrapper around console.log()
in your WebDriverIO configuration, adding flexibility and clarity to your log messages.
Why Use a Global Log Wrapper in WebDriverIO?
One of the key challenges in Automation Frameworks is distinguishing your custom log messages from framework or Node.js logs. A simple console output can easily get buried, making it harder to track essential messages. We need a way to make our logs stand out while adding some useful features like skipping empty logs, handling unresolved promises, and color-coding for different log levels.
Step 1: Creating a Simple log()
Wrapper
The console.log()
method is great for outputting information to the console, but we can enhance and shorten it with a custom log()
wrapper. Add this snippet at the end of your wdio.conf.ts
file:
/** * log wrapper * @param text to be output to the console window */global.log = (text) => { console.log(`---> ${text}`);}
This new global.log()
works like console.log()
, but with a little extra formatting to help your logs stand out. Lets see it in action:
Before:
console.log('Entering text');
Output:
[0-0] Entering text
After:
await global.log('Entering text');
Output:
[0-0] ---> Entering text
By adding this wrapper, your custom messages are clearly separated from the ones generated by the framework or Node.js.
Step 2: How to Handle Promises and Enhancing the log()
Function
Lets take this a step further. What if we want to skip empty strings and null values in our logs? Or detect when a Promise is passed to the log? Heres an improved version:
global.log = (text) => { if (text) { // Truthy value check if (text === Promise) { console.log('---> WARN: Log was passed a Promise object'); console.trace(); } else { console.log(`---> ${text}`); } }}
This version gives you more control. It:
Ignores empty and null values.
Warns when a Promise object is passed.
Prints a console trace showing where the unresolved Promise originated.
Step 3: How to Add Color-Coded Logs
To make your logs even more distinguishable, we can add color coding using ANSI escape codes. Heres how:
global.log = (text, level = 'info') => { if (text === undefined || text === null) { console.log('\x1b[33m%s\x1b[0m', '---> No log content (undefined or null)'); // Yellow for empty values return; } let colorCode; switch (level.toLowerCase()) { case 'info': colorCode = '\x1b[32m'; // Green for info break; case 'warn': colorCode = '\x1b[33m'; // Yellow for warnings break; case 'error': colorCode = '\x1b[31m'; // Red for errors break; default: colorCode = '\x1b[37m'; // White for others } if (text instanceof Promise) { console.log('\x1b[33m%s\x1b[0m', '---> WARN: Log was passed a Promise object'); // Yellow warning console.trace(); } else if (typeof text === 'object') { console.log(`${colorCode}%s\x1b[0m`, `---> ${level.toUpperCase()}: ${JSON.stringify(text, null, 2)}`); } else { console.log(`${colorCode}%s\x1b[0m`, `---> ${level.toUpperCase()}: ${text}`); }};
Function Definition
Here's an updated version of global.log
function with color codes:
Info logs will be green.
Warn logs will be yellow.
Error logs will be red.
The global.log
function is defined globally, meaning it can be accessed from anywhere in the application.
It takes two parameters:
text
: The message or object to be loggedlevel
: The severity level of the log (default is 'info')
Handling Different Types of Input:
If the input is undefined or null, it logs a yellow message saying "No log content".
If the input is a Promise, it warns that a Promise was passed and shows a stack trace.
If the input is an object, it's converted to a formatted JSON string.
For other types (like strings), it's logged as-is.
Color Code Explanation:
\x1b[32m: Green color for info logs.
\x1b[33m: Yellow color for warn logs.
\x1b[31m: Red color for error logs.
\x1b[37m: Default white for other log levels.
\x1b[0m: Resets the color back to normal after printing the log.
Output Format:
Each log message starts with "--->" followed by the uppercase log level and then the message.
For objects, it uses
JSON.stringify
with indentation for better readability.
💡
Check out our guide on setting up WebDriverIO v9 for more details.
Example Usage
Now, you can use this function throughout your framework:
global.log('This is an info log'); // Green textglobal.log('This is a warning', 'warn'); // Yellow textglobal.log('This is an error!', 'error'); // Red textglobal.log({ key: 'value' }, 'info'); // Green formatted object
Output:
[0-0] ---> INFO: This is an info log[0-0] ---> WARN: This is a warning[0-0] ---> ERROR: This is an error![0-0] ---> INFO: { "key": "value"}
Conclusion
By creating a custom global.log()
function, weve improved how logs are handled in our framework. From adding color-coding to ignoring empty logs, this wrapper makes debugging much easier, while ensuring the frameworks logs are separated from ours.
Have you tried creating your own log wrapper in WebDriverIO? Share your experience in the comments below, and don't forget to subscribe for more WebDriverIO tips and tricks!
Happy logging!
Important Links:
GitHub repositories related to logging ( https://github.com/hardikchotaliya/WebdriverIO-TS-Cucumber-e2e )
Official WebDriverIO documentation ( https://webdriver.io/docs/gettingstarted )
Top comments (0)