Nightmare.js allows you to automate HTTP requests in Node.js, which you can use to download files from sites, check your e-mail, runt integration tests, etc.
The last couple of years, more and more logic have appeared on the client-side of web sites. Thanks to Single Page Applications (SPA) instead of server-side frameworks, we are able to cache views on the client and just get the data from the backend.
While doing this, it is more important than ever to test our sites in different browsers, versions, devices etc. One popular framework to do this is Karma (http://karma-runner.github.io/0.12/index.html), which is created by Google and often used with Angular.js. But sometimes you just want to go to an url, enter some input, click some buttons and make sure the expected result shows up on the web page, and do all this in the background with a headless browser such as PhantomJS (http://phantomjs.org/) or SlimerJS (http://slimerjs.org/). And since you don’t actually see the output, you might want to grab a screenshot while running the tests to make sure it looks correct with the styling.
Sweet dreams with Nightmare.js
Recently I found a library that works great for these kind of tasks. It’s called Nightmare.js (http://www.nightmarejs.org/) and is, as it says in the headline, “A high level wrapper for Phantomjs”. And not just that, the API is absolutely stunning.
The example shown on the start page for Nightmare.js shows us an example of how to do a simple search on Yahoo:
.type('input[title="Search"]', 'github nightmare')
Nightmare.js also allows us to write plugins for common tasks, such as logging in to a site before running the specific logic.
So, we know what we can do, but when could we actually use this? Some tasks that I can think of where this could be useful could be:
- Downloading files from a web site.
- Logging in to web shops such as Amazon and get our order information.
- Logging in to the webmail to get the number of unread e-mails.
- Use this to make end-to-end tests.
Get the necessary tools
To be able to run these tests we need a couple of tools and frameworks.
First of all, we need to install the latest version of Node.js with npm (http://nodejs.org/). We also need to install Python 2.7.x (https://www.python.org/). Make sure to install 2.7 and not 3.x since the latter is not officially supported by node-gyp, which is used to compile some components.
When both Node.js and Python is installed, we start by creating a new npm package inside an empty folder.
Navigate to an empty folder in your terminal/powershell/command prompt or what you are using. Start by running npm init and click enter until you are done (you don’t have to fill in all information yet, you can do that later by editing package.json). You should have an package.json file in your project now, which allows you to save packages and developer dependencies in your package.json.
The next step is to install Mocha (global), Chai and Nightmare.js.
Mocha (may require sudo on Linux and Mac OS X since it is a global module):
> npm install -g mocha
> npm install --save-dev chai
> npm install --save-dev nightmare
The next step is to create a test folder with an index.js in it.
We have all files needed to create the tests, but we need something to test as well. I have prepared a simple web site, which you can download here:
Clone the repository and go to the server folder.
To start the server, run these commands:
- npm install
- node index.js
You should now be able to use your browser to go to http://localhost:3000.
Closing the terminal will shutdown the server, so to be able to test this site, you will need to keep that open. The tests should be run in another terminal window.
Start the tests
You should have everything you need to run the tests now.
We are going to create three different tests for this web site, using Mocha, Chai and Nightmare.js.
To make it easier to explain how it works, I will just paste the full tests here:
Mocha gives us describe() and it(), which contains the tests. By adding “done” as parameters in the callback function, we can use these tests with asynchronous calls. If we omit that, it will just run the tests without waiting for the result, and always return success.
With Chai (and “should”) we can tell the tests that some variable “should” have the expected value. Chai also contains “expect” and “assert”. You can use any of them, you will just have to import the right one in the file.
And by using Nightmare.js, we can make these simple calls to the url, where we perform some tasks and wait for the result.
Spinning up a new PhantomJS browser and going through the steps for each task takes a while, and since the standard timeout in Mocha is set to 2000 milliseconds, we have to change that. I have been using 15000 milliseconds here, which seems to be a good number for this test (it takes 8-9 seconds per test on my machine). Because of the time to run all tests, you probably do not want to use this in your normal test runner (like “grunt test”), but running it from time to time to make sure everything still works or running it from the build server could be a good plan, and you should not use this to do performance tests.
To run the tests, simply go to the root directory for your tests (where you have your package.json) and type:
The result should look like this:
That´s it! We are now able to run tests on any website by just entering the url, and doing the tasks needed to get the information we ask for.
The full project used here can be found here: