Sync mode vs async
How to enable/disable sync mode
To enable sync mode it's only required to install @wdio/sync
package, to disable sync mode uninstall @wdio/sync
.
Async mode
Every browser/element function call returns a Promise and needs to be awaited to get result.
Example
describe('suite async', () => {
it('test', async () => { // pay attention to `async` keyword
const el = await $('body') // note `await` keyword
await el.click()
await browser.pause(500)
console.log(browser.capabilities) // static properties should not be awaited
await $('body').click() // WON'T WORK! You can't chain functions like this.
})
})
Common issues in async mode
await $('body').click()
throws $(...).click is not a function
because the element was not awaited. To fix this, first await element then trigger the click, like so:
const el = await $('body')
await el.click()
- previous command was not awaited:
const el = await $('body')
el.waitForExist() // ERROR: await is missing here, you'll get `Unhandled promise rejection`.
await el.click()
Sync mode
If you're using @wdio/sync
then you can avoid awaiting for browser/element calls. It is still required to deal with Promises from 3rd-party libraries, you should use browser.call for this.
Example
// 3rd-party library example
// https://www.npmjs.com/package/got#gotgeturl-options
const { get } = require('got')
describe('suite sync', () => {
it('test sync',
// make sure to remove `async` keyword otherwise function treated as async
// and you have to await every browser call.
// The same is applicable to hooks in `wdio.conf.js` as well.
() => {
browser.pause(500)
// wrap 3rd-party library calls with `browser.call`
const response = browser.call(() => get('https://cat-fact.herokuapp.com/facts/'))
$('body').click() // You can chain functions in sync mode
})
it('using async function in sync mode',
// If you have `@wdio/sync` installed and configured, it is still possible to use async functions.
// However, in such case you have to await every browser/element call like in async mode, and this can
// be confusing when other tests are sync, so we discourage mixing modes, but it is possible to do so.
// The best practice in sync mode is to wrap anything async with `browser.call`.
async () => {
await browser.pause(500)
const response = await get('https://cat-fact.herokuapp.com/facts/')
const el = await $('body')
await el.click()
})
})
How does sync mode work?
Every browser/element command is wrapped with fibers while in sync mode.
Common issues in sync mode
- declaring test function as
async
and not awaiting browser/element functions - not awaiting 3rd-party library promises with
browser.call
- using sync mode while
@wdio/sync
package is not installed fibers
failed to install properly. There might be some issues withnode-gyp
or you have unsupported NodeJS version. Seenpm install
errors for more details