Selenium testing without nested callbacks or promises!
Selenium testing without nested callbacks or promises!
webdriver-sync wraps the Java
WebDriver API in a synchronous way allowing your
tests to be very concise. You can avoid the intricacies of
async ceremony by using it.
browserget""browsertitleassertok~titleindexOf'foo title' 'Wrong title!';browserelementById'i am a link'browserclickElementelbrowsereval"window.location.href"assertok~hrefindexOf'foo title 2';browserquit;;;;;;
Completely synchronous API! No promises or callbacks needed.
driverget"";title = drivergetTitle;link = driverfindElementByid'i am a link';linkclick;assertdrivergetCurrentUrlindexOf'foo title 2' > -1;titleshouldequal'foo title';console.logtitle;driverquit;
- Run Chrome, Firefox, Safari, PhantomJS, Internet Explorer, and RemoteWebDriver (Android to come)!
- Reduce code by embracing a synchronous API!
- Reduce verbosity found in statically typed langs like java and c#
- Dependency management for 3rd party binaries I.E. chromedriver and selenium-server-standalone-x.x.x.jar.
- Always up to date binary dependencies when you update your version of
- Run your automated tests against your app much faster on
- Connect to Sauce using the RemoteWebDriver or other drivers that extend RemoteWebDriver.
##Instantiating Drivers Here are a few examples on how you can instantiate drivers for testing: ###InternetExplorerDriver
var wd = require'webdriver-sync';var IEDriver = wdInternetExplorerDriver;var driver = ;driverget'';
var wd = require'webdriver-sync';var PhantomJSDriver = wdPhantomJSDriver;var driver = ;driverget'';
var wd = require'webdriver-sync';var FirefoxDriver = wdFirefoxDriver;var driver = ;driverget'';
###ChromeDriver There are 2 ways to run Chrome.
The straightforward way is slower as it has to start chromedriver each time it's instantiated:
var wd = require'webdriver-sync';var ChromeDriver = wdChromeDriver;var driver = ;driverget'';
This way uses a service and is much faster overall, but requires more setup. You'd likely want to wrap this in a module with a getter for a new driver when you need one:
var wd = require'webdriver-sync';var ChromeDriverService = wdChromeDriverService;var ChromeDriver = wdChromeDriver;var service =usingAnyFreePortusingDriverExecutablefindsChromeDriverfindbuild;var driver = service;driverget'';
##Dealing with arrays and data
webdriver-sync allows you to treat data as you normally would. For Arrays, you've got all the methods
you would expect:
Here we execute an async script, return a collection of divs, and console.log the inner text of each div. Notice that our control flow with other assertions are not affected in any way:
it'can do really cool stuff!'var numberOfElements = 0;driverexecuteAsyncScript"var cb = arguments[arguments.length-1]; cb(document.querySelectorAll('div'));"forEachnumberOfElements++;console.logelgetText;;assertnumberOfElements 'We got here!';;
See more tests for
wait utility method pauses execution until some arbitrary condition is met. Provide a function and
webdriver-sync will invoke the function repeatedly until it returns a truthy value. You may optionally specify millisecond values for a
timeout (how long to wait before considering the operation failed and throwing an error) and a
period (how long to wait between invocations of the provided function).
driverfindElementwebdriverBycssSelector'button'click;driverwaitreturn driverfindElementswebdriverBycssSelector'.thumbnail'length > 0;timeout: 1000 period: 100 ;
webdriver-sync's goal is to wrap the Java API and make selenium binary management simpler overall. Any other functionality or feature should be addressed in 3rd party modules.
Here is a list of 3rd party modules and why you'd want to use them:
- selenium-global. This module enables you to add
webdriver-syncwrappings globally before running your tests. If you prefer to avoid
var wd = require('webdriver-sync');in each of your tests then you can use this.
- selenium-binaries. This module handles selenium binary management.
webdriver-sync leverages node-java to wrap the java API provided by the Selenium project which is by far the best supported of them all. Wrappings are located under
src/. In most cases, methods proxy through to their java equivalent.
You can view
webdriver-sync's API here. You can directly instantiate any of the classes directly. Interfaces are returnes by various methods and are usually not worth calling directly, but they're useful for verifying the type of returned data.
node-java requires that you're able to compile node add ons. The install can be a bit tricky depending on your environment. Here are some general guidelines when installing
- Ensure that your environment is setup to compile node add ons. A good module to use in verifying that you can compile node addons is microtime.
- You'll need a minimum JDK version of
1.7installed on your system.
npm install webdriver-syncIf you run into issues feel free to reach out!
chromedriverfor you which makes your life easier.
Binaries will be downloaded to one of the following locations (listed in order of precedence):
- A directory defined by env var
/lib/webdriver-syncif running as
rooton *nix systems
You can further override the download location for binaries as follows:
- Chromdriver - Place
chromedriver.exe(for windows) on your path.
- Selenium jar - Set
SELENIUM_SERVER_STANDALONE_JARin your env and have it point to the location where you have it on disk. You should never do this, as the API is only tested against specific versions of selenium, but it is available.
webdriver-sync is a wrapper around the java API, you can browse any of the
javadocs online. You can quite literally use this module the same way you
would in java without the static typing.
Here are some links:
webdriver-sync disables any output from the selenium java bindings. To
change this behavior, you can set either of the following env vars to any non-empty
You can run Chrome, Firefox, Safari, and PhantomJS headless with
You must have
Xvfb installed, or an equivalent.
Here's how Chromdriver can be run headless:
#Run this on a ttyexport DISPLAY=:99Xvfb :99 -ac -screen 0 1280x1024x32> /dev/null &npm test
//Use this in your tests for ChromeDriverServicevar service =usingAnyFreePortusingDriverExecutablefindsChromeDriverfindwithEnvironment"DISPLAY":":99.0"build;var driver = service;//Running Headless!
webdriver-syncis synchronous, you can't
driver.get()a server you've started in the same process (thanks to @jugglinmike for discovering this!) I.E.
var driver = new require'webdriver-sync'ChromeDriver;require'http'createServerresend'This is never reached!';listen'localhost';driverget'';//This never completes.
The MIT License (MIT)Copyright (c) 2013 Joseph SpencerPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.
Special thanks to the developers of node-java!!!
###Contributors (listed chronologically).
Anyone who contributes to webdriver-sync, either through code changes or testing will be listed here when their efforts are significant:
- Justin Searls @searls
- Campbell Morgan @campbellwmorgan
- Nick Tulett @NickTulett
- Andrew Nichols @tandrewnichols
- jugglinmike @jugglinmike