JS library for UI testing in the browser
Bromine is a tool for running UI tests in the browser. It provides a simple-to-use flow control mechanism, as well as utilities for executing DOM events.
Bromine was designed to be event based by nature, and relies heavily on Events.js, its syntax and its methods for passing event arguments
Take a look at the demo. You can also take a look at the docs for more details on the API.
While working on automated tests for our eReader, we were finding it harder and harder to write tests for complex scenarios. We tried Selenium, but we found that in order to use it, we had to write a lot of JS code in it's tests, to be able to properly monitor the more complex state changes in our app.
JS developers as we are, we decided to see if we could write a fully usable tool that will let us define our scenarios in readable, scalable, and easy to maintain JS code.
Today, all our automated tests are running using Bromine. We were surprised by the power it gave us, and the level of details we were able to test, and so we decided to open source it, so we could share it with the world.
First - a code example:
var tester = new Bromine.Tester();
var test = tester.registerTest('Example Test',{
init : function(){
this.handle = document.querySelector('handle');
this.target = document.querySelecrot('target');
},
destroy : function(){
this.handle = null;
this.target = null;
},
tests : [
function(){
//in this example, the click will trigger a transition, so we have
//to wait until it's done
Bromine.fireEventWithDelay(this.handle, 'click', this.next);
},
function(){
if (target.classList.contains('hidden')){
this.fail('Target is not visible');
}else{
this.done();
}
}
],
//first method to register events
onStart : function(){
console.log('starting test suite');
}
});
//second method of registering events
test.addEvent('fail', function(e){
console.log('fail');
});
tester.run();
Bromine is composed of 3 basic components:
Bromine.Test
- A test suit, which manages a stack of steps to executeBromine.Tester
- A test runnerBromine.Reporter
- A simple Reporter object for you to extendBromine.fireEvent
and Bromine.fireEventWithDelay
.In the example above, we start by creating a Test-runner. We then register a Test suit on top of it.
Inside the test suite, we use fireEventWithDelay
to execute a 'click' event, and wait before executing the next function in the stack (default is 500ms). The wait is becuase many times we want to wait for a transition or an effect to finish running.
The main method for creating Test suites is by using Bromine.Tester#registerTest. Possible parameters for the Test constructor are:
init
: a function to run when the test is createddestroy
: a function to run when the test is donedescription
: some textual description of the testdepend
: a test name that if fails, will prevent this suit from runningtests
: the actual test stack for this suitfail\_timeout
: how long to wait before reporting a fail (default is 10s). If 0, will not set timeout.In addition, each test fires the following events:
Each function in the test stack has the following methods at it's disposal:
log(obj)
- logs a result into the results stackdone
- finished the test successfullyfail(msg)
- fails the testIn addition, each function has access to 3 methods to contol the flow of the test - prev
, current
, and next
. These can be called and passed around.
The test runner is used to register suites, manage their dependencies, and execute them. It has the following methods:
registerTest(name, options)
registerReporter(reporter)
run()
reset()
And the following events:
The first 3 pass as arguments the test name and the test instance:
tester.addEvent('testDone', function(e){
console.log('test ' + e.name +'passed', e.test.results);
});
The framework supplies a simple reporter for you to use. The reporter can either be extended, or you can override it's callbacks.
Usage:
var reporter = new Bromine.Reporter;
reporter.testStart = function(name, test){};
reporter.testDone = function(name, results, test){};
reporter.testFail = function(name, results, test){};
reporter.done = function(results){};
tester.registerReporter(reporter);
Right now Bromine supplies 2 simple methods for dispatching events on elements:
Bromine.fireEvent(element, type)
- will fire a DOM eveny of type
on element
Bromine.fireEventWithDelay(element, type, callback [,delay])
- will fire a DOM event of type
on element
, then wait delay
ms (default is 500) before dispatching callback
. This is useful when you need to wait for a transition or effect to end before next step.In case you need special event details (such as clientX or e.keyCode), Bromine supplies 2 helper methods:
Parameters can be: x, y, details, button, ctrl, alt, shift, meta, relatedTarget
Parameters can be: ctrl, alt, shift, meta, key, charCode
Note - these methods are not tested on IE, so we cannot gaurentee they will work on IE < 9 (IE9+ will work fine)