Using Selenium Webdriver with Javascript

Introduction Selenium-WebDriver

  • The WebDriverJS library uses a promise manager to ease the pain of working with a purely asynchronous API
  • Rather than writing a long chain of promises allows you to write synchronous code by using a blocking API

Sample using a chain of promises [asynchronous Mode]

const {Builder, By, until} = require('selenium-webdriver');
new Builder()
    .forBrowser('firefox')
    .build()
    .then(driver => {
      return driver.get('http://www.google.com/ncr')
        .then(_ => driver.findElement(By.name('q')).sendKeys('webdriver'))
        .then(_ => driver.findElement(By.name('btnK')).click())
        .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
        .then(_ => driver.quit());
    });

Sample using a chain of promises [synchronous Mode]

const {Builder, By, until} = require('selenium-webdriver');

let driver = new Builder()
    .forBrowser('firefox')
    .build();

driver.get('http://www.google.com/ncr');
driver.findElement(By.name('q')).sendKeys('webdriver');
driver.findElement(By.name('btnK')).click();
driver.wait(until.titleIs('webdriver - Google Search'), 1000);
driver.quit();

Understanding the Promises Chain

Selenium Code:
driver.sleep(4000);                       // Let the chromedriver Browser open for 4 seconds to review results
driver.quit();

Logger Output:
[2018-01-17T09:37:13Z] [WARNING] [promise.ControlFlow] Detected scheduling of an unchained task.
    When the promise manager is disabled, unchained tasks will not wait for
    previously scheduled tasks to finish before starting to execute.
    New task: Task: WebDriver.quit()
        at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
        at thenableWebDriverProxy.quit (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:840:23)
        at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:31:8)
        at Module._compile (module.js:635:30)
        at Object.Module._extensions..js (module.js:646:10)
        at Module.load (module.js:554:32)
        at tryModuleLoad (module.js:497:12)
        at Function.Module._load (module.js:489:3)
        at Function.Module.runMain (module.js:676:10)
        at startup (bootstrap_node.js:187:16)
    Previous task: Task: WebDriver.sleep(4000)
        at ControlFlow.timeout (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\promise.js:2510:17)
        at thenableWebDriverProxy.sleep (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:956:23)
        at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:30:8)
        at Module._compile (module.js:635:30)
        at Object.Module._extensions..js (module.js:646:10)
        at Module.load (module.js:554:32)
        at tryModuleLoad (module.js:497:12)
        at Function.Module._load (module.js:489:3)
        at Function.Module.runMain (module.js:676:10)
        at startup (bootstrap_node.js:187:16)                                                                                                                                                              
  • The Task: WebDriver.quit() is scheduled after WebDriver.sleep(4000);
  • This is called the Promises Chain

Logging with Webdriver-Selenium

Selenium Code: 
var {Builder, By, until, logging } = require('selenium-webdriver');
//
// Enable Logging 
logging.installConsoleHandler();
logging.getLogger('promise.ControlFlow').setLevel(logging.Level.ALL);

Logger Output:
        at Function.Module._load (module.js:489:3)
[2018-01-17T09:37:13Z] [WARNING] [promise.ControlFlow] Detected scheduling of an unchained task.
    When the promise manager is disabled, unchained tasks will not wait for
    previously scheduled tasks to finish before starting to execute.
    New task: Task: WebDriver.getTitle()
        at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
        at thenableWebDriverProxy.getTitle (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:1000:17)
        at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:12:8)
        at Module._compile (module.js:635:30)
        at Object.Module._extensions..js (module.js:646:10)
        at Module.load (module.js:554:32)
        at tryModuleLoad (module.js:497:12)
        at Function.Module._load (module.js:489:3)
        at Function.Module.runMain (module.js:676:10)
        at startup (bootstrap_node.js:187:16)
    Previous task: Task: WebDriver.navigate().to(http://www.google.com/ncr)
        at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
        at Navigation.to (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:1133:25)
        at thenableWebDriverProxy.get (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:988:28)
        at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:11:8)
        at Module._compile (module.js:635:30)
        at Object.Module._extensions..js (module.js:646:10)
        at Module.load (module.js:554:32)
        at tryModuleLoad (module.js:497:12)
        at Function.Module._load (module.js:489:3)
        at Function.Module.runMain (module.js:676:10)

Install Selenium-WebDriver /Chromedriver locally

  • npm install selenium-webdriver@3.6.0
  • npm install chromedriver@2.34.1

Verify Installation

D:\xampp\htdocs\pvdata\testSelenium\test>npm list --depth=0
D:\xampp\htdocs\pvdata\testSelenium\test
+-- chromedriver@2.34.1
`-- selenium-webdriver@3.6.0

Testing a Google Search with Selenium Webdriver

Create a JavaScript file testSelenium.js

require('chromedriver');
var {Builder, By, until, logging } = require('selenium-webdriver');
//
// Enable Logging 
// logging.installConsoleHandler();
//logging.getLogger('promise.ControlFlow').setLevel(logging.Level.ALL);

var  driver = new Builder()
    .forBrowser('chrome')
    .build();
dumpMessage( "--- Script Start ---");

driver.get('http://www.google.com/ncr');
driver.getTitle().then(function (titleName ) {	dumpMessage("Initial Google Page load - Page Title: ---" + titleName + "---" ); });

driver.findElement(By.name('q')).sendKeys('webdriver');            	// Fill in the  Serach String to the 
driver.findElement(By.name('btnK')).click();					   	// Star the Google Searcht 	

var searchTitle = 'webdriver - Google Search';                    	// The New Page Title  
driver.wait(until.titleIs(searchTitle), 10000)						// Wait Google Search List becomes availabe
	.then(function (titleName ) { console.log(getTime() + "Title Element now Visible in DOM ? : " + titleName)});

var xPathElem =  '//*[@id="rso"]/div/div/div[1]/div/div/h3/a';      // xPAth to the  first Item from Google Search Results  
driver.wait(until.elementLocated( { xpath: xPathElem }),20000)      // Wait until Goggle Search Results becomes available 
	.then(function () { dumpMessage("XPath wait finished : Element  Found in DOM - xPath :  " + xPathElem );
		}); 

driver.findElement( { xpath: xPathElem }).click()                   // Click ON the for Search Result   
	.then(function (  ) { dumpMessage("xPath  Element  Found in DOM: Triggering a Click Event on first Element of Google Search List !" );
		});
			
driver.sleep(4000);                                               	// Let the chromedriver Browser open for 4 seconds to review results
driver.quit();                                                    	// Finally Quit the driver 

dumpMessage( "--- Script End ---");                              	// Note as all functions are async wer 

															 		// Helper Functions 							
function dumpMessage(mesg) {                                        // console.log at top level will create a undefined message
	console.log(getTime() + mesg);                                  // Provide a wrapper function which returns some data 
	return "---------------------------------------------------";	
}

function getTime() {
	var ts = new Date();
    return ts.toLocaleTimeString()+ ":" + ts.getMilliseconds() + "  ";
}

Run first Selenium-Webdriver Script: testSelenium.js

D:\xampp\htdocs\pvdata\testSelenium\test> node testSelenium.js

Script Output

D:\xampp\htdocs\pvdata\testSelenium\test> node testSelenium.js
10:40:29:745  --- Script Start ---
10:40:29:745  --- Script End ---

DevTools listening on ws://127.0.0.1:12790/devtools/browser/aa1d4440-591b-45dd-8332-f590848ec58c
10:40:34:359  Initial Google Page load - Page Title: ---Google---
10:40:35:173  Title Element now Visible in DOM ? : true
10:40:35:187  XPath wait finished : Element  Found in DOM - xPath :  //*[@id="rso"]/div/div/div[1]/div/div/h3/a
10:40:36:320  xPath  Element  Found in DOM: Triggering a Click Event on first Element of Google Search List !

Understanding the Script Output

  • The Script end is reached in less then 1ms [ due to the Asyn Mode of Node.js ]
  • All driver calls are scheduled via chains of promises for later execution
  • After about 5 seconds the ChromeDriver is started and initial Google Search Mask gets displayed [ Page Title : Google ]
  • About 1 second later the Google Search List gets displayed [ Page Title: webdriver Google-Search ]
  • Again 1 second later the 1 entry of our Google Search List gets displayed

Reference

Leave a Reply

Your email address will not be published. Required fields are marked *