Functional tests extension for BusterJS. Adds helper functions to simulate basic user interactions.
Expects: jQuery to be present on the test target page.
Install
npm install buster-functional --save-dev
Add following snippet to your project's package.json
to allow buster-server
support
proxying without session prefixes.
"scripts":
{
"postinstall": "test ! -d ./node_modules/buster-functional || ./node_modules/buster-functional/bin/install_wrapper"
},
You might need to run npm run-script postinstall
for the first time.
Examples
Config
Just include buster-functional
as extension,
list proxied paths as resources, see Proxy resources.
'Functional tests': environment: 'browser' tests: 'tests/functional/**/*.js' resources: // provide proxy paths, "/" is occupied by buster itself // so provide some alternative, like "/index" path: '/index' backend: 'http://localhost:3030/' path: '/js' backend: 'http://localhost:3030/js' path: '/css' backend: 'http://localhost:3030/css' path: '/api' backend: 'http://localhost:3030/api' extensions: 'buster-functional': timeout: 120 // seconds
.load(uri, [callback])
Loads requested page into iframe.
Note: When page is loaded, references to it's window
, document
and $
are attached to the test's context.
{ // load new app's homepage for each test this;}
.unload([callback])
Cleans up iframe and proxy-cookie, leaving stage clean for the next test.
{ this;}
.touch(selector|element, [callback])
Simulates browser events related to touch, in the right order and with proper pauses.
{ // initially loads as For Sale search type assertclassNamethis0 'backgroundLowlight'; // change tab this;}
.click(selector|element, [callback])
Simulates browser events related to click, in the right order and with proper pauses.
{ // initially loads as For Rent search type assertclassNamethis0 'backgroundLowlight'; // change tab this;}
.type(selector|target, text, [callback])
Simulates user's typing, with all related events and proper timing.
{ thistype'[data-action=searchForm]' 'Palo Al' { // Check first line of autosuggest // should contain "Palo Alto, CA" assert; ; };}
.select(selector|target, option, [callback])
Simulates selecting option within dropdown, with all related events and proper timing.
{ var minPrice = this; this;}
.checkbox(selector|target, [callback])
Simulates tapping checkbox input, with all related events and proper timing.
{ var checkboxElement = this; this;}
.multipleCheckbox(selector|target, [callback])
Simulates tapping of multiple input checkboxes, with all related events and proper timing.
{ var multipleCheckboxElements = this; this;}
.wait(event, callback)
Waits for the application level events ($(document)
by default), if no window.$
is available, waits until it's resolved (via this._eventRoot
).
{ // no property page yet refute; // tap on the property this; // wait for the new page to activate this;}
.waitForTransition(selector|element, callback)
Waits for CSS Transition to finish, triggers provided callback after that.
{ // define target element var target = this; // when menu closed it has position absolute assert; // Toggle menu this; // there is animation delay for sliding in, wait till animation is done this;}
.waitForText(selector|element, text, callback)
Waits for element to show up on the page and contain provided text. Better to use with selectors rather than elements, to allow it to catch newly created elements.
Another autocomplete example, this time much closer to the real life.
{ thistype'[data-action=searchForm]' 'Palo Al' { // need to wait for all the autocomplete requests to be resolved this; };}
.waitForElement(selector, callback)
Waits for element to show up on the page.
{ this;}
.waitForElementToContain(selector|element, callback)
Waits for the element to have some content.
{ this;}
.waitForVar(variable, callback)
Waits for variable to be defined.
// wait for App to be initialized on page load{ // load new homepage for each test this ;}
.enhance(callback)
Provides means to enhance testable environment by enhancing in-iframe window object.
Note: Enhance handler function will called bound to the test object.
{ // load new app's homepage for each test this; this;}
Rendr
For Rendr based application you need to wait for the App
object
to be instantiated, before proceeding to the tests.
Following example shows possible setUp function to use with Rendr-based sites.
{ this; }
PhantomJS
At the moment PhantomJS uses older version of webkit
that doesn't support Function.prototype.bind
.
As workaround you can add es5-shim
to the list of libraries:
'Functional tests': environment: 'browser' libs: // PhantomJS - https://github.com/ariya/phantomjs/issues/10522 'assets/js/vendor/es5-shim.js' tests: 'tests/functional/**/*.js'
And add bind
to the test page loaded in iframe:
{ // load new app's homepage for each test this; this;}
Real Life Example
Functional testing of Trulia Mobile website using Buster.JS
with buster-functional
module in real browsers on mobile devices, including iPhones 6+ and 5S with iOS8/Safari, Androids 4.4 with Stock and Chrome browsers.
TODO
- Integrate resource proxy changes into
buster-server
. - Improve documentation.
License
MIT