How to test Chrome Extension under node.js (Javascript)

This is the continuation of my reflection of Week 11 of Makers Academy — and first week of final projects.

We were struggling a lot with the problem above (in the title), and as most of the information we could find in the web was quite confusing, hopefully, my story below will be useful to someone else. (note, that we are very new for programming).

The idea we are working on is to create a Chrome Extension that will help to visually augment google search results, mainly for developers who are constantly browsing web for code-related information. And the idea is to create it in TDD manner.

Prior we have spiked a very simple extension that added a div with a text upfront search results. Text is added after another element on the page is clicked. We have placed this extension inside React app. If you are in similar situation, things you need to consider are (at least this was the way we have done it):

  1. First of all, you need to open browser automatically inside the test
  2. Then you need to make sure that you open this browser with your extension already switched on
  3. And last, you need to test whether the opened page has inside the text you are looking for

To open the browser we used selenium-webdriver. A lot of useful docs about how to use it are in official documentation. To load the extension you need to specify it to ChromeOptions and activate them while you are building your driver (in Capabilities).

var sw = require('selenium-webdriver');
var chromeOptions = sw.Capabilities.chrome();
chromeOptions.set("chromeOptions", {"args": ['--load-extension='+"/Users/KateLoschinina/Workspace/MakersAcademy/app-name"]});
var driver = new sw.Builder()
.forBrowser('chrome')
.withCapabilities(chromeOptions)
.build();

To operate with the driver — it is important to understand the concept of promises —each time you call driver action, it returns promise rather than element. You can access element with then function. E.g.

console.log(driver.findElement(sw.By.id('element-id')) // returns a promise
driver.findElement(sw.By.id('element-id')).then(function(c){
console.log(c)
}) // returns an element

The test will be completed only when the done() action completes it (and it is indicated as an argument of the test on line 3).

We used chai literally for one line of code — to check whether our div was found and was not NULL. And we used setTimeout() to make sure our app has enough time to run through all the loading.

And this is .test.js file that worked for us:

jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; // you might need it as it takes sometime to load page
it('Extention: add text to the google search results',  (done)=> {
var sw = require('selenium-webdriver');
var assert = require('chai').assert;
var chromeOptions = sw.Capabilities.chrome();
chromeOptions.set("chromeOptions", {"args": ['--load-extension='+"/Users/KateLoschinina/Workspace/MakersAcademy/app-name"]});
var driver = new sw.Builder()
.forBrowser('chrome')
.withCapabilities(chromeOptions)
.build();
driver.get('https://www.google.co.uk/#q=search&*')
.then(function(){
driver.findElement(sw.By.id('searchform'))
.then(function(a) {
setTimeout(function() {
a.click().then(function() {
driver.findElement(sw.By.id('stack'))
.then(function(c){
c.getText()
.then(function(d){
assert.inNotNull(d,'Awesome');
done();
})
done();
})
done();
})
.catch(function() {
done();
})
}, 5000)
})
})
})

Code above is still raw and require refactoring, but I guess it covers the main idea, and — the most important — it is working!