WebdriverIO v9 Released
The whole Webdriverio development team is stoked and proud to release WebdriverIO v9 today!
This marks the beginning of a new exciting era for all projects using WebdriverIO as their test automation tool. With the great work of browser teams that are working on e.g. Chrome and Firefox, we now enter a new era that offers much greater automation capabilities than ever before thanks to the new WebDriver Bidi protocol. With WebdriverIO v9 we have been working to be at the forefront of adopters of this new era and allow you to leverage from the power of the protocol first.
Let's explore the new features, updates, and optimizations in this release.
New Features
The majority of the new features in v9 are enabled by the WebDriver Bidi capabilities now available in browsers. Upon upgrading to v9, all sessions will automatically use Bidi unless you explicitly disable it via the new wdio:enforceWebDriverClassic
capability.
These features unfortunately won't be available to you if your remote environment doesn't support WebDriver Bidi. You can check if Bidi is support in your session by looking into the browser.isBidi
property.
New url
Command Parameters
The url
command has evolved from a simple navigation tool to a powerful feature-packed command.
Passing in Custom Headers
You can now pass custom headers that will be applied when the browser makes a request. This is useful for setting session cookies to log in automatically.
await browser.url('https://webdriver.io', {
headers: {
Authorization: 'Bearer XXXXX'
}
});
Note that while you can modify how the browser treats all requests through the mock
command, changes applied to the url
command only last for that particular page load and reset once navigation is complete.
Overcome Basic Authentification
Automating user authentication via basic authentication has never been easier:
await browser.url('https://the-internet.herokuapp.com/basic_auth', {
auth: {
user: 'admin',
pass: 'admin'
}
});
await expect($('p=Congratulations! You must have the proper credentials.').toBeDisplayed();
Running an Initialization Script
Inject JavaScript before anything loads on the website using the beforeLoad
parameter. This is useful for manipulating Web APIs, e.g.:
// navigate to a URL and mock the battery API
await browser.url('https://pazguille.github.io/demo-battery-api/', {
onBeforeLoad (win) {
// mock "navigator.battery" property
// returning mock charge object
win.navigator.getBattery = () => Promise.resolve({
level: 0.5,
charging: false,
chargingTime: Infinity,
dischargingTime: 3600, // seconds
})
}
})
// now we can assert actual text - we are charged at 50%
await expect($('.battery-percentage')).toHaveText('50%')
// and has enough juice for 1 hour
await expect($('.battery-remaining')).toHaveText('01:00)
In this example, we overwrite the getBattery
method of the Navigator
interface.
New addInitScript
Command
The addInitScript
command enables you to inject a script into the browser that is triggered every time a new browsing context is opened. This includes actions such as navigating to a URL or loading an iframe within an application. The script you pass to this command receives a callback as its last parameter, allowing you to send values from the browser back to your Node.js environment.
For instance, to get notified whenever an element is added or removed from a node in the application, you can use the following example:
const script = await browser.addInitScript((myParam, emit) => {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
emit(mutation.target.nodeName)
}
})
observer.observe(document, { childList: true, subtree: true })
})
script.on('data', (data) => {
console.log(data) // prints: BODY, DIV, P, ...
})
This initialization script can modify global variables and overwrite built-in Web API primitives, allowing you to configure the test environment to meet your specific requirements.
Cross Browser Request Mocking
WebdriverIO introduced request mocking in v6.3.0
, limited to Chromium browsers. With v9, we now use WebDriver Bidi, extending support to all browsers. This enhancement allows modifying requests before they go out to the network:
// mock all API requests
const mock = await browser.mock('**/api/**')
// apply auth token to each request
mock.request({
headers: { 'Authorization': 'Bearer XXXXXX' }
})