buster-rendr-functional-tests
Functional tests helper for Rendr-powered sites in BusterJS.
Adds helper functions to simulate basic user interactions.
Requires: BusterJS as peer dependency.
Install
npm install buster-rendr-functional-tests --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-rendr-functional-tests || ./node_modules/buster-rendr-functional-tests/bin/install_wrapper"
},
You might need to run npm run-script postinstall for the first time.
Examples
Config
Just include buster-rendr-functional-tests as extension,
list proxied paths as resources, see Proxy resources.
'Functional tests':
{
environment: 'browser',
tests:
[
'tests/functional/**/*.js'
],
resources:
[
{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:
[
require('buster-rendr-functional-tests')
],
'buster-rendr-functional-tests':
{
timeout: 120
}
}
.load(uri, [callback])
Loads requested page into iframe and waits for the App object to be resolved.
Note: When page is loaded, references to it's window, document, $ and App
are attached to the test's context.
setUp: function(done)
{
this.load('/index').wait('postPageRender', done);
}
.unload([callback])
Cleans up iframe and proxy-cookie, leaving stage clean for the next test.
tearDown: function(done)
{
this.unload(done);
}
.touch(selector|element, [callback])
Simulates browser events related to touch, in the right order and with proper pauses.
'Change search type to for-rent': function(done)
{
assert.className(this.$('#searchTypeTabs>[data-tab=for_sale]')[0], 'backgroundLowlight');
this.touch('#searchTypeTabs>[data-tab=for_rent]', function()
{
assert.className(this.$('#searchTypeTabs>[data-tab=for_rent]')[0], 'backgroundLowlight');
refute.className(this.$('#searchTypeTabs>[data-tab=for_sale]')[0], 'backgroundLowlight');
done();
});
}
.type(selector|target, text, [callback])
Simulates user's typing, with all related events and proper timing.
'Get autocomplete suggestions': function(done)
{
this.type('[data-action=searchForm]', 'Palo Al', function()
{
assert.contains(this.$('[data-role=autosuggest_list]>li:first-child').text(), 'Palo Alto, CA');
done();
});
}
.focus(selector|target)
Makes sure focus event is triggered on the provided element.
Note: .type uses it internally. It's a synchronous function.
'Test': function(done)
{
this.focus('[data-action=searchForm]');
}
.blur(selector|target)
Makes sure blur event is triggered on the provided element.
Note: It's a synchronous function.
'Test': function(done)
{
this.blur('[data-action=searchForm]');
}
.wait([event], callback, [delay])
Waits for the App level events, if no window.App is available,
puts callbacks into queue and continues to check for the App object
every once in a while.
'Go to the property page': function(done)
{
refute.contains(this.$('[data-action=pdpDesc]').text(), 'Home Details');
this.touch('[data-action=property] .propertyPhoto');
this.wait('currentViewActive', function()
{
assert.contains(this.$('[data-action=pdpDesc]').text(), 'Home Details');
done();
});
}
.waitForCss(selector|element, [callback])
Waits for CSS Transition to finish, triggers provided callback after that.
'Open side menu': function(done)
{
var target = this.$('body>[data-view*=side_nav]');
assert.equals(target.css('position'), 'absolute');
this.touch('#navToggle');
this.waitForCss(target, function()
{
assert.equals(target.css('position'), 'fixed');
done();
});
}
.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.
'Get autocomplete suggestions': function(done)
{
this.type('[data-action=searchForm]', 'Palo Al', function()
{
this.waitForText('[data-role=autosuggest_list]>li:first-child b', 'Palo Al', function()
{
assert.contains(this.$('[data-role=autosuggest_list]>li:first-child').text(), 'Palo Alto, CA');
done();
});
});
}
.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.
setUp: function(done)
{
this.load('/index').wait('postPageRender', done);
this.enhance(function(iframeWindow)
{
iframeWindow.console.log = console.log.bind(console);
});
}
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:
[
'assets/js/vendor/es5-shim.js'
],
tests:
[
'tests/functional/**/*.js'
]
}
And add bind to the test page loaded in iframe:
setUp: function(done)
{
this.load('/index').wait('postPageRender', done);
this.enhance(function(iframeWindow)
{
iframeWindow.Function.prototype.bind = Function.prototype.bind;
});
}
TODO
- Add support for desktop events.
- Integrate resource proxy changes into
buster-server.
- Improve documentation.
License
MIT