using mocha-phantomjs to automate functional testing

captainclam picture captainclam · Nov 8, 2012 · Viewed 18.4k times · Source

My project is using: Node, Coffeescript, SocketIO, Browserify and Mocha. (mocha for standard server-side unit tests)

I would like to automate some client-side interface testing using a headless browser. PhantomJS looked like the ideal choice (picked over Zombie due to web socket support).

The PhantomJS pages warn it is not a test runner, which I understand, and they recommend using the mocha-phantomjs project to drive your tests.

So I've been able to get the sample tests running (e.g. mocha-phantomjs tests/mixed.html), but my current problem is actually using PHANTOM within the tests. All the sample tests in the mocha-phantomjs repo seem to use standard mocha server-side unit test.

e.g. I can easily run mocha-phantomjs tests/mixed.html to view boring old unit tests. Or I can run phantomjs tests/login.coffee to load up my login screen... but how do I combine the two to make assertions on what I should expect to see on my login screen?

I can't find any examples of this on the web, and I'm struggling with understanding the best way to go about this.

Hope this all makes sense. Thanks in advance for any assistance.

UPDATE: I found the following suggestion by the author (here), but I don't really understand exactly what to do with it: phantomjs lib/mocha-phantomjs.coffee test/mixed.html

Answer

Darren picture Darren · Dec 25, 2012

There's a fairly nice tutorial for testing with Mocha and Phantom.JS here.

The section on Mocha and PhantomJS is short, but the basic idea is to put DOM assertions and interactions into your Mocha test suite, run it a la client-side via a testrunner.html file, and then point mocha-phantomjs at the testrunner.html file.

To paraphrase, your Mocha test might look like this:

describe("DOM Test", function () {

    var el = document.createElement("div");
    el.id = "myDiv";
    el.innerHTML = "Hello World!";
    document.body.appendChild(el);
    var myEl = document.getElementById('myDiv');

    it("has the right text", function () {
        (myEl.innerHTML).should.equal("Hello World!");
    });
});

And the testrunner.html file would be the normal setup:

<html>
    <head>
        <title> Tests </title>
        <link rel="stylesheet" href="./node_modules/mocha/mocha.css" />
    </head>
    <body>
        <div id="mocha"></div>
        <script src="./node_modules/mocha/mocha.js"></script>
        <script src="./node_modules/chai/chai.js"></script>
        <script>
            mocha.ui('bdd');
            mocha.reporter('html');
            var should = chai.should();
        </script>
        <script src="test/test.js"></script>
        <script>
            if (window.mochaPhantomJS) { mochaPhantomJS.run(); }
            else { mocha.run(); }
        </script>
    </body>
</html>

If you'd prefer a solution run entirely from the node.js ecosystem, it's worth considering Zombie.JS. This Stack Overflow question provides a basic example.

The tradeoff is that while Zombie.JS can be used simply by requiring the node module, and is extremely fast, it's not a "real" web browser. PhantomJS is closer, as its based on webkit. Also, the first approach with mocha-phantomjs would allow you to run the client-side Mocha tests in different browsers of your choice, PhantomJS being just one of them.