Selenium and JavaScript

Applies to CrossBrowserTesting SaaS, last modified on September 13, 2021

Getting started with Selenium and Node.js

Selenium is a great tool to automate our functional tests on websites and web applications in our favorite language. With CrossBrowserTesting, you can use Selenium and JavaScript to run automated browser tests on thousands of real mobile and desktop browsers in the cloud.

Note: You will need a Username and Authkey to run your tests on CrossBrowserTesting To get yours, sign up for a free trial or purchase a plan.

Install Selenium

To get started, make sure you have Selenium’s language bindings for JavaScript installed and ready. You can find the official resource for this here:

http://www.seleniumhq.org/download/

Or if you have NPM loaded on your machine (comes with Node.js distribution), you can type the following into the terminal:

npm install selenium-webdriver

Run your first test

Once you have Selenium-WebDriver in place, you should be ready to start testing. Copy the following script into your text-editor of choice:

"use strict";
var webdriver = require("selenium-webdriver"),
SeleniumServer = require("selenium-webdriver/remote").SeleniumServer;
 
var cbtHub = "http://hub.CrossBrowserTesting:80/wd/hub";

var username ='YOUR_USERNAME'; //replace with your email address
var authkey = 'YOUR_AUTHKEY'; //replace with your authkey

var caps = {
    name : 'Basic Test Example',
    build : '1.0',
    version : '70',
    platform : 'Windows 10',
    screen_resolution : '1366x768',
    record_video : 'true',
    record_network : 'false',
    browserName : 'Chrome',
    username : username,
    password : authkey
};


async function basicExample(){
    try{
        var driver = new webdriver.Builder()
            .usingServer(cbtHub)
            .withCapabilities(caps)
            .build();


        await driver.get('http://crossbrowsertesting.github.io/selenium_example_page.html');

        await driver.getTitle().then(function(title) {
                    console.log("The title is: " + title)
            });

        driver.quit();
    }

    catch(err){
        handleFailure(err, driver)
    }

}

basicExample();

function handleFailure(err, driver) {
     console.error('Something went wrong!\n', err.stack, '\n');
     driver.quit();
}

Choose browsers

To choose your environment, you can select from Browsers, Operating System, Resolutions, and Devices. You can use our easy Selenium Wizard to select your configuration or hit our browser list endpoint.

Record videos

For superior debugging capabilities, CrossBrowserTesting offers the ability to record a video of your Selenium test session. You can find a copy of your test results here.

var caps = {
    'record_video': 'true'
}

Record network

To record the network packets during your test for performance debugging, set the following to "true".

  var caps = {
    'record_network': 'true'
}

Run a local test

With our Local Tunnel, you can run a test on a local URL or behind your company's firewall. There are two different ways to connect the CrossBrowserTesting local tunnel: our Node.js client and our Chrome Extension.

To learn more about setting up, starting, and using your tunnel connection, see About Local Testing.

When a tunnel is open, any automated test can access websites locally, behind a firewall, or across a proxy. There is no need to set a capability during your test.

Run tests in parallel

To speed your automated testing, you can run your tests in parallel, making use of several browsers or devices at one time. To run parallel tests using Node we will use the Flow function.

var username ='YOUR_USERNAME'; //replace with your email address
var authkey = 'YOUR_AUTHKEY'; //replace with your authkey

var webdriver = require('selenium-webdriver'),
    SeleniumServer = require('selenium-webdriver/remote').SeleniumServer,
    request = require('request');

var remoteHub = "http://" + username + ":" + authkey + "@hub.crossbrowsertesting.com:80/wd/hub";

var browsers = [
   { browserName: 'Chrome', platform: 'Windows 10', version: '64', screen_resolution: '1366x768' },
   { browserName: 'Chrome', platform: 'Mac OSX 10.14', version: '71x64', screen_resolution: '1366x768' },
   { browserName: 'Internet Explorer', platform: 'Windows 8.1', version: '11', screen_resolution: '1366x768' }
];

var flows = browsers.map(function(browser) {

    var caps = {
        name : 'Node Parallel Example',
        browserName : browser.browserName,
        version : browser.version,
        platform : browser.platform,
        screen_resolution : browser.screen_resolution,
        username : username,
        password : authkey
    };
    async function parallelExample(){
        try{
            var driver = new webdriver.Builder()
                 .usingServer(remoteHub)
                 .withCapabilities(caps)
                 .build();

            await driver.getSession().then(function(session){
                var sessionId = session.id_; //need for API calls
                console.log('Session ID: ', sessionId);
                console.log('See your test run at: https://app.crossbrowsertesting.com/selenium/' + sessionId)
            });

            await driver.get('http://www.google.com');
            var element = await driver.findElement(webdriver.By.name('q'));
            await element.sendKeys('cross browser testing');
            await element.submit();
            await driver.getTitle().then(function(title) {
                console.log("The title is: " + title);
                if (title !== ('cross browser testing - Google Search')) {
                    throw Error('Unexpected title: ' + title);
                }
            });
            driver.quit();

           
        }
        catch(err){
            console.error('Exception!\n', err.stack, '\n');
            driver.quit();
        }
    }
    parallelExample();
});

Take snapshot

You can take snapshots of errors during your test run for easy debugging and documentation. You can share these snapshots through Jira, Slack, or Email. To take a snapshot during your test run, you just have to invoke our API.

driver.takeSnapshot();

To see how to call the API, read below.

Full example

var username ='YOUR_USERNAME'; //replace with your email address
var authkey = 'YOUR_AUTHKEY'; //replace with your authkey

var webdriver = require('selenium-webdriver');
var SeleniumServer = require('selenium-webdriver/remote').SeleniumServer;
var request = require('request');
var remoteHub = 'http://hub.crossbrowsertesting.com:80/wd/hub';

var caps = {
    name : 'Login Form Example',
    build : '1.0',
    version : '70',
    platform : 'Windows 10',
    screen_resolution : '1366x768',
    record_video : 'true',
    record_network : 'false',
    browserName : 'Chrome',
    username : username,
    password : authkey
};

var sessionId = null;


console.log('Connection to the CrossBrowserTesting remote server');
async function fullExample(){
    try{
    var driver = new webdriver.Builder()
                .usingServer(remoteHub)
                .withCapabilities(caps)
                .build();


    console.log('Waiting on the browser to be launched and the session to start');

    await driver.getSession().then(function(session){
        sessionId = session.id_; //need for API calls
        console.log('Session ID: ', sessionId);
        console.log('See your test run at: https://app.crossbrowsertesting.com/selenium/' + sessionId)
    });

    //load your URL
    await driver.get('http://crossbrowsertesting.github.io/login-form.html');

    //take snapshot via cbt api
    await driver.takeSnapshot();
 
     //find checkout and click it
    await driver.findElement(webdriver.By.id("username")).sendKeys("tester@crossbrowsertesting.com);

    //send keys to element to enter text
    await driver.findElement(webdriver.By.xpath("//*[@type=\"password\"]")).sendKeys("test123");

    //take snapshot via cbt api
    driver.takeSnapshot();

    //click the archive button
    await driver.findElement(webdriver.By.css("button[type=submit]")).click();

    //wait on logged in message
    await driver.wait(webdriver.until.elementLocated(webdriver.By.id("logged-in-message")), 10000);


    //take snapshot via cbt api
    await driver.takeSnapshot();

    //quit the driver
    await driver.quit()

    //set the score as passing
    setScore('pass').then(function(result){
        console.log('SUCCESS! set score to pass')
    });
    }
    catch(e){
        webdriverErrorHandler(e, driver)
    }
   
}

fullExample();


//Call API to set the score
function setScore(score){
    return new Promise((resolve, fulfill)=> {
    var result = { error: false, message: null }

    if (sessionId){
        
        request({
            method: 'PUT',
            uri: 'https://crossbrowsertesting.com/api/v3/selenium/' + sessionId,
            body: {'action': 'set_score', 'score': score },
            json: true
        },
        function(error, response, body) {
            if (error) {
                result.error = true;
                result.message = error;
            }
            else if (response.statusCode !== 200){
                result.error = true;
                result.message = body;
            }
            else{
                result.error = false;
                result.message = 'success';
            }
        })
        .auth(username, authkey);
    }
    else{
        result.error = true;
        result.message = 'Session Id was not defined';
        deferred.fulfill(result);
    }

    
        result.error ? fulfill('Fail') : resolve('Pass');
    });
}

//Call API to get a snapshot
webdriver.WebDriver.prototype.takeSnapshot = function() {

    return new Promise((resolve, fulfill)=> {
        var result = { error: false, message: null }
        
        if (sessionId){
            request.post(
                'https://crossbrowsertesting.com/api/v3/selenium/' + sessionId + '/snapshots',
                function(error, response, body) {
                    if (error) {
                        result.error = true;
                        result.message = error;
                    }
                    else if (response.statusCode !== 200){
                        result.error = true;
                        result.message = body;
                    }
                    else{
                        result.error = false;
                        result.message = 'success';
                    }
                }
            )
            .auth(username,authkey);
            
        }
        else{
            result.error = true;
            result.message = 'Session Id was not defined';
           
        }

            result.error ? fulfill('Fail') : resolve('Pass'); //never call reject as we don't need this to actually stop the test
    });
}

//general error catching function
function webdriverErrorHandler(err, driver){

    console.error('There was an unhandled exception! ' + err.message);

    //if we had a session, end it and mark failed
    if (driver && sessionId){
        driver.quit();
        setScore('fail').then(function(result){
            console.log('FAILURE! set score to fail')
        })
    }
}

Troubleshooting

JavaScript and Selenium bindings and promises

The major difference between Selenium bindings for JavaScript and any other language is that almost every method call in JavaScript is asynchronous. The following code does not work:

var title = driver.getTitle();
console.log(title);

Because, of course, both statements are executed at the same time. WebDriver for JavaScript luckily allows us to use promises so that the steps of our test are executed in the proper sequence. The following code snippet does the same thing the previous version should, but it actually executes correctly:

driver.getTitle().then(function(title) {
console.log(title);
});

Luckily for us, most WebDriver methods in JavaScript will return a then method which takes a callback function for the first argument. In the example here, our first function gets a title, and the callback function receives and makes use of that title.

See Also

CucumberJS

Highlight search results