Fork me on GitHub

CasperJS is an open source navigation scripting & testing utility written in Javascript and based on PhantomJS — the scriptable headless WebKit engine. It eases the process of defining a full navigation scenario and provides useful high-level functions, methods & syntactic sugar for doing common tasks such as:

  • defining & ordering browsing navigation steps
  • filling & submitting forms
  • clicking & following links
  • capturing screenshots of a page (or part of it)
  • making assertions on remote DOM
  • logging events
  • downloading resources, including binary ones
  • writing functional test suites, saving results as JUnit XML
  • scraping Web contents
In case you haven’t seen CasperJS yet, go and take a look, it’s an extremely useful companion to PhantomJS. Ariya Hidayat, creator of PhantomJS

PhantomJS >= 1.3 must be installed (1.5.0 highly recommended). Check out PhantomJS' installation instructions, and:

  • Ensure to always install the latest available version of PhantomJS, and prefer static builds over other package installation methods

  • Ubuntu users Double check the version of PhantomJS provided by your apt repository. Often, only PhantomJS 1.2 is provided.

Once PhantomJS's installed on your machine, you should obtain something like this:

$ phantomjs --version
1.5.0

Now just follow these instructions:

$ git clone git://github.com/n1k0/casperjs.git
$ cd casperjs
$ git checkout tags/0.6.6
$ ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs

So now you should get something like this:

$ casperjs --version
0.6.6

You are now ready to write your first script!

Note The casperjs executable is written in Python, so you can also run it using the python command:

$ python /path/to/casperjs/bin/casperjs
CasperJS version 0.6.6 at /Users/niko/casperjs
Usage: casperjs script.(js|coffee) [options...]
Read the docs http://casperjs.org/

Note If for some reason you don't have access to Python, please check this FAQ entry.

In the following example, we'll query google for two terms consecutively, "capserjs" and "phantomjs", aggregate the result links in a standard Array and output the result to the console.

Fire up your favorite editor and save the javascript code below in a googlelinks.js file:

var links = [];
var casper = require('casper').create();

function getLinks() {
    var links = document.querySelectorAll('h3.r a');
    return Array.prototype.map.call(links, function(e) {
        return e.getAttribute('href')
    });
}

casper.start('http://google.fr/', function() {
    // search for 'casperjs' from google form
    this.fill('form[action="/search"]', { q: 'casperjs' }, true);
});

casper.then(function() {
    // aggregate results for the 'casperjs' search
    links = this.evaluate(getLinks);
    // now search for 'phantomjs' by filling the form again
    this.fill('form[action="/search"]', { q: 'phantomjs' }, true);
});

casper.then(function() {
    // aggregate results for the 'phantomjs' search
    links = links.concat(this.evaluate(getLinks));
});

casper.run(function() {
    // echo results in some pretty fashion
    this.echo(links.length + ' links found:');
    this.echo(' - ' + links.join('\n - ')).exit();
});

Run it:

$ casperjs googlelinks.js
20 links found:
 - https://github.com/n1k0/casperjs
 - https://github.com/n1k0/casperjs/issues/2
 - https://github.com/n1k0/casperjs/tree/master/samples
 - https://github.com/n1k0/casperjs/commits/master/
 - http://www.facebook.com/people/Casper-Js/100000337260665
 - http://www.facebook.com/public/Casper-Js
 - http://hashtags.org/tag/CasperJS/
 - http://www.zerotohundred.com/newforums/members/casper-js.html
 - http://www.yellowpages.com/casper-wy/j-s-enterprises
 - http://local.trib.com/casper+wy/j+s+chinese+restaurant.zq.html
 - http://www.phantomjs.org/
 - http://code.google.com/p/phantomjs/
 - http://code.google.com/p/phantomjs/wiki/QuickStart
 - http://svay.com/blog/index/post/2011/08/31/Paris-JS-10-%3A-Introduction-%C3%A0-PhantomJS
 - https://github.com/ariya/phantomjs
 - http://dailyjs.com/2011/01/28/phantoms/
 - http://css.dzone.com/articles/phantom-js-alternative
 - http://pilvee.com/blog/tag/phantom-js/
 - http://ariya.blogspot.com/2011/01/phantomjs-minimalistic-headless-webkit.html
 - http://www.readwriteweb.com/hack/2011/03/phantomjs-the-power-of-webkit.php

CoffeeScript

You can also write Casper scripts using the CoffeeScript syntax:

getLinks = ->
  links = document.querySelectorAll "h3.r a"
  Array::map.call links, (e) -> e.getAttribute "href"

links = []
casper = require('casper').create()

casper.start "http://google.fr/", ->
  # search for 'casperjs' from google form
  @fill "form[action='/search']", q: "casperjs", true

casper.then ->
  # aggregate results for the 'casperjs' search
  links = @evaluate getLinks
  # search for 'phantomjs' from google form
  @fill "form[action='/search']", q: "phantomjs", true

casper.then ->
  # concat results for the 'phantomjs' search
  links = links.concat @evaluate(getLinks)

casper.run ->
  # display results
  @echo links.length + " links found:"
  @echo(" - " + links.join("\n - ")).exit()

Just remember to suffix your script with the .coffeeextension.

Casper source code is quite heavily documented using jsdoc, but below you'll find the whole API documentation with sample code.

The Casper class

The most easiest way to instantiate a casper instance is to use the module create() method:

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

But you can also retrieve the main Function and instantiate it by yourself:

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

Casper([Object options])

Both the Casper constructor and the create() function accept a single options argument which is a standard javascript object:

var casper = require('casper').create({
    loadImages: false,
    loadPlugins: false
});

Casper options

All the available options are detailed below:

Name Type Default Description
clientScripts Array [] A collection of script filepaths to include to every page loaded
faultTolerant Boolean true Catch and log exceptions when executing steps in a non-blocking fashion
httpStatusHandlers Object {} A javascript Object containing functions to call when a requested resource has a given HTTP status code. A dedicated sample is provided as an example.
logLevel String "error" Logging level (see the logging section for more information)
onAlert Function null A function to be called when a javascript alert() is triggered
onDie Function null A function to be called when Casper#die() is called
onError Function null A function to be called when an "error" level event occurs
onLoadError Function null A function to be called when a requested resource cannot be loaded
onPageInitialized Function null A function to be called after WebPage instance has been initialized
onResourceReceived Function null Proxy method for PhantomJS' WebPage#onResourceReceived() callback, but the current Casper instance is passed as first argument.
onResourceRequested Function null Proxy method for PhantomJS' WebPage#onResourceRequested() callback, but the current Casper instance is passed as first argument.
onStepComplete Function null A function to be executed when a step function execution is finished.
onStepTimeout Function null A function to be executed when a step function execution time exceeds the value of the stepTimeout option, if any has been set.
onTimeout Function null A function to be executed when script execution time exceeds the value of the timeout option, if any has been set.
page WebPage null An existing WebPage instance
pageSettings Object {}

PhantomJS's WebPage settings object. Available settings are:

  • javascriptEnabled defines whether to execute the script in the page or not (default to true)
  • loadImages defines whether to load the inlined images or not
  • loadPlugins defines whether to load NPAPI plugins (Flash, Silverlight, ...) or not
  • localToRemoteUrlAccessEnabled defines whether local resource (e.g. from file) can access remote URLs or not (default to false)
  • userAgent defines the user agent sent to server when the web page requests resources.
  • userName sets the user name used for HTTP authentication
  • password sets the password used for HTTP authentication
  • XSSAuditingEnabled defines whether load requests should be monitored for cross-site scripting attempts (default to false)
stepTimeout Number null Max step timeout in milliseconds; when set, every defined step function will have to execute before this timeout value has been reached. You can define the onStepTimeout() callback to catch such a case. By default, the script will die() with an error message.
timeout Number null Max timeout in milliseconds
verbose Boolean false Realtime output of log messages
viewportSize Object null Viewport size, eg. {width: 800, height: 600}

Example:

var casper = require('casper').create({
    clientScripts:  [
        'includes/jquery.js',      // These two scripts will be injected in remote
        'includes/underscore.js'   // DOM on every request
    ],
    logLevel: "info",              // Only "info" level messages will be logged
    onError: function(self, m) {   // Any "error" level message will be written
        console.log('FATAL:' + m); // on the console output and PhantomJS will
        self.exit();               // terminate
    },
    pageSettings: {
        loadImages:  false,        // The WebPage instance used by Casper will
        loadPlugins: false         // use these settings
    }
});

But no worry, usually you'll just need to instantiate Casper using require('casper').create().

Casper#back()

Moves back a step in browser's history.

casper.start('http://foo.bar/1')
casper.thenOpen('http://foo.bar/2');
casper.thenOpen('http://foo.bar/3');
casper.back();
casper.run(function() {
    console.log(this.getCurrentUrl()); // 'http://foo.bar/2'
});

Also have a look at Casper.forward().

Casper#base64encode(String url [, String method, Object data])

Encodes a resource using the base64 algorithm synchronously using client-side XMLHttpRequest.

Note We cannot use window.btoa() because it fails miserably in the version of WebKit shipping with PhantomJS.

Example: retrieving google logo image encoded in base64:

var base64logo = null;
casper.start('http://www.google.fr/', function() {
    base64logo = this.base64encode('http://www.google.fr/images/srpr/logo3w.png');
});

casper.run(function() {
    this.echo(base64logo).exit();
});

You can also perform an HTTP POST request to retrieve the contents to encode:

var base46contents = null;
casper.start('http://domain.tld/download.html', function() {
    base46contents = this.base64encode('http://domain.tld/', 'POST', {
        param1: 'foo',
        param2: 'bar'
    });
});
casper.run(function() {
    this.echo(base46contents).exit();
});

Casper#click(String selector)

Performs a click on the element matching the provided CSS3 selector. The method tries two strategies sequentially:

  1. trying to trigger a MouseEvent in Javascript
  2. using native QtWebKit event if the previous attempt failed

Example:

casper.start('http://google.fr/');

casper.thenEvaluate(function(term) {
    document.querySelector('input[name="q"]').setAttribute('value', term);
    document.querySelector('form[name="f"]').submit();
}, { term: 'CasperJS' });

casper.then(function() {
    // Click on 1st result link
    this.click('h3.r a');
});

casper.then(function() {
    console.log('clicked ok, new location is ' + this.getCurrentUrl());
});

casper.run();

Hint If you want the mouse to click a given point within the viewport area, you can use the mouse property of the Casper instance:

casper.then(function() {
    this.mouse.click(150, 200);
});

Casper#capture(String targetFilepath, Object clipRect)

Proxy method for PhantomJS' WebPage#render. Adds a clipRect parameter for automatically setting page clipRect setting values and sets it back once done.

Example:

casper.start('http://www.google.fr/', function() {
    this.capture('google.png', {
        top: 100,
        left: 100,
        width: 500,
        height: 400
    });
});

casper.run();

Casper#captureSelector(String targetFile, String selector)

Captures the page area containing the provided selector.

Example:

casper.start('http://www.weather.com/', function() {
    this.captureSelector('weather.png', '.twc-story-block');
});

casper.run();

Casper#clear()

Clears the current page execution environment context. Useful to avoid having previously loaded DOM contents being still active.

Think of it as a way to stop javascript execution within the remote DOM environment.

Example:

casper.start('http://www.google.fr/', function() {
    this.clear(); // javascript execution in this page has been stopped
});

casper.then(function() {
    // ...
});

casper.run();

Note This method has been added in 0.6.5.

Casper#debugHTML()

Logs the HTML code of the current page directly to the standard output, for debugging purpose.

Example:

casper.start('http://www.google.fr/', function() {
    this.debugHTML();
});

casper.run();

Casper#debugPage()

Logs the textual contents of the current page directly to the standard output, for debugging purpose.

Example:

casper.start('http://www.google.fr/', function() {
    this.debugPage();
});

casper.run();

Casper#die(String message[, int status])

Exits phantom with a logged error message and an optional exit status code.

Example:

casper.start('http://www.google.fr/', function() {
    this.die("Fail.", 1);
});

casper.run();

Casper#download(String url, String target)

Saves a remote resource onto the filesystem.

casper.start('http://www.google.fr/', function() {
    var logoUrl = 'http://www.google.fr/intl/fr/about/corporate/company/';
    this.download(logoUrl, 'google_company.html');
});

casper.run(function() {
    this.echo('Done.').exit();
});

Casper#each(Array array, Function fn)

Iterates over provided array items and execute a callback.

Example:

var links = [
    'http://google.com/',
    'http://yahoo.com/',
    'http://bing.com/'
];

casper.start().each(links, function(self, link) {
    self.thenOpen(link, function() {
        this.echo(this.getTitle());
    });
});

casper.run();

Hint Have a look at the googlematch.js sample script for concrete usecase.

Casper#echo(String message[, String style])

Prints something to stdout, optionally with some fancy color (see the Colorizer section of this document for more information).

Example:

casper.start('http://www.google.fr/', function() {
    this.echo('Page title is: ' + this.evaluate(function() {
        return document.title;
    }), 'INFO'); // Will be printed in green on the console
});

casper.run();

Casper#evaluate(function fn[, Object replacements])

Evaluates an expression in the page context, a bit like what PhantomJS' WebPage#evaluate does, but can also handle passed arguments if you define their context:

Example:

casper.evaluate(function(username, password) {
    document.querySelector('#username').value = username;
    document.querySelector('#password').value = password;
    document.querySelector('#submit').click();
}, {
    username: 'sheldon.cooper',
    password: 'b4z1ng4'
});

Note For filling and submitting forms, rather use the Casper#fill() method.

Casper#evaluateOrDie(function fn[, String message])

Evaluates an expression within the current page DOM and die() if it returns anything but true.

Example:

casper.start('http://foo.bar/home', function() {
    this.evaluateOrDie(function() {
        return /logged in/.match(document.title);
    }, 'not authenticated');
});

casper.run();

Casper#exit([int status])

Exits PhantomJS with an optional exit status code.

Casper#exists(String selector)

Checks if any element within remote DOM matches the provided CSS3 selector.

casper.start('http://foo.bar/home', function() {
    if (this.exists('#my_super_id')) {
        this.echo('found #my_super_id', 'INFO');
    } else {
        this.echo('#my_super_id not found', 'ERROR');
    }
});

casper.run();

Casper#fetchText(String selector)

Retrieves text contents matching a given CSS3 selector. If you provide one matching more than one element, their textual contents will be concatenated.

casper.start('http://google.com/search?q=foo', function() {
    this.echo(this.fetchText('h3'));
}).run();

Casper#forward()

Moves a step forward in browser's history.

casper.start('http://foo.bar/1')
casper.thenOpen('http://foo.bar/2');
casper.thenOpen('http://foo.bar/3');
casper.back();    // http://foo.bar/2
casper.back();    // http://foo.bar/1
casper.forward(); // http://foo.bar/2
casper.run();

Also have a look at Casper.back().

Casper#log(String message[, String level, String space])

Logs a message with an optional level in an optional space. Available levels are debug, info, warning and error. A space is a kind of namespace you can set for filtering your logs. By default, Casper logs messages in two distinct spaces: phantom and remote, to distinguish what happens in the PhantomJS environment from the remote one.

Example:

casper.start('http://www.google.fr/', function() {
    this.log("I'm logging an error", "error");
});

casper.run();

Casper#fill(String selector, Object values[, Boolean submit])

Fills the fields of a form with given values and optionally submits it.

Example with this sample html form:

<form action="/contact" id="contact-form" enctype="multipart/form-data">
    <input type="text" name="subject"/>
    <textearea name="content"></textearea>
    <input type="radio" name="civility" value="Mr"/> Mr
    <input type="radio" name="civility" value="Mrs"/> Mrs
    <input type="text" name="name"/>
    <input type="email" name="email"/>
    <input type="file" name="attachment"/>
    <input type="checkbox" name="cc"/> Receive a copy
    <input type="submit"/>
</form>

A script to fill and submit this form:

casper.start('http://some.tld/contact.form', function() {
    this.fill('form#contact-form', {
        'subject':    'I am watching you',
        'content':    'So be careful.',
        'civility':   'Mr',
        'name':       'Chuck Norris',
        'email':      'chuck@norris.com',
        'cc':         true,
        'attachment': '/Users/chuck/roundhousekick.doc'
    }, true);
});

casper.then(function() {
    this.evaluateOrDie(function() {
        return /message sent/.test(document.body.innerText);
    }, 'sending message failed');
});

casper.run(function() {
    this.echo('message sent').exit();
});

Please Don't use CasperJS nor PhantomJS to send spam, or I'll be calling the Chuck. More seriously, please just don't.

Casper#getCurrentUrl()

Retrieves current page URL. Note the url will be url-decoded.

Example:

casper.start('http://www.google.fr/', function() {
    this.echo(this.getCurrentUrl()); // "http://www.google.fr/"
});

casper.run();

Casper#getGlobal(String name)

Retrieves a global variable value within the remote DOM environment by its name.

Example:

casper.start('http://www.google.fr/', function() {
    this.echo(this.getGlobal('innerWidth')); // 1024
});

casper.run();

Casper#getTitle()

Retrieves current page title.

Example:

casper.start('http://www.google.fr/', function() {
    this.echo(this.getTitle()); // "Google"
});

casper.run();

Casper#mouseClick(String selector)

Warning This method has been deprecated since 0.6. Use Casper.click() instead.

Casper#open(String location, Object Settings)

Performs an HTTP request for opening a given location. You can forge GET, POST, PUT, DELETE and HEAD requests.

Example for a standard GET request:

casper.start();

casper.open('http://www.google.com/').then(function() {
    this.echo('GOT it.');
});

casper.run();

Example for a POST request:

casper.start();

casper.open('http://some.testserver.com/post.php', {
    method: 'post',
    data:   {
        'title': 'Plop',
        'body':  'Wow.'
    }
});

casper.then(function() {
    this.echo('POSTED it.');
});

casper.run();

Warning PhantomJS 1.4.0 and 1.4.1 have introduced a regression with POST requests preventing data to be actually submitted; so please check you're using a more recent or patched version of PhantomJS before reporting any issue regarding this bug. PhantomJS 1.3 is not affected by the bug.

Casper#repeat(int times, function then)

Repeats a navigation step a given number of times.

Example:

var i = 0;
casper.start('http://foo.bar/home', function() {
    this.evaluateOrDie(function() {
        return /logged in/.match(document.title);
    }, 'not authenticated');
});

casper.repeat(5, function() {
    this.echo("I am step #" + ++i);
});

casper.run();

Casper#resourceExists(Mixed test)

Checks if a resource has been loaded. You can pass either a function or a string to perform the test.

Example:

casper.start('http://www.google.com/', function() {
    if (this.resourceExists('logo3w.png')) {
        this.echo('Google logo loaded');
    } else {
        this.echo('Google logo not loaded', 'ERROR');
    }
});

casper.run();

Casper#run(fn onComplete[, int time])

Runs the whole suite of steps and optionally executes a callback when they've all been done. Obviously, calling this method is mandatory in order to run the Casper navigation suite.

Casper suite won't run:

casper.start('http://foo.bar/home', function() {
    // ...
});

// hey, it's missing .run() here!

Casper suite will run:

casper.start('http://foo.bar/home', function() {
    // ...
});

casper.run();

Casper.run() also accepts an onComplete callback, which you can consider as a custom final step to perform when all the other steps have been executed. Just don't forget to exit() Casper if you define one!

casper.start('http://foo.bar/home', function() {
    // ...
});

casper.then(function() {
    // ...
});

casper.run(function() {
    this.echo('So the whole suite ended.');
    this.exit(); // <--- don't forget me!
});

Casper#setHttpauth(String username, String password)

Sets HTTP_AUTH_USER and HTTP_AUTH_PW for HTTP based authentication systems.

Example:

casper.start();

casper.setHttpAuth('sheldon.cooper', 'b4z1ng4');

casper.thenOpen('http://password-protected.domain.tld/', function() {
    this.echo("I'm in. Bazinga.");
})
casper.run();

Of course you can directly pass the auth string in the url to open:

var url = 'http://sheldon.cooper:b4z1ng4@password-protected.domain.tld/';
casper.start(url, function() {
    this.echo("I'm in. Bazinga.");
})
casper.run();

Casper#start(String url[, function then])

Configures and starts Casper, then open the provided url and optionally adds the step provided by the then argument.

Example:

casper.start('http://google.fr/', function() {
    this.echo("I'm loaded.");
});

casper.run();

Alternatively:

casper.start('http://google.fr/');

casper.then(function() {
    this.echo("I'm loaded.");
});

casper.run();

Or alternatively:

casper.start('http://google.fr/');

casper.then(function() {
    casper.echo("I'm loaded.");
});

casper.run();

Or even:

casper.start('http://google.fr/');

casper.then(function(self) {
    self.echo("I'm loaded.");
});

casper.run();

Matter of taste!

Note You must call the start() method in order to be able to add navigation steps and run the suite. If you don't you'll get an error message inviting you to do so anyway.

Casper#then(function fn)

The standard way to add a new navigation step to the Casper suite by provide a callback function which will be executed when the requested page is loaded.

Example:

casper.start('http://google.fr/').then(function() {
    this.echo("I'm in your google.");
});

casper.run();

If you want to open a page as a next step in your navigation scenario, please refer to the Casper#thenOpen() method documentation.

Casper#thenEvaluate(function fn[, Object replacements])

Adds a new navigation step to perform code evaluation within the current retrieved page DOM.

Example:

// Querying for "Chuck Norris" on Google
casper.start('http://google.fr/').thenEvaluate(function(term) {
    document.querySelector('input[name="q"]').setAttribute('value', term);
    document.querySelector('form[name="f"]').submit();
}, {
    term: 'Chuck Norris'
});

casper.run();

Casper#thenOpen(String location[, function then])

Adds a new navigation step for opening a new location, and optionally add a next step when its loaded.

Example:

casper.start('http://google.fr/').then(function() {
    this.echo("I'm in your google.");
});

casper.thenOpen('http://yahoo.fr/', function() {
    this.echo("Now I'm in your yahoo.")
});

casper.run();

Casper#thenOpenAndEvaluate(String location[, function then, Object replacements])

Basically a shortcut for opening an url and evaluate code against remote DOM environment.

Example:

casper.start('http://google.fr/').then(function() {
    this.echo("I'm in your google.");
});

casper.thenOpenAndEvaluate('http://yahoo.fr/', function() {
    var f = document.querySelector('form');
    f.querySelector('input[name=q]').value = 'chuck norris';
    f.submit();
});

casper.run(function() {
    this.debugPage();
    this.exit();
});

Casper#viewport(Number width, Number height)

Changes current viewport size.

Example:

casper.viewport(1024, 768);

Note PhantomJS comes with a default viewport size of 400x300, and CasperJS doesn't override it by default.

Casper#visible(String selector)

Checks if the DOM element matching the provided CSS3 selector is visible in remote page.

Example:

casper.start('http://google.com/', function() {
    if (this.visible('#hplogo')) {
        this.echo("I can see the logo");
    } else {
        this.echo("I can't see the logo");
    }
});

Casper#wait(Number timeout[, Function then])

Pause steps suite execution for a given amount of time, and optionally execute a step on done.

Example:

casper.start('http://yoursite.tld/', function() {
    this.wait(1000, function() {
        this.echo("I've waited for a second.");
    });
});

casper.run();

Casper#waitFor(Function testFx[, Function then, Function onTimeout, Number timeout])

Waits until a function returns true to process any next step.

You can also set a callback on timeout using the onTimeout argument, and set the timeout using the timeout one, in milliseconds. The default timeout is set to 5000ms.

Example:

casper.start('http://yoursite.tld/', function() {
    this.waitFor(function() {
        return this.evaluate(function() {
            return document.querySelectorAll('ul.your-list li').length > 2;
        });
    }, function() {
        this.captureSelector('yoursitelist.png', 'ul.your-list');
    });
});

casper.run();

Example using the onTimeout callback:

casper.start('http://yoursite.tld/', function() {
    this.waitFor(function() {
        return this.evaluate(function() {
            return document.querySelectorAll('ul.your-list li').length > 2;
        });
    }, function() {
        this.captureSelector('yoursitelist.png', 'ul.your-list');
    }, function() {
        this.echo("I can't haz my screenshot.").exit();
    });
});

casper.run();

Casper#waitForSelector(String selector[, Function then, Function onTimeout, Number timeout])

Waits until an element matching the provided CSS3 selector exists in remote DOM to process any next step. Uses Casper.waitFor().

Example:

casper.start('https://twitter.com/#!/n1k0', function() {
    this.waitForSelector('.tweet-row', function() {
        this.captureSelector('twitter.png', 'html');
    });
});

casper.run();

Casper#waitWhileSelector(String selector[, Function then, Function onTimeout, Number timeout])

Waits until an element matching the provided CSS3 selector does not exist in remote DOM to process a next step. Uses Casper.waitFor().

Example:

casper.start('http://foo.bar/', function() {
    this.waitWhileSelector('.selector', function() {
        this.echo('.selector is no more!');
    });
});

casper.run();

Casper#waitForResource(Function testFx[, Function then, Function onTimeout, Number timeout])

Wait until a resource that matches the given testFx is loaded to process a next step. Uses Casper.waitFor().

Example:

casper.start('http://foo.bar/', function() {
    this.waitForResource(function (resource) {
        return resource.url.match("foobar.png");
    }, function() {
        this.echo('foobar.png is loaded');
    });
});

casper.run();

Casper#waitUntilVisible(String selector[, Function then, Function onTimeout, Number timeout])

Waits until an element matching the provided CSS3 selector is visible in the remote DOM to process a next step. Uses Casper.waitFor().

Casper#waitWhileVisible(String selector[, Function then, Function onTimeout, Number timeout])

Waits until an element matching the provided CSS3 selector is no longer visible in remote DOM to process a next step. Uses Casper.waitFor().

CasperJS ships with a built-in command line parser on top of PhantomJS' one, located in the cli module; it exposes passed arguments as positional ones and named options

But no worries for manipulating the cli module parsing API, a Casper instance always contains a ready to use cli property, allowing easy access of all these parameters.

Let's consider this simple casper script:

var casper = require("casper").create();

casper.echo("Casper CLI passed args:");
require("utils").dump(casper.cli.args);

casper.echo("Casper CLI passed options:");
require("utils").dump(casper.cli.options);

casper.exit();

Note Please note the two casper-path and cli options; these are passed to the casper script through the casperjs Python executable.

Execution results:

$ casperjs test.js arg1 arg2 arg3 --foo=bar --plop anotherarg
Casper CLI passed args: [
    "arg1",
    "arg2",
    "arg3",
    "anotherarg"
]
Casper CLI passed options: {
    "casper-path": "/Users/niko/Sites/casperjs",
    "cli": true,
    "foo": "bar",
    "plop": true
}

Getting, checking or dropping parameters:

var casper = require("casper").create();
casper.echo(casper.cli.has(0));
casper.echo(casper.cli.get(0));
casper.echo(casper.cli.has(3));
casper.echo(casper.cli.get(3));
casper.echo(casper.cli.has("foo"));
casper.echo(casper.cli.get("foo"));
casper.cli.drop("foo");
casper.echo(casper.cli.has("foo"));
casper.echo(casper.cli.get("foo"));
casper.exit();

Execution results:

$ casperjs test.js arg1 arg2 arg3 --foo=bar --plop anotherarg
true
arg1
true
anotherarg
true
bar
false
undefined

Hint What if you want to check if any arg or option has been passed to your script? Here you go:

// removing default options passed by the Python executable
casper.cli.drop("cli");
casper.cli.drop("casper-path");

if (casper.cli.args.length === 0 && Object.keys(casper.cli.options).length === 0) {
    casper.echo("No arg nor option passed").exit();
}

Last but not least, you can still use all PhantomJS standard CLI options as you would do with any other phantomjs script. To remember what they are, just run the casperjs --help command:

$ casperjs --help
CasperJS version 0.6.6 at /Users/niko/Sites/casperjs, using PhantomJS version 1.3.0

Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
       casperjs [options] test [test path [test path ...]]

Options:

--cookies-file=/path/to/cookies.txt    Sets the file name to store the persistent cookies
--config=/path/to/config               Specifies path to a JSON-formatted config file
--disk-cache=[yes|no]                  Enables disk cache (at desktop services cache storage location, default is 'no')
--ignore-ssl-errors=[yes|no]           Ignores SSL errors (i.e. expired or self-signed certificate errors)
--load-images=[yes|no]                 Loads all inlined images (default is 'yes')
--load-plugins=[yes|no]                Loads all plugins (i.e. 'Flash', 'Silverlight', ...) (default is 'no')
--local-to-remote-url-access=[yes|no]  Local content can access remote URL (default is 'no')
--max-disk-cache-size=size             Limits the size of disk cache (in KB)
--output-encoding                      Sets the encoding used for terminal output (default is 'utf8')
--proxy=address:port                   Sets the network proxy (e.g. "--proxy=192.168.1.42:8080")
--script-encoding                      Sets the encoding used for the starting script (default is 'utf8')
--version                              Prints out CasperJS version

CasperJS provides an event handler very similar to the one shipping with nodejs; actually it borrows most of its codebase. CasperJS also adds filters, which are basically ways to alter values asynchronously.


Events

Using events is pretty much straightforward if you're a node developer, or if you worked with any evented system before:

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

casper.on('resource.received', function(resource) {
    casper.echo(resource.url);
});

Here's a table containing all the available events with all the parameters passed to their callback:

Name Arguments Description
back None Emitted when the embedded browser is asked to go back a step in its history.
capture.saved targetFile Emitted when a screenshot image has been captured.
click selector Emitted when the Casper.click() method has been called.
die message, status Emitted when the Casper.die() method has been called.
downloaded.file targetPath Emitted when
exit status Emitted when the Casper.exit() method has been called.
fill selector, vals, submit Emitted when a form is filled using the Casper.fill() method.
forward None Emitted when the embedded browser is asked to go forward a step in its history.
http.auth username, password Emitted when http authentication parameters are set.
http.status.[code] resource

Emitted when any given HTTP reponse is received with the status code specified by [code], eg.:

casper.on('http.status.404', function(resource) {
    casper.echo(resource.url + ' is 404');
})
load.started None Emitted when PhantomJS' WebPage.onLoadStarted event callback is called.
load.failed Object Emitted when PhantomJS' WebPage.onLoadFinished event callback has been called and failed.
load.finished status Emitted when PhantomJS' WebPage.onLoadFinished event callback is called.
log entry

Emitted when the Casper.log() method has been called. The entry parameter is an Object like this:

{
    level:   "debug",
    space:   "phantom",
    message: "A message",
    date:    "a javascript Date instance"
}
mouse.click args Emitted when the mouse left-click something or somewhere.
mouse.down args Emitted when the mouse presses on something or somewhere with the left button.
mouse.move args Emitted when the mouse moves onto something or somewhere.
mouse.up args Emitted when the mouse releases the left button over something or somewhere.
open location, settings

Emitted when an HTTP request is sent. First callback arg is the location, second one is a request settings Object of the form:

{
    method: "post",
    data:   "foo=42&chuck=norris"
}
page.created page Emitted when PhantomJS' WebPage object used by CasperJS has been created.
page.initialized page Emitted when PhantomJS' WebPage object used by CasperJS has been initialized.
remote.alert message Emitted when a remote alert() call has been performed.
remote.message msg Emitted when any remote console logging call has been performed.
resource.received resource Emitted when any resource has been received.
resource.requested request Emitted when any resource has been requested.
run.complete None Emitted when the whole series of steps in the stack have been executed.
run.start None Emitted when Casper.run() is called.
starting None Emitted when Casper.start() is called.
started None Emitted when Casper has been started using Casper.start().
step.added step Emitted when a new navigation step has been added to the stack.
step.complete stepResult Emitted when a navigation step has been executed.
step.created fn Emitted when a new navigation step has been created.
step.start step Emitted when a navigation step has been started.
step.timeout None Emitted when a navigation step has been executed.
timeout None Emitted when the execution time of the script has reached the Casper.options.timeout value.
viewport.changed [width, height] Emitted when the viewport has been changed.
wait.done None Emitted when a Casper.wait() operation ends.
wait.start None Emitted when a Casper.wait() operation starts.
waitFor.timeout None Emitted when the execution time of a Casper.wait*() operation has exceeded the value of Casper.options.stepTimeout.

Emitting you own events

Of course you can emit your own events, using the Casper.emit() method:

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

// listening to a custom event
casper.on('google.loaded', function() {
    this.echo('Google page title is ' + this.getTitle());
});

casper.start('http://google.com/', function() {
    // emitting a custom event
    this.emit('google.loaded');
});

casper.run();

Filters

Filters allow you to alter some values asynchronously. Sounds obscure? Let's take a simple example and imagine you would like to alter every single url opened by CasperJS to append a foo=42 query string parameter:

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

casper.setFilter('open.location', function(location) {
    return /\?+/.test(location) ? location += "&foo=42" : location += "?foo=42";
});

There you have it, every single requested url will have this appended. Let me bet you'll find far more interesting use cases than my silly one ;)

Here'a the list of all available filters with their expected return value:

Name Arguments Return type Description
capture.target_filename args String Allows to alter the value of the filename where a screen capture should be stored.
echo.message message String Allows to alter every message written onto stdout.
log.message message String Allows to alter every log message.
open.location args String Allows to alter every url before it being opened.

Casper ships with a few client-side utilities which are injected in the remote DOM environment, and accessible from there through the __utils__ object instance of the ClientUtils class of the clientutils module.

Note These tools are provided to avoid coupling CasperJS to any third-party library like jQuery, Mootools or something; but you can always include these and have them available client-side using the Casper.options.clientScripts option.

ClientUtils#encode(String contents)

Encodes a string using the base64 algorithm. For the records, CasperJS doesn't use builtin window.btoa() function because it can't deal efficiently with strings encoded using >8b characters.

var base64;
casper.start('http://foo.bar/', function() {
    base64 = this.evaluate(function() {
        return __utils__.encode("I've been a bit cryptic recently");
    };
});

casper.run(function() {
    this.echo(base64).exit();
});

ClientUtils#exists(String selector)

Checks if a DOM element matching a given CSS3 selector exists.

var exists;
casper.start('http://foo.bar/', function() {
    exists = this.evaluate(function() {
        return __utils__.exists('#some_id');
    };
});

casper.run(function() {
    this.echo(exists).exit();
});

ClientUtils#findAll(String selector)

Retrieves all DOM elements matching a given CSS3 selector.

var links;
casper.start('http://foo.bar/', function() {
    links = this.evaluate(function() {
        var elements = __utils__.findAll('a.menu');
        return Array.prototype.forEach.call(elements, function(e) {
            return e.getAttribute('href');
        });
    };
});

casper.run(function() {
    this.echo(JSON.stringify(links)).exit();
});

ClientUtils#findOne(String selector)

Retrieves a single DOM element by a CSS3 selector.

var href;
casper.start('http://foo.bar/', function() {
    href = this.evaluate(function() {
        return __utils__.findOne('#my_id').getAttribute('href');
    };
});

casper.run(function() {
    this.echo(href).exit();
});

ClientUtils#getBase64(String url[, String method, Object data])

This method will retrieved a base64 encoded version of any resource behind an url. For example, let's imagine we want to retrieve the base64 representation of some website's logo:

var logo = null;
casper.start('http://foo.bar/', function() {
    logo = this.evaluate(function() {
        var imgUrl = document.querySelector('img.logo').getAttribute('src');
        return __utils__.getBase64(imgUrl);
    };
});

casper.run(function() {
    this.echo(logo).exit();
});

ClientUtils#getBinary(String url[, String method, Object data])

This method will retrieved the raw contents of a given binary resource; unfortunately though, PhantomJS cannot process these data directly so you'll have to process them within the remote DOM environment. If you intend to download the resource, use ClientUtils.getBase64() or Casper.base64encode() instead.

casper.start('http://foo.bar/', function() {
    this.evaluate(function() {
        var imgUrl = document.querySelector('img.logo').getAttribute('src');
        console.log(__utils__.getBinary(imgUrl));
    };
});

casper.run();

Warning You won't be able to pass the binary string from the remote DOM environment to PhantomJS' one. For retrieving binary contents, use ClientUtils.encode().

ClientUtils#visible(String selector)

Checks if an element is visible.

casper.start('http://foo.bar/', function() {
    if (this.visible('#cain')) {
        this.echo("I CAN SEE YOU");
    }
});

casper.run();

Casper ships with a tester module and a Tester class providing an API for unit & functional testing purpose. By default you can access an instance of this class through test property of any Casper class instance.

Note The best way to learn how to use the Tester API and see it in action is probably to have a look at the CasperJS test suite code.

Tester#assert(Boolean condition[, String message])

Asserts that the provided condition strictly resolves to a boolean true.

var url = 'http://www.google.fr/';
var casper = require('casper').create();
casper.start(url, function() {
    this.test.assert(this.getCurrentUrl() === url, 'url is the one expected');
});

Tester#assertEquals(mixed testValue, mixed expected[, String message])

Asserts that two values are strictly equals.

var url = 'http://www.google.fr/';
var casper = require('casper').create();
casper.start(url, function() {
    this.test.assertEquals(this.getCurrentUrl(), url, 'url is the one expected');
});

Tester#assertEval(Function fn[, String message])

Asserts that a code evaluation in remote DOM resolves to true.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertEval(function() {
        return document.querySelectorAll('form').length > 0;
    }, 'google.fr has at least one form');
});

Tester#assertEvalEquals(Function fn, mixed expected[, String message])

Asserts that the result of a code evaluation in remote DOM equals.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertEvalEquals(function() {
        return document.querySelectorAll('form').length;
    }, 1, 'google.fr provides a single form tag');
});

Tester#assertExists(String selector[, String message])

Asserts that an element matching the provided CSS3 selector exists in remote DOM environment.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertExists('form[name="gs"]', 'google.fr has a form with name "gs"');
});

Tester#assertMatch(mixed subject, RegExp pattern[, String message])

Asserts that a provided string matches a provided javascript RegExp pattern.

casper.test.assertMatch('Chuck Norris', /^chuck/i, 'Chuck Norris' first name is chuck');

Tester#assertNot(mixed subject[, String message])

Asserts that the passed subject resolves to false.

casper.test.assertNot(false, "Universe is still operational");

Tester#assertRaises(Function fn, Array args[, String message])

Asserts that the provided function called with the given parameters raises a javascript Error.

casper.test.assertRaises(function(throwIt) {
    if (throwIt) {
        throw new Error('thrown');
    }
}, [true], 'Error has been raised.');

Tester#assertSelectorExists(String selector[, String message])

Asserts that at least an element matching the provided CSS3 selector exists in remote DOM.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertSelectorExists('form[name="gs"]', 'google.fr provides a form');
});

Tester#assertResourceExists(Function testFx[, String message])

The testFx is executed against all loaded asserts and the test passes when at least one resource matches.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertResourceExists(function (resource) {
      return resource.url.match('logo3w.png');
    }, 'google.fr logo was loaded');
    // or shorter
    this.test.assertResourceExists('logo3w.png', 'google.fr logo was loaded');
});

Tester#assertTextExists(String expected[, String message])

Asserts that body plain text content contains the given string.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertTextExists('google', 'page body contains "google"');
});

Tester#assertTitle(String expected[, String message])

Asserts that title of the remote page equals to the expected one.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertTitle('Google', 'google.fr has the correct title');
});

Tester#assertType(mixed input, String type[, String message])

Asserts that the provided input is of the given type.

var casper = require('casper').create();
casper.test.assertType(42, "number", "Okay, 42 is a number");
casper.test.assertType([1, 2, 3], "array", "Yeah, we can test for arrays too =)");

Tester#assertUrlMatch(Regexp pattern[, String message])

Asserts that a the current page url matches the provided RegExp pattern.

var casper = require('casper').create();
casper.start('http://www.google.fr/', function() {
    this.test.assertUrlMatch(/^http:\/\//', 'google.fr is served in http://');
});

Tester#colorize(String message, String style)

Render a colorized output. Basically a proxy method for Casper.Colorizer#colorize().

Tester#comment(String message)

Writes a comment-style formatted message to stdout.

var casper = require('casper').create();
casper.test.comment("Hi, I'm a comment");

Tester#error(String message)

Writes an error-style formatted message to stdout.

var casper = require('casper').create();
casper.test.error("Hi, I'm an error");

Tester#fail(String message)

Adds a failed test entry to the stack.

var casper = require('casper').create();
casper.test.fail("Georges W. Bush");

Tester#formatMessage(String message, String style)

Formats a message to highlight some parts of it. Only used internally by the tester.

Tester#info(String message)

Writes an info-style formatted message to stdout.

var casper = require('casper').create();
casper.test.info("Hi, I'm an informative message.");

Tester#pass(String message)

Adds a successful test entry to the stack.

var casper = require('casper').create();
casper.test.pass("Barrack Obama");

Tester#renderResults(Boolean exit, Number status, String save)

Render tests results, save results in an XUnit formatted file, and optionally exit phantomjs.

var casper = require('casper').create();
// ...
casper.run(function() {
    // exists with status code 0 and saves XUnit formatted results
    // in test-results.xml
    this.test.renderResults(true, 0, 'test-results.xml');
});

Casper ships with a colorizer module which contains a Colorizer class which can print stuff to the console output in color:

var colorizer = require('colorizer').create();
console.log(colorizer.colorize("Hello World", "INFO"));

Though most of the times you will use it transparently using the Casper.echo() method:

casper.echo('an informative message', 'INFO'); // printed in green
casper.echo('an error message', 'ERROR');      // printed in red

Available predefined styles

Available predefined styles are:

  • ERROR: white text on red background
  • INFO: green text
  • TRACE: green text
  • PARAMETER: cyan text
  • COMMENT: yellow text
  • WARNING: red text
  • GREEN_BAR: green text on white background
  • RED_BAR: white text on red background
  • INFO_BAR: cyan text

Here's a sample output of what it can look like:

capture

Colorizer#colorize(String text, String styleName)

Computes a colored version of the provided text string using a given predefined style.

var colorizer = require('colorizer').create();
console.log(colorizer.colorize("I'm a red error", "ERROR"));

Note Most of the time you won't have to use a Colorizer instance directly as CasperJS provides all the necessary methods.

See the list of the predefined styles available.

Colorizer#format(String text, Object style)

Formats a text string using the provided style definition. A style definition is a standard javascript Object instance which can define the following properties:

  • String bg: background color name
  • String fg: foreground color name
  • Boolean bold: apply bold formatting
  • Boolean underscore: apply underline formatting
  • Boolean blink: apply blink formatting
  • Boolean reverse: apply reverse formatting
  • Boolean conceal: apply conceal formatting

Note Available color names are black, red, green, yellow, blue, magenta, cyan and white.

var colorizer = require('colorizer').create();
colorizer.format("We all live in a yellow submarine", {
    bg:   'yellow',
    fg:   'blue',
    bold: true
});

Quick reference

The Colorizer class

CasperJS allows logging using its log() method and these standard event levels:

  • debug
  • info
  • warning
  • error

Sample use:

var casper = require('casper').create();
casper.log('plop', 'debug');
casper.log('plip', 'warning');

Now, there are two things to distinguish: log storage and log display; by default CasperJS won't print the logs to the standard output. In order to do so, you must enable the verbose Casper option:

var casper = require('casper').create({
    verbose: true
});

Also, by default Casper is configured to filter logging which is under the error level; you can override this setting by configuring the logLevel option:

var casper = require('casper').create({
    verbose: true,
    logLevel: 'debug'
});

You can also dump a JSON log of your Casper suite just by rendering the contents of the Casper.logs property:

var casper = require('casper').create({
// ...
casper.run(function() {
    this.echo(JSON.stringify(this.logs, null, 4)).exit();
});

Last, if you print log messages to the standard output using the verbose option, you'll get some fancy colors:

var casper = require('casper').create({
    verbose: true,
    logLevel: 'debug'
})
casper.log('this is a debug message', 'debug');
casper.log('and an informative one', 'info');
casper.log('and a warning', 'warning');
casper.log('and an error', 'error');
casper.exit();

This will give the following output:

image

Sometimes it can be convenient to add your own methods to a Casper object instance; you can easily do so as illustrated in the example below:

var casper = require('casper').create({
    loadImages:  false,
    logLevel:   "debug",
    verbose:    true
});

var links = {
    'http://edition.cnn.com/': 0,
    'http://www.nytimes.com/': 0,
    'http://www.bbc.co.uk/': 0,
    'http://www.guardian.co.uk/': 0
};

var fantomas = Object.create(casper);

fantomas.countLinks = function(selector) {
    return this.evaluate(function() {
        return __utils__.findAll('a[href]').length;
    });
};

fantomas.renderJSON = function(what) {
    return this.echo(JSON.stringify(what, null, '  '));
};

fantomas.start();

Object.keys(links).forEach(function(url) {
    fantomas.thenOpen(url, function() {
        links[url] = this.countLinks();
    });
});

fantomas.run(function() {
    this.renderJSON(links).exit();
});

Warning As of version 0.6, the Casper.extend() method has been deprecated; please now use the method illustrated above.

Using CoffeeScript

If you're writing your casper scripts using CoffeeScript, this is getting a bit easier:

links =
    'http://edition.cnn.com/': 0
    'http://www.nytimes.com/': 0
    'http://www.bbc.co.uk/': 0
    'http://www.guardian.co.uk/': 0

class Fantomas extends require('casper').Casper
    countLinks: ->
        @evaluate ->
            __utils__.findAll('a').length

    renderJSON: (what) ->
        @echo JSON.stringify what, null, '  '

fantomas = new Fantomas
    loadImages:  false
    logLevel:    "debug"
    verbose:     true

fantomas.start()

for url of links
    do (url) ->
        fantomas.thenOpen url, ->
            links[url] = @countLinks()

fantomas.run ->
    @renderJSON links
    @exit()

CasperJS ships with a handful set of tools to be used as a functional testing framework. For example, let's test write a tests suite for testing google search (yes, you read it well):

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

casper.start('http://www.google.fr/', function() {
    this.test.assertTitle('Google', 'google homepage title is the one expected');
    this.test.assertExists('form[action="/search"]', 'main form is found');
    this.fill('form[action="/search"]', {
        q: 'foo'
    }, true);
});

casper.then(function() {
    this.test.assertTitle('foo - Recherche Google', 'google title is ok');
    this.test.assertUrlMatch(/q=foo/, 'search term has been submitted');
    this.test.assertEval(function() {
        return __utils__.findAll('h3.r').length >= 10;
    }, 'google search for "foo" retrieves 10 or more results');
});

casper.run(function() {
    this.test.renderResults(true);
});

As you can see, casper.test is a reference to a tester.Tester object instance, which is used to make the assertions and render the results.

Note You can find the whole tester.Tester API documentation in the dedicated section.

Now run the tests suite:

$ casperjs samples/googletest.js

You'll probably get something like this:

capture

In case any assertion fails, you'd rather get something like the following:

capture


Exporting results in xUnit format

CasperJS can export the results of the test suite to an xUnit XML file, which is compatible with continuous integration tools such as Jenkins. To save the xUnit log of your test suite to a log.xml file, you can process this way:

casper.run(function() {
    this.test.renderResults(true, 0, 'log.xml');
});

A cooler way is to add an option to your script using CLI argument parsing:

casper.run(function() {
    this.test.renderResults(true, 0, this.cli.get('save') || false);
});

Then you can run:

$ casperjs test.js --save=log.xml

CasperJS tests

CasperJS has its own unit and functional test suite, located in the tests subfolder. More tests will be added in the future. To run the test suite, from the root of a checkout of the casperjs repository:

$ cd /path/to/casperjs
$ casperjs test tests/suites

Organizing your tests

Of course writing all your tests in a single file may be painful, so you can split them across files.

Important There are two important conditions for splitting your test suite across several files:

  1. Not to create a new Casper instance in a split test file;

  2. To call the Tester.done() method when all the tests contained in a single file have been executed.

Here's a first sample test file:

// file: /path/to/test/dir/test1.js

casper.test.comment('My first test file');
casper.test.assert(true, "true is so true");
casper.test.done(); // I must be called!

And a second one:

// file: /path/to/test/dir/test2.js

casper.test.comment('This is my second test file, a bit more async');

casper.start('http://my.location.tld/', function() {
    this.test.assertNot(false, "false is so false");
});

casper.run(function() {
    this.test.done(); // I must be called once all the async stuff has been executed
});

Hint As you can see, a standard Casper class instance, stored in a casper variable, is already available and exposed to each test file; that's because a configured one's already available as stated previously.

The casperjs test command comes handy for running all the tests found at a given location:

$ casperjs test /path/to/test/dir/

This is theoretically what you will get:

image

Also, you can of course run a single test file:

$ casperjs test /path/to/test/dir/test1.js

Some options are available using the casper test command:

  • --xunit=<filename> will export test suite results in a xUnit XML file
  • --direct will output log messages directly to the console
  • --log-level=<logLevel> sets the logging level (see the related section)

Extending Casper for Testing

The $ casper test [path] command is just a shortcut for $ casper /path/to/casperjs/tests/run.js [path]; so if you want to extend Casper capabilities for your tests, your best bet is to write your own runner and extend the casper object instance from there.

Hint You can find the default runner code in ./tests/run.js.

Here's a selection of the most frequently asked questions by casperjs newcomers.

I'm stuck! What can I do?

Your best bet is probably to ask for help on the CasperJS discussion group


What is the versioning policy of CasperJS?

Releases will follow the SemVer standard; they will be numbered with the follow format:

<major>.<minor>.<patch>[-<identifier>]

And constructed with the following guidelines:

  • Breaking backwards compatibility bumps the major
  • New additions without breaking backwards compatibility bumps the minor
  • Bug fixes and misc changes bump the patch
  • Unstable, special and trunk versions will have a proper identifier

I'm getting TypeError: 'undefined' is not a function; WTF?

Unfortunately PhantomJS ships with a QtWebKit JS engine which would need quite a serious upgrade to have more explicit error messages, stack traces, location, etc.

I cannot do much to make the situation really better, unfortunately :/


Can I use jQuery with CasperJS?

Sure, as every single other javascript library on Earth.

A first solution is to inject it into the remote DOM environment by hand using the standard WebPage.injectJs() method:

casper.page.injectJs('http://code.jquery.com/jquery-1.7.min.js');

If you need jQuery being available everytime, you can also make it being injected in every received response by setting the clientScripts option of CasperJS:

var casper = require('casper').create({
    clientScripts: ["includes/jquery.min.js"]
});

Note You can't inject scripts using the HTTP protocol, you actually have to use a relative/absolute filesystem path to the script resource.


Can I use CasperJS without using the casperjs executable?

Yes, you can call a CasperJS script directly with the phantomjs executable, but if you do so, you must set the phantom.casperPath property to the path where the library root is located on your system:

// casperscript.js
phantom.casperPath = '/path/to/casperjs';
phantom.injectJs(phantom.casperPath + '/bin/bootstrap.js');

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

You can run such a script like any other standard PhantomJS script:

$ phantomjs casperscript.js

Tip This is especially useful if you work on Windows and don't have a way to use the Python-based casperjs executable easily.


How can I catch HTTP 404 and other status codes?

You can define your own HTTP status code handlers by using the httpStatusHandlers option of the Casper object. You can also catch other HTTP status codes as well, as demoed below:

var casper = require('casper').create({
    httpStatusHandlers: {
        404: function(self, resource) {
            self.echo(resource.url + ' not found (404)');
        },
        500: function(self, resource) {
            self.echo(resource.url + ' gave an error (500)');
        }
    },
    verbose: true
});

casper.start('http://mywebsite/404', function() {
    this.echo('We suppose this url return an HTTP 404');
});

casper.thenOpen('http://mywebsite/500', function() {
    this.echo('We suppose this url return an HTTP 500');
});

casper.run(function() {
    this.echo('Done.').exit();
});

Hint As of 0.6, casper ships with a complete event system and a bunch of these are dedicated to HTTP statuses. You're encouraged to use them.

You can download this project in either zip or tar formats. You can also clone the project with Git by running:

$ git clone git://github.com/n1k0/casperjs casperjs

Always try to use a tagged version on production:

$ cd casperjs
$ git checkout tags/0.6.6

Feel free to play with the code and report any issue on github. CasperJS has also its own on twitter account.

Casper.js is released under the terms of the MIT license.

Copyright (c) 2011 Nicolas Perriault
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.