Introduction

This pro tip will guide you through the steps of implementing an end to end test using CasperJS. Although there's no code specific to Backbone in this tutorial, I do make assumptions on how an app will operate within the context of a Backbone app.

This tutorial is therefore suitable for anyone who would like a 0 - 20 getting started guide to CasperJS.

Who is this written for

This pro tip is written for intermediate and above javascript developers who are comfortable with Backbone, and have some experience with testing frameworks such as Mocha or Jasmine.

Technology

To do this we will use:

PhantomJS - this acts as a browser to run tests in.

CasperJS - built for PhantomJS, this give you some nice utilities for testing such as clicks and logging events.

Step 1 - Install PhantomJS

If you are using NPM.

$ npm install phantomjs -g

Otherwise download here

To test that PhantomJS has installed and is accessible through your terminal:

phantomjs -v

This should return the version number

Write your first PhantomJS hello world test script. Create a "test.js" file with the following:

console.log("Hello PhantomJS");

To run, go to your console and enter the following:

phantomjs test.js

Step 2 - Install CasperJS

If you are using NPM.

$ npm install casperjs -g

Otherwise checkout the installation documentation here.

To test that CasperJS has installed and is accessible through your terminal:

casperjs -version

This should return the version number

Now lets get to grips with CasperJS. Create a new casper_test.js file.

Require and create a new Casper instance

The .create() method will return an instance of the casper class

var Casper = require('casper').create();

To start Casper up, you must use the .start() method to navigate the site and run the casper suit

// casper.start(url, callback); casper.start('http//:google.com', function(){})

Now echo out the title of the current page. You can print out messages in a range of different styles: INFO, ERROR, WARNING, COMMENT

casper.start('http//:google.com', function(){ // this.echo(messageToPrint, style) this.echo(this.getTitle, 'INFO') });

Finally use the run method

casper.run()

The full code is as follows:

var casper = require('casper').create(); casper.start('http://google.com/', function() { this.echo(this.getTitle(), 'INFO'); }); casper.run();

To run this, go to your terminal and enter:

$ casperjs casper_test.js

The console should print out 'Google'

Step 3 - Write a test in CasperJS

The basics

CasperJS has its own handy test runner. Let's begin by writing a quick little script to get used to the boilerplate.

// casper.test.begin(testTitle, numberOfTests, callback) casper.test.begin('Testing Google', 1, function(test){ casper.start('http//:google.com'); casper.then(function(){ test.assertTitle('Google', 'Google has correct title'); }); capser.run(function(){ test.done(); }) });

To run this test, go to terminal and enter:

$ casperjs test google_test.js

So, what's happening here? Firstly you might have noticed we don't require the casper module and instantiate a casper instance. Tests require that we run them using the 'test' command in the terminal. Some kind of ghostly magic ensures that an instance of casper is created for us.

We then use casper.test.begin() passing in 3 arguments. The title of the test, the number of tests expected to run and the callback function. The callback function is where all the business happens. In here we use the .start() method to fire up a site (see above for more info), then we use one of the test methods test .assertTitle() to check the title of the page is what we expect.

In the .run() method we throw in a callback with test.done() to tell CasperJS that we have finished running.

Filling in a form

To fill in a form we use the fill function:

casper.fill('selector', { 'nameOfFormElement' : 'yourInput' }, submit);

Here's some sample code for filling in a simple sign in form:

casper.fill('form#signInForm', { 'username' : 'santa', 'password' : 'presents' }, true);

This will fill out the username with santa and the password with presents. Here, I've set submit to true, so it will submit the form for me.

Sometimes, a Backbone app may do away with submit buttons. To click your own custom submit button, set the last argument in the .fill() method to false and use the .click() method instead.

Sign-In Santa Test

Let's have a look at a test which will log santa in and check that the url has changed to '/user/santa'.

Here we begin our test, naming it 'Sign In Santa' and telling casper to expect 1 test to be run. Then we start up our site, which in this case I'm running locally on port 3000.

casper.test.begin('Sign In Santa', 1, function(test){ casper.start('http://localhost:3000/');

As I'm using Backbone, the site takes some time to parse my script and render the views. Therefore, I make use of the .wait() method. After waiting 500 milliseconds I fill out the form and set the submit option to false.

casper.wait(500, function(){ this.fill('form#signInForm', { 'username' : 'santa', 'password' : 'xmas' }, false); });

Then I click the 'sign In' button.

casper.then(function(){ this.click(".signInBtn"); });

Backbone should re-route to a new URL ('http://localhost:3000/#user/santa'), displaying the users profile page. This will take a little processing time, so I use the .wait() method once more. Now I can test if the URL is what I expect it to be.

casper.wait(500, function(){ test.assertUrlMatch(this.getCurrentUrl(), 'http://localhost:3000/#user/santa'); });

Finally, I run the test.

casper.run(function(){ test.done(); }); });

Here's the full code:

casper.test.begin('Sign In Santa', 1, function(test){ casper.start('http://localhost:3000/'); casper.wait(500, function(){ this.fill('form#signInForm', { 'username' : 'santa', 'password' : 'xmas' }, false); }); casper.then(function(){ this.click(".signInBtn"); }); casper.wait(500, function(){ test.assertUrlMatch(this.getCurrentUrl(), 'http://localhost:3000/#user/santa'); }); casper.run(function(){ test.done(); }); });

The End

You have made it to the end of the tutorial. Congrats!

If you have any suggestions for how I could improve this tutorial, please leave a constructive comment below :)