Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

testing existing pages with mocha-phantomjs

I'm not quite getting how to use PhantomJS and Mocha together, specifically through mocha-phantomjs.

I've read some tutorials (the one at tutsplus is quite helpful) and am not seeing how I can test external pages using Phantom and Mocha. I'm sure I just need a nudge.

In the tutorial the author creates a tests.js file with some DOM setup/manipulation, as well as some mocha assertions. Then, he creates a separate HTML file that loads the tests.js file and uses mocha-phantomjs to fire up phantom and run the tests.

That's where I'm a little confused, how the mochaPhantomJS.run() method actually does things behind the scenes, whether it knows to search the js file for a describe block and run all tests within, that sort of thing. I don't need chapter and verse, but a high-level summary would be ideal.

Also, if I want to test an outside page, how can I best do that? In the tutorial all the DOM investigation and testing is done on the test page. If I want to test a different page, do I change or setup my assertions differently? Should I call the PhantomJS API from those tests and point to an external site?

like image 714
larryq Avatar asked Mar 10 '14 21:03

larryq


1 Answers

Mocha will run tests that have been specified in javascript that has been included in the html page that is launched. If you look at the example html page on mocha-phantomjs it expects the test definitions using describe/it calls to be in the test/mycode.js file. If you put something like

These tests are only testing what is in the main file and associated javascript, there isn't anything special that mocha-phantomjs provides to test external html files. If you want to test your own html files I think you can head in a couple of directions, I came up with these:

first option: Create a way to load the parts of you app that you want to test into the main testing html file. How to do this depends a lot on your application setup. It is probably well-suited for a modular system. Just include the javascript from your application and test it. Not so good for full-page-html tests.

second option: Open new windows with the pages to test from the main testing html file (from within phantom that is). You can open a page using window.open() just like a normal browser. I created a proof of concept like this:

describe('hello web', function () {
        it('world', function (done) {
            var windowReference = window.open("fileundertest.html");

            // windowReference.onload didn't work for me, so I resorted to this solution
            var intervalId = window.setInterval(function () {
                if (windowReference.document && windowReference.document.readyState === 'complete') {
                    window.clearInterval(intervalId);
                    expect(windowReference.document.title).to.equal("File Under Test");
                    done();
                } else {
                    console.log('not ready yet');
                }
            }, 10);
        });
    }
)

This solution is relatively simple, but has the same drawbacks as any page-loading solution: you never know when the page is fully initialized and have to resort to some sort of timeout/wait system to wait for the page to get into the correct state. If you want to test a lot of separate html files these delays start to add up. Additionally waiting for 'onload' on the page that I opened wouldn't work so I created my own function based on setInterval and a (non-perfect) test on the document that was being loaded. I found out there are differences in behavior between loading an html page from the filesystem and loading the same page via a web-server.

third option: Create a mocha test that you run nodejs-style from the command line, and launch phantomjs with a specific page as part of your mocha tests. This is what I'd say you need if your system really depends on html pages that are quite different from each other.

I quickly tested the third option, here is my test based on the example I found on the phantom page (which is an alternative solution to phantomjs that is used by mocha-phantomjs -- I've used neither for more than brief experiments so I cannot recommend which one to use)

'use strict';

var chai = require('chai'),
    phantom = require('phantom');

var expect = chai.expect;

describe('hello node', function () {
        it('world', function (done) {
            phantom.create(function (ph) {
                ph.createPage(function (page) {
                    page.open("http://www.google.com", function (status) {
                        console.log("opened google? ", status);
                        page.evaluate(function () { return document.title; }, function (result) {
                            console.log('Page title is ' + result);
                            ph.exit();
                            expect(result).to.equal("Google");
                            done();
                        });
                    });
                });
            });

        });
    }
)

While it is possible to test this way I'd say that maybe the overhead of the communication between the code in the phantom-world and the testing code in the nodejs world isn't worth it. You can of course move a lot of general functionality to a couple of helper functions, but you are still stuck with having to call page.evaluate() to perform specific tests on the page. The same issues with timeouts/waits as above apply.

As an aside: do already know CasperJS? Maybe it can be helpful for your setup should you choose to build something on 'plain' phantomjs.

like image 137
Simon Groenewolt Avatar answered Oct 14 '22 11:10

Simon Groenewolt