Table of Contents
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