Skip to main content

How to Upgrade hermione to Version 4.x

warning

This guide is relevant only for projects using hermione versions older than 4.x.

Why Should You Upgrade?

A long time ago, hermione switched to a "temporary" fork of the webdriverio@4 package (abbr. wdio) that it used "under the hood" because issues in the external wdio were slowing down its development: constant bugs in wdio, disagreements over changes, etc. Initially, the fork was regularly updated by the hermione team to provide users with up-to-date functionality, but over time, the fork significantly lagged behind the current version of wdio globally.

By the time many new features appeared in wdio that interested developers, such as Chrome DevTools Protocol (CDP), mocking external requests, extended mobile device capabilities, etc., the hermione team had no choice but to abandon the webdriverio@4 fork and switch to the latest version of webdriverio@7.

info

Version 8 of webdriverio is already available, and hermione@7 uses it.

Additionally, users found it increasingly inconvenient to use outdated commands: typings had to be included from a separate package (in the new wdio, they are included out of the box), and documentation for commands had to be accessed on the old site, while some users occasionally visited the current page and couldn't understand why the commands from the documentation didn't work in hermione.

Thus, there were plenty of reasons for a radical upgrade — jumping up by three major versions.

What Has Changed?

There are many changes, so only the most important/interesting ones will be listed below.

Command API

async/await Instead of Chaining

In the new version, you can no longer write tests using chaining. Only async/await syntax is available:

  it('some test', function() {
return this.browser
.foo()
.bar()
.baz();
});

Starting from version hermione@4.9.0, you can write tests even shorter, as hermione now passes an object with a browser field to the function:

it("some test", async function ({ browser }) {
await browser.foo();
await browser.bar();
await browser.baz();
});
warning

In the "New" examples going forward, it is assumed that the hermione version is at least 4.9.0. If you plan to use hermione 4+ but at a lower version than 4.9.0, you should still access the browser in tests through this, for example: await this.browser.getText('.selector').

Direct Result Instead of Object with value Key

Now, instead of returning an object with a value key, the actual result is directly returned from command results (old behavior often led to errors in tests):

  it('some test', async function() {
const { value } = await this.browser.getText('.selector');
console.log(value); // some text
});

Direct Work with Elements

Using the browser.$ command, you can get an instance of the found element and work with it in the test. This is convenient when you need to interact with an element more than once (the element won't be searched again on the page):

  it('some test', async function() {
await this.browser.clearElement('.input');
await this.browser.setValue('.input', 'text');
});

Also see the commands:

Passing Arguments Through an Object

For many commands, arguments are now passed using an object with understandable keys instead of sequentially passing arguments, which could be very confusing. For example, in the waitForExist command, which previously accepted even boolean values as arguments:

it('some test', async function() {
await this.browser.waitForExist('.selector', 1000, true);
});

Special Command for React

A bonus for those who are already using React — now you can use the browser.react$ and browser.react$$ commands to find specific react components on the page with certain states. Similar commands are available for elements as well — element.react$ and element.react$$.

Also read the article on working with react components on the webdriverio website.

Example usage:

it('some test', async function() {
// no special commands for working with react components :(
});

Up-to-Date Documentation

While hermione used the old version of webdriverio@4, users constantly had to be reminded that the documentation for all commands was located at a separate address: v4.webdriver.io/api.html. Now, descriptions of all webdriverio commands used by hermione can be found at the standard address: webdriver.io/docs/api.

In addition, we translated the descriptions of all commands into Russian and adapted all usage examples to hermione, since webdriverio uses its own runner and the examples in its documentation cannot be directly applied in hermione.

Tests Run Faster

You might not notice this speedup when running several tests locally, but it will be very noticeable with a large number of tests. The new commands work about 15% faster (assuming you have stopped using the old commands).

Easy Local Browser Testing

Previously, to run tests locally in your browser, you had to start selenium-standalone and specify a magical gridUrl to make things work in hermione. Now, it's much simpler: in the config, just specify the automationProtocol option with the value devtools:

// hermione.conf.js
module.exports = {
browsers: {
chrome: {
automationProtocol: 'devtools',
desiredCapabilities: {
// ...
}
}
},

// other hermione settings...
};

We also plan to add a separate button in the hermione GUI for switching to CDP mode to make it even easier.

warning
  • Currently, this is fully supported only in the Chrome browser. * Retaking screenshots in this mode should only be done for debugging, as browsers in the pipeline run under Linux, which means page rendering will differ and tests in the pull request will fail with diffs.

API for Network Request Stubbing

The new version provides the ability to stub or override the responses of your service. This is done using the mock.respond() command. You can also block URLs of external services.

Read more about all the features in the "How to Track and Intercept Network Requests and Responses" guide.

warning

Currently, this functionality only works in Chrome DevTools Protocol (CDP) mode, which only works in Chrome and Firefox Nightly.

Browser Configuration in the Config

For browsers that support the W3C protocol, instead of the version field, you need to specify browserVersion. And additional options need to be prefixed with the browser's name:

  module.exports = {
browsers: {
'chrome-desktop': {
desiredCapabilities: {
browserName: 'chrome',
version: '75',
'chromeOptions': {
// ...
}
}
}
}
};

Read more about vendor prefixes at this link.

The list of all available settings can be found in the specification.

How to Migrate?

We upgraded webdriverio by three major versions at once, so simply updating the hermione version in package.json won't suffice. The main issues during migration are the absent chaining in tests and outdated test commands. To help you with these issues, we wrote the following guide.

1. Update hermione to 4+, Install Migrator Plugin and Codemod

Specifically:

You can do all this with one command:

npm install -D hermione@4 hermione-wdio-migrator hermione-codemod --save-exact

The versions of all hermione plugins (e.g., html-reporter) also need to be updated to the latest versions, as some may not work correctly with the new hermione version.

2. Run the Codemod for async/await

The codemod will regenerate your tests from chaining format to async/await format:

If you use the zsh shell, you can pass test files as relative paths and as glob patterns, such as somefolder/**/*.js, and so on.

npx jscodeshift -t node_modules/hermione-codemod/transforms/browser-chaining-to-async-await.js path_to_file_mask

Upon successful completion, you will see a corresponding message:

Results:
0 errors
0 unmodified
0 skipped
251 ok

However, there can be cases the current codemod cannot handle. For such tests, an error with information about the problematic file will be displayed:

WARN: can't correctly transform ConditionalExpression, fix it manually
file: tests/hermione/suites/common/promotion-page/promotion-page.hermione.js
position: {"start":112,"end":116}

Such tests will need to be fixed manually. We tried to account for most test cases, so there shouldn't be too many of these instances.

After this, you can already merge your changes (this is optional) to perform the migration in parts. The async/await syntax will still work in wdio@4. Many services have been writing tests this way for a long time.

3. Run the Codemod to Remove value

Since command results now directly return the actual result instead of an object with a value key, you need to change result handling in all tests. This codemod is intended for such cases.

The command is very similar to the previous one, only the path to the next codemod file changes:

npx jscodeshift -t node_modules/hermione-codemod/transforms/remove-browser-prop.js path_to_file_mask

For any warnings, problematic tests need to be fixed manually. For example, if a test uses value multiple times through destructuring, the codemod will not handle it properly and generic variable names might be generated. For example:

// test on wdio@4:
it('test', function(){
return this.browser
...
.getText('.button')
.then((value) => {
assert.equal(value, 'Button', 'We need a button');
})
...
.getValue('.input')
.then((value) => {
assert.equal(value, 'Hello', 'We were not greeted');
});
});

// auto-generated for wdio@7 in this format:
it('test', async function() {
const value = await this.browser.getText('.button');
assert.equal(value, 'Button', 'We need a button');
...
// there will be an error due to reuse of the variable name,
// so the codemod will issue a warning about the problematic spot
const value = await this.browser.getValue('.input');
assert.equal(value, 'Hello', 'We were not greeted');
});

If your project has too many tests that cannot be automatically migrated, please reach out to github issues for help. We will analyze these errors and assist with the migration.

4. Add hermione-wdio-migrator to the hermione Config

This plugin "under the hood" simply adds the implementation of old commands using the new API, so during migration, you don't have to update tests yourself. Eventually, you should replace these deprecated commands with new ones in your tests:

module.exports = {
plugins: {
"hermione-wdio-migrator": {
enabled: true,
},

// other hermione plugins...
},

// other hermione settings...
};

5. Remove the Codemod

Uninstall the hermione-codemod package as you won't need it anymore.

npm uninstall hermione-codemod

6. Run Linters

Run linters on the modified tests, as the codemod might have violated your project's coding standards.

7. Run the Tests

Finally, ensure that all tests pass successfully by creating a pull request and verifying that all tests run successfully in CI.

Conclusion

Updating webdriverio brings many useful features that can be used right away, while some will appear in a more convenient form later. Therefore, we highly recommend upgrading to the new version to make writing tests more convenient, faster, and enjoyable.

warning

The old hermione version is in limited support mode, and new features will not appear in it.

Support

If you encounter issues during the upgrade or have any questions, come to github issues — we will definitely help you!