ghoulies

0.0.2 • Public • Published

ghoulies is a full-stack JavaScript integration test runner that allows you to run a NodeJS server, and a JavaScript client in the same unit test and write BDD-style integration tests in a simple and natural way.

ghoulies works by spawning a headless JSDom pointed to your development NodeJS server application. The client-side API ghoulie exposes an event emitter that can be listened to in your server-side tests.

So far, ghoulies has only been used alongside webpack (to build the app) and mocha/chai (for running the tests) but should work with other JavaScript test and build systems. Ghoulies may also be useful for those not even using Node, but are interested in using mocha/jasmine/jest for their client-side integration tests.

Installation


Prerequisites

Install your test and build systems (mocha, chai, webpack etc.):

npm install mocha --save
npm install chai --save
npm install webpack --save -g

Install nodemon to watch for file changes:

npm install nodemon --save -g

Install

Install both ghoulies (server-side interface) and ghoulie (client-side interface):

npm install ghoulies --save
npm install ghoulie --save

Set Up Your Unit Test (Using Mocha)


Make a directory specifically for ghoulie tests:

mkdir /test/ghoulie

Create a new unit test script (eg. /test/ghoulies/myghoulie.test.js):

var chai = require('chai');
var expect = chai.expect;

// include ghoulies
var ghoulies = require('ghoulies');

// url of your local development server
var url = "http://localhost:1337";

before(function (done) {	
	 ghoulies.client({
		url: url,
		globals: true,		// make window, document, and jquery global objects
		jquery: true		// (optional) include jquery if it isn't included in the app
	}, function (window, ghoulie) {
		done();
	});
});

describe('ghoulies', () => {
	it('loads a headless client and renders my application', (done) => {
	
		// ghoulies exposes a headless browser window object
		expect(typeof window).to.be.equal('object');
		
		// see if it loaded the app successfully
		console.log(document.body.innerHTML);
		
		// use jQuery to inspect the dom
		var myAppNode = $('#myapp');
		expect(myAppNode.length).to.be.equal(1);
		expect(myAppNode.get(0)].nodeName).to.be.equal('DIV');
		
		// initialize ghoulie at the end of the first test
		ghoulie.init();
		
		done();
	});
});

As configured above, the ghoulies.client() method will instantiate an instance of JSDom and load the entire contents of your web application running on http://localhost:1337

In a ghoulie test you can use JQuery or standard DOM operations to just as you would in a browser. It also exposes an API for emitting events and listening for events used by your unit tests.

Server-Side Setup


Ghoulies requires your webserver be fully booted and ready to go before the test proceeds. Ghoulies also exposes an EventEmitter to capture when the server is loaded.

If using ExpressJS, emit an event after the http server is running:

var express = require('express');
var app = express();

// include ghoulies
var ghoulies = require('ghoulies');

app.listen(8000, function () {
	
	// emit server event
	ghoulies.emit('SERVER_LOADED', app);

});

Create a unit test bootstrap script named /test/ghoulies/config.js, it listens for the 'SERVER_LOADED' event before continuing with the rest of the test suite:

before(function(done) {
	ghoulies.once('SERVER_LOADED', function(app) {
		// store a reference to the app for use in the tests
		ghoulies.app = app;		
		done();
	});
});

Client-To-Server Events


The client-side API is exposed by the ghoulie npm module. Your client-side application will need to include this module and emit events after important actions take place (eg. after data is loaded or a portion of your app is rendered). The unit tests use ghoulies to spawn the client browser and listen to the events emitted by ghoulie.

Somewhere in your JavaScript client-side code emit a client event:

// include ghoulie
var ghoulie = require('ghoulie');

// emit client event
var arg1 = 123;
var arg2 = "abc";
ghoulie.emit('CLIENT_LOADED', arg1, arg2);

Then add an event listener in your unit test /test/ghoulies/myghoulie.test.js to listen for the 'CLIENT_LOADED' event:

define("a ghoulie test", function() {
	it("listens for client events", function(done) {
		
		// wait for client event
		ghoulie.once('CLIENT_LOADED', function()arg1, arg2, ...) {
			
			// output useful data in the terminal
			ghoulie.log('CLIENT_LOADED!', arg1, arg2);
			
			expect(arg1).to.be.equal(123);
			expect(arg2).to.be.equal("abc");
			
			done();
		});
		
		// initialize ghoulie at the end of the first test
		ghoulie.init();
	
	});
});

Server-to-Client Events


You can also emit events from within a ghoulie test and have your client listen and respond to them. In this manner you can force the client to reload data from the server, render a new part of the application, or some other action:

Somewhere in your unit test, emit an event:

ghoulie.emit('RELOAD_SOME_DATA');

Somewhere in your client app, listen to the event:

ghoulie.once('RELOAD_SOME_DATA', function() {
	
	// fetch data from server
	$.ajax({url: "/api/data", success: function(result) {
        
        // emit new event
        ghoulie.emit('RELOADED_DATA', result);
        
    }});
	
});

Update your unit test to listen to the 'RELOADED_DATA' event:

ghoulie.on('RELOADED_DATA', function(result) {
	
	// perform test on the data
	expect(typeof result).to.be.equal('object');
	
	// can also perform DOM/JQuery commands to see if client rendered the new data
	$(...)
});

Ghoulies NPM Commands


The ghoulies npm commands are:

npm run ghoulies          # runs the build, then runs the tests
npm run ghoulies:build    # bundles your client app (eg. webpack/gulp)
npm run ghoulies:test     # runs your tests (eg. mocha/jasmine)
npm run ghoulies:watch    # runs your tests and watch for changes (nodemon)

These commands will need to be manually added to your project's package.json and modified accordingly depending on your build and test systems.

This example is for webpack and mocha:

...
	"scripts": {
		...
		"ghoulies": "npm run ghoulies:build; npm run ghoulies:test",
		"ghoulies:test": "NODE_ENV=test mocha --timeout 60000 --recursive ./test/ghoulies/config.js ./test/ghoulies",
		"ghoulies:watch": "npm run ghoulies:build; NODE_ENV=test nodemon -w ./test/ghoulies -e js -x npm run ghoulies:test",
		"ghoulies:build": "NODE_ENV=test node node_modules/webpack/bin/webpack.js -p --progress"
	}
...

It is recommended to experiment with running ghoulies:build and ghoulies:test independently and be sure they work properly before trying ghoulies and ghoulies:watch

Examples


The best example to date of a ghoulie test is the one supplied in the sails-react-redux-boilerplate example application which uses SailsJS server, ReactJS client, webpack build, and mocha tests.

See: https://github.com/jaxcore/sails-react-redux-boilerplate/blob/master/test/ghoulies/todos.test.js

To-do


  • console/REPL client

  • listen to react/redux events

  • command line interface

  • stand alone example app (simple expressjs example)

  • experiment with multiple client instances

Readme

Keywords

none

Package Sidebar

Install

npm i ghoulies

Weekly Downloads

1

Version

0.0.2

License

MIT

Last publish

Collaborators

  • dsteinman