Using TypeScript Async/Await With Selenium NodeJS Bindings

In previous post I described how I used TypeScript with Babel to get my JavaScript Selenium tests to be executed by Node.

I wanted to dedicate this separate post to an example of the Selenium code that I wrote, because there are many tricks and gotchas that need your full attention.

That’s mainly around the use of async/await of course. Instead of write a paragraph about each piece of the code, I have embedded my points in the code itself.

The sample simply goes to the Angular2 Github repository, and reports the title and date of the first page of open issues in the repository.

<code>// Following `reference` comments allow Node & WebDriver autocomplete.
// This is needed as both are not written in TypeScript.
// You can download them via TypeScript Definitions package manager:
//      npm install tsd -g
//      tsd install node
//      tsd install selenium-webdriver

/// <reference path="typings/node/node.d.ts" />
/// <reference path="typings/selenium-webdriver/selenium-webdriver.d.ts" />

// If you are not using babel-runtime (see prev post), 
//      you can try this instead. You'll still need babel processing.
// This worked in atom-typescript, didn't work in gulp run.
// Not good to have to write it in every file anyway

// The selenium-webdriver offers multiple exports
// Each of them works like namespace
// To use, you need:
//      npm install selenium-webdriver
import * as webdriver from "selenium-webdriver";
import * as chrome from "selenium-webdriver/chrome";

// This is optional good way to manage chromedriver binaries
//      npm install selenium-binaries
// You see I can mix `import` and `require` in same file!
var chromeDriverPath =
process.env.CHROME_DRIVER_PATH = chromeDriverPath;

// Shorten the names we'll use a lot
var By = webdriver.By,
    until = webdriver.until;

// Configure WebDriver. Nothing async yet.
// Could also move into next function no problem.
var driver = new webdriver.Builder()

// You can only use `await` inside an `async` function.
// Hence the IIFE (immediately-invoked function expression) wrapping
(async function() {

    // Some code to ensure browser is closed if I get an error
    // That's trial and error with Selenium, and googling...
    await webdriver.promise.controlFlow().on('uncaughtException',
        async function(e) {
            await driver.quit();
    await process.on('SIGINT', async function() {
        try {
        } finally {
            await driver.quit();

    // I'll store the results here then console log them.
    // I could log them directly, at 1st I didn't know how
    //      and now I'm keeping it to show more cool tips 
    var results = [];

    try {

        // Most WebDriver functions return special promises 
        //      that allow you to call the next function fluently:
        //      `driver.get(...).findElements(...)`
        // But that's not cool for debugging which part failed
        //      & doesn't work with loops, etc.
        // So, I `await` most of the `promise`s.
        await driver.get("");

        var issues = await driver

        // This is worth its own post:
        // When I use `async` function in `map` (to use `await` in it),
        //      I get an array of promises, not results
        // So, I use Promise.all to
        //      get the results in one promise I can `await`
        results = await Promise.all( function(issue) {

            // Could have used `await` here or did it fluently
            // Just showing different styles.
            var titleContainer = issue
            var title = await titleContainer.getText();

            var dateContainer = issue.
            var date = await dateContainer.getAttribute("title");

            return { title: title, date: date };

        // console doesn't get flushed inside `async` functions
        // Surprisingly, I can `await` it to work!
        await console.log(results);

    } finally {
        await driver.quit();

} ()); // As mentioned above, the function executes itself


In case you wonder, here are the packages used above, in a single NPM install command

<code>npm install selenium-webdriver babel selenium-binaries

This doesn’t involve the build configuration to get this compiled and running.

Check out my other post to learn how to setup the build for this.

Finally, I hope those two articles combined help you write your own asynchronous code with ease, with Selenium or any other purpose.

On Selenium, Or, My Choice of Automated UI Testing Frameworks

This morning I got a nice little email from a dear Egyptian friend, Ebeid Soliman (@ebeid_soliman) asking the following:

I know this may be something answered by google, but I trust your opinion.
What is the best free automated UI testing framework/tool you used ? or know ?

I actually already have a long draft on the subject showing the framework I use, and how to get basic stuff working on it, since this one is not yet complete, let me for now share my reply to him with you, as raw as possible …

(I have added some titles to make the long reply more readable)

The Reply


Choosing a framework

Look, I haven’t tried many. Only Watin and Selenium, and even Watin didn’t dig it enough.

The people around me all seem to be using Selenium. This is not only the story though…

Selenium is meant to be cross-browser, while Watin is more of an IE thingy. You should be able to just swap a line of code to change the browser. In reality Selenium works best with Firefox. But this is usually not a problem because usually you don’t use those frameworks to confirm visual look (like screenshots and pixel-by-pixel comparison) or even cross-browser stuff. Usually you use them to ensure on the long run that the system “still” works the way it’s supposed to, the more you develop features and introduce changes, to make sure those didn’t break existing flows (for example, the presence of menu items, going to product page and completing an order, signing up, etc..).


The State of Selenium

Selenium has two current versions, version 1.x, depends on JavaScript interop to the browser. It has a “server” kind of thing (Called Remote Control, RC), that communicates to some Firefox Window it opens, and this window opens another window for running your site, and because it is a child window, the RC browser window controls it via JAvaScript to perform operations (like clicking, going to certain URL), and queries (like checking for existence or value of some HTML element) via JavaScript.

This version is more solid, has so many features, so much coupled with Firefox, runs on Java, but is no-longer in active development.

The more current version of Selenium is called Selenium WebDriver, or Selenium 2.0. This version is meant to be more cross-browser thingy (I have had few issues in minor tries with Chrome), and much faster (official word is 4x in Firefox, although speed doesn’t really matter usually, because you make explicit slowness anyway to simulate user thinking and wait for pages to load, etc..). It uses browser native interfaces to run the tests instead of JavaScript. And you can download it as a Nuget package (not sure whether it still depends on Java).

The problem with this version is that it’s still not as feature-rich as the previous one, you can easily run into limitations and things you can’t do straight forward as in previous version. They try to release new versions very quickly (I think few weeks, like 2 or 4, can’t remember), so, it sure is going to rock, but it’s not still there quite yet.


Real World Requirements

Both of them allow you to run one central server that communicates to client machines if you want for example this server to run your tests in parallel on multiple test machines. At the current customer we have this triggered from a CI server (Cruise) which uses the Selenium library to call the Selenium Grid (Server) and then Selenium (1.3 I guess) connects to client test machines to run our tests. Of course running tests in parallel without affecting each other is another story on its own that is hard to get right as well.

So, we have hundreds of tests (now over 1000)  running on Selenium 1.x with custom stuff (like for example an extension to allow using jQuery selectors to select elements, and custom code to overcome its JS nature to be able to reference the actual site window object instead of the wrong Selenium window itself), but I also know of another colleagues at another client getting good experience with Selenium 2.0 WebDriver. They also found some nice stuff from the community, and, they also wrote their own custom hacks to overcome some of its gotchas.



So, UI automation is not exactly nice or straight when you start doing real stuff (for small tries, you’ll be super amazed, it feels like magic to see the browser windows spin up and click themselves and go the boring steps to re-run some scenario! Generally speaking the least evil is Selenium, because it has the biggest community support, hence google-ability if you may (finding solutions created by others easier and get more stuff done). Although Selenium 2.0 is not as robust as Selenium 1.x, if you are going to use it for a new project, obviously not using Selenium 2.0 will be simply adding technical debt to your test code base, so, go with Selenium 2.0 and see how the journey feels for you, starting by exploring the Nuget packages available for it of course (Just search for Selenium and read package descriptions).

And I am always available if you hit something with it maybe I can help :)


More on Selenium

Since it was the main mention, you can learn more about Selenium from:

Hopefully I review my old draft and see what from it I can add here or make another “code-full” post from. The best help you can give me to do this faster is trying to learn about it, and throwing me some questions that can later turn into blog posts here. There are a lot of posts in this blog that couldn’t have existed without my friends throwing challenges and various queries in my inbox!