How to Use ES6 Generators to Simplify Your Node.js Selenium Webdriver Scripts

For a couple weeks, I have been using cucumber.js and selenium webdriver for acceptance testing.

For the most part, I’ve been very happy with tools. However, the pervasent use of promises in selenium webdriver annoys me.

For example, consider the following script that opens up a login page, and tests that you can successfully login.

I personally don’t like the 2 levels of indirection from using promises. 

Further, the number of promises will scale with each page you visit.

This leads to very painful reading.

Just recently, I found a way to increase the understandability of selenium webdriver based scripts using es6 generators.

Since node.js does not support es6 yet, you will have to use the babel-node executable to make it work. You can installing babel-node with the following script from the command line:

The following code does the exact same thing as the previous script, but instead uses es6.

The code uses lazy evaluation to stop and continue execution of the script. If you are familiar with functional languages like scala, clojure, or haskell then this type of approach should be second nature to you.

I will give you a high level overview of what is happening:

Step 1: We define a generator function called main.

Step 2: In main, we explicitly tell it to stop execution at two locations. We signal to the javascript engine to stop execution using the keyword yield.

Step 3: We instantiate main and assign the instance to the variable m. The javascript engine will execute the function and stop execution at the first yield statement.

However, after it stops execution, it will call the function visitLoginPage.

Step 4: visitLoginPage will use the variable m to get a reference to the main function, and either tell it to continue or to throw and exception.

Step 5: The main function will continue executing until it reaches the second yield statement.

The javascript engine will stop execution of the function, and it will call the function getUrl.

Step 6: getUrl will continue execution and return a value that we store in currentUrl in the main function.

Now we can print the url to the console.

Conclusion

I’m sure that there are ways alternative ways to simplify selenium webdriver scripts.

I’m not saying that this is the best way. It is just something that I personally like, and I hope that it helps you.

Advertisements