Promise manager
Before async/await, the only way to use WebDriverJS was through its promise manager.
The example below performs a Google search:
// promise-manager.js
const { Builder, By, Key, until } = require('selenium-webdriver');
// initializes chrome browser
const driver = new Builder().forBrowser('chrome').build();
// navigates to Google and then prints title
driver.get('https://www.google.com/');
driver.getTitle().then((title) => console.log('getTitle:', title));
// enters `webdriver` in search input and then presses Enter key
driver.findElement(By.name('q')).sendKeys('webdriver', Key.ENTER);
// waits up to 1 second for title to change and then prints title
driver.wait(until.titleContains('webdriver'), 1000);
driver.getTitle().then((title) => console.log('getTitle:', title));
// closes browser
driver.quit();
As you can tell, the promise manager makes an asynchronous API look somewhat synchronous.
Async/await
With Node.js 8+, we can now use the async/await syntax.
The following refactors our example to async/await:
// async-await.js
const { Builder, By, Key, promise, until } = require('selenium-webdriver');
// disable promise manager
promise.USE_PROMISE_MANAGER = false;
// wrap in async function
async function run() {
let driver;
// use try-catch-finally
try {
// we need to `await` for the promise to finish
driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.google.com/');
// the resolved value can be saved to a variable
const title = await driver.getTitle();
console.log('getTitle:', title);
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.ENTER);
await driver.wait(until.titleContains('webdriver'), 1000);
// `await` can be used inside `console.log`
console.log('getTitle:', await driver.getTitle());
} catch (error) {
// when a promise is rejected
console.error(error);
} finally {
// executes after `try` or `catch`
await driver.quit();
}
}
// call async function
run();
The main thing to notice is that our code is wrapped inside an async function. This allows us to utilize try-catch-finally.
Overall, the code looks much cleaner and less complex.
Another thing to note is that we had to disable the promise manager:
const { promise } = require('selenium-webdriver');
promise.USE_PROMISE_MANAGER = false;
Alternatively, it can be disabled by setting the environment variable:
SELENIUM_PROMISE_MANAGER=0
Which means we can do the following before running the script:
SELENIUM_PROMISE_MANAGER=0 node async-await.js
Addendum
You can find all code examples (as well as others), in my webdriverjs-recipes repository.