Fluent api built to create acceptance tests.
It is based on selenium-webdriver and execute every tasks in the control flows.
More info https://code.google.com/p/selenium/wiki/WebDriverJs#Control_Flows
It is also using chai utils method which allows to add chainable methods or properties.
https://github.com/chaijs/chai/tree/master/lib/chai/utils
The /runner class builds the client api and start a local selenium webserver in child process. Configuration properties available in /config.properties All this properties are overridable by passing an object options in the Runner constructor.
- selenium-server-standalone-2.40.0.jar - http://docs.seleniumhq.org/download/
- chromedriver.exe - https://code.google.com/p/selenium/wiki/ChromeDriver
- phantomjs.exe - http://phantomjs.org/download.html
The Runner object allows to configure the selenium server and the selenium webdriver used behind the client api.
var conf = {
"browser" : "chrome"
, "seleniumJarPath": "c:\\...\\resources\\selenium-server-standalone-2.40.0.jar"
, "phantomExecutable": "c:\\...\\resources\\phantomjs.exe"
, "screenshotFailedTest": true
};
require("am-webdriver/runner").setConfig(conf);
Get a singleton instance of the client object
var client = require("am-webdriver").client;
You can get a singleton instance
var factory = require("am-webdriver").factory;
var client = factory.getInstance();
//OR
var client = factory.getClient();
You can also get a new instance. Please note that you will need to reinstall your custom commands...
var factory = require("am-webdriver").factory;
var client = factory.newInstance();
//OR
var client = factory.newClient();
trigger the click event on an element. ie.
client.click(".my-css-selector")
client.element(".my-css-selector").click()
Search for argument text on the page and trigger a click on the element containing it
client.clickText("homepage")
close the driver and the browser window
client.close()
find and select the first element matching the selector
client.element("my-selector")
Alias: attr Get the attribute value of a pre selected element
client.element("my-selector").attribute("style")
trigger the mouseover event on an element
client.element(".button-ok").hover();
find a collection of elements matching the selector Used in combination with the index command, first or last property
client.elements("my-selector")
client.elements("my-grid-rows").index(0)
client.elements("my-grid-rows").first
select the element n of a pre selected collection of element
client.elements("my-grid-rows").index(0)
open a url in the browser
client.open("http://google.com")
Alias: pause(n) pause the driver process for n ms
client.sleep(1000)
triggers a special key press, ENTER TAB CTRL... to test keyboard navigation
client.pressKey("TAB")
search for a collection of element within one element.
client.element("my-grid-container").find(".row")
search for a sub element within one element.
client.element("my-grid-container").select(".row:first")
####selectText(...) search for a sub element by its content text within one element.
client.element("button").selectText("Cancel")
execute a custom callback in the flow
client.then(breakStreamingConnection)
type a text within an input field
client.element("input.description").type("am-webdriver is cool!")
pause the control flow until the css selector is found, and timeout if not found.
client.open("http://google.com").wait("input.search", 10000)
take a screenshot of the current page
client.open("http://google.com").screenshot()
pre load a window property that may be used in assertion
Alias: contain, include Check is the pre stated property include the exected value
client.element("input").cssClass.contains("error");
Check is the pre stated property strictly equal the expected value
client.element("title").text.equal("Hello World!");
Check is the pre stated property is below n (operator used is <)
client.elements("li").length.should.be.below(10);
Check is the pre stated property is above n (operator used is >)
client.elements("li").length.should.be.above(10);
Check is the pre stated property is at least n (operator used is >=)
client.elements("li").length.should.be.at.least(1);
Check is the pre stated property is at most n (operator used is <=)
client.elements("li").length.should.be.at.most(10);
Check is the pre stated property starts with string
client.element("title").text.should.startWith("Hello");
Check is the pre stated property ends with string
client.element("title").text.should.endWith("World!");
Returns the currently focused element, that is, the element that will get keystroke events if the user types any.
client.activeElement.cssClass.should.contain("field-whatever");
Select the parent element of the pre selected element
client.element("li:first").parent.cssClass.should.contain("list-wrapper");
Returns the class attribute value of an element
client.element(".title").cssClass.should.equal("title and whatever-other-class applied-on-the-element");
Returns true if the element is enabled and false if not
client.element(".disabled-field").isEnabled.should.equal(false);
Returns the pre selected element
client.element("div.that-listen-to-change")
//to access it via a property, you shouldn't need to use this property
client.inspectedElement
Returns the first element of a pre selected collection of element
client.elements("li").first.text.should.equal("first item");
Returns the last element of a pre selected collection of element
client.elements("li").first.text.should.equal("first item");
Returns the number of elements of the pre selected collection of element
client.elements("li").length.should.equal(3);
Returns the content of an element
client.element(".title").text.should.equal("Hello World!");
Returns the value of the value attribute of an element
client.element("option").value.should.equal("0");
Returns the title of the opened window
client.open("http://google.com").title.should.equal("Google");
Reverts the assertion. So for example, these 2 statements are equivalent
client.elements("li").length.should.be.at.least(10);
client.elements("li").length.should.not.be.below(10);
These are just linking words to make the api more fluent and does not execute any code in the background. Thus these 2 statements are equivalent.
client.elements("li").length.should.not.be.below(10);
client.elements("li").length.not.below(10);
Add a chainable function to the client object.
client.addCommand("login", function(username, password){
return page.open("http://whatever.com/login")
.wait('input.login')
.type(username)
.pressKey("TAB")
.type(password)
.click(".btn-submit");
});
now you can use login as any other commands in your api client.login("admin", "password") .open("/admin") ...
** Do not forget to return the object **
names: Array of aliases or string fn: function that will be executed when the property is accessed
This method is used by the builder class to add all the properties in the client object. The fn function will be executed in the control flow and the 'this' object binded to the client object. So it gives you access to the following properties.
- this._driver: the native selenium driver
- this._flow: The webdriver.promise.controlFlow() - More info https://code.google.com/p/selenium/wiki/WebDriverJs#Control_Flows
- this._flag: the chai/lib/chai/utils.flag object which allows to keep in memory properties. This object is used to compare values in every assertion statements
This is a core client api method which should be used wisely. It is recommended that you use 'addCommand' to extend the API
client.addProperty("length", function(){
if(!this._flag("elements"))
return 0;
var value = this._flag("elements").length;
this._flag("actual", value);
return value;
});
names: Array of aliases or string fn: function that will be executed when the method is invoked
This method is used by the builder class to add all the commands in the client object. The fn function will be executed in the control flow and the 'this' object is binded to the client object. See add properties for more details.
This is a core client api method which should be used wisely. It is recommended that you use 'addCommand' to extend the API
client.addChainableMethod(["element", "findFirstElement"], function(cssSelector){
var that = this;
return this._driver.findElement(By.css(cssSelector)).then(function(el){
that._flag("element", el);
return el;
});
}
Choose your favourite test runner. Jasmine, mocha...
Then you can chain your api calls as much as you like.
it("list should allow selection with tab", function(done){
page.activeElement.type("GBP")
.pressKey("tab")
.cssClass.should.contains("btn-swap")
.and.element("[ccy-pair-input]").value.should.equal("GBPAED")
.then(done);
});
-
Integrate it with BrowserStack
-
Write Unit Tests