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