diff --git a/.gitignore b/.gitignore index d06b7b9..bb60a70 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # Config files config/development.json config/production.json +config/test.json # Generated npm files node_modules diff --git a/Gruntfile.js b/Gruntfile.js index 77fd853..7404844 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,6 +34,15 @@ module.exports = function (grunt) { } }, + mochaTest: { + functional: { + src: ['test/functional/*.js'], + options: { + reporter: 'spec' + } + } + }, + nodemon: { development: { options: { @@ -43,6 +52,15 @@ module.exports = function (grunt) { NODE_ENV: 'development' } } + }, + test: { + options: { + cwd: __dirname, + file: 'index.js', + env: { + NODE_ENV: 'test' + } + } } }, @@ -84,12 +102,15 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-mocha-test'); grunt.loadNpmTasks('grunt-nodemon'); grunt.registerTask('lint', ['jshint']); + grunt.registerTask('test', ['mochaTest']); grunt.registerTask('compile', ['less', 'uglify']); grunt.registerTask('start', ['nodemon:development']); - grunt.registerTask('default', ['compile', 'lint']); - grunt.registerTask('ci', ['compile', 'lint']); + grunt.registerTask('start-test', ['nodemon:test']); + grunt.registerTask('default', ['compile', 'lint', 'test']); + grunt.registerTask('ci', ['lint', 'test']); }; \ No newline at end of file diff --git a/config/development.sample.json b/config/development.sample.json index 1a11916..433f43e 100644 --- a/config/development.sample.json +++ b/config/development.sample.json @@ -1,5 +1,4 @@ { - "webservice": "http://localhost:3000/", "port": 4000, "noindex": true, "readonly": false, diff --git a/config/test.sample.json b/config/test.sample.json new file mode 100644 index 0000000..23ffdab --- /dev/null +++ b/config/test.sample.json @@ -0,0 +1,12 @@ +{ + "port": 4000, + "noindex": true, + "readonly": false, + + "webservice": { + "database": "mongodb://localhost/pa11y-webservice-test", + "host": "0.0.0.0", + "port": 3000, + "cron": "0 30 0 * * *" + } +} \ No newline at end of file diff --git a/package.json b/package.json index 126db1c..ca8a98b 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,11 @@ "grunt-contrib-less": "~0.8", "grunt-contrib-uglify": "~0.2", "grunt-contrib-watch": "~0.5", - "grunt-nodemon": "~0.1" + "grunt-mocha-test": "~0.7", + "grunt-nodemon": "~0.1", + "jsdom": "~0.8", + "proclaim": "~2.0", + "request": "~2.27" }, "scripts": { diff --git a/test/functional/helper/navigate.js b/test/functional/helper/navigate.js new file mode 100644 index 0000000..8c6b684 --- /dev/null +++ b/test/functional/helper/navigate.js @@ -0,0 +1,44 @@ +'use strict'; + +var jsdom = require('jsdom'); +var request = require('request'); + +module.exports = createNavigator; + +// Create a navigate function +function createNavigator (baseUrl, store) { + return function (opts, callback) { + + store.body = null; + store.dom = null; + store.request = null; + store.response = null; + store.status = null; + store.window = null; + + request({ + url: baseUrl + opts.endpoint, + method: opts.method || 'GET', + body: opts.body, + json: true, + qs: opts.query + }, function (err, res, body) { + + store.body = body; + store.request = res.request; + store.response = res; + store.status = res.statusCode; + + jsdom.env( + store.body, + function (err, window) { + store.window = window; + store.dom = window.document; + callback(); + } + ); + + }); + + }; +} diff --git a/test/functional/index.js b/test/functional/index.js new file mode 100644 index 0000000..7044efd --- /dev/null +++ b/test/functional/index.js @@ -0,0 +1,31 @@ +/* global beforeEach, describe, it */ +/* jshint maxlen: 200, maxstatements: 20 */ +'use strict'; + +var assert = require('proclaim'); + +describe('GET /', function () { + + describe('with no query', function () { + + beforeEach(function (done) { + var req = { + method: 'GET', + endpoint: '/' + }; + this.navigate(req, done); + }); + + it('should send a 200 status', function () { + assert.strictEqual(this.last.status, 200); + }); + + it('should have an "Add new URL" button', function () { + var elem = this.last.dom.querySelectorAll('[data-test=add-task]'); + assert.strictEqual(elem.length, 1); + assert.strictEqual(elem[0].getAttribute('href'), '/new'); + }); + + }); + +}); diff --git a/test/functional/setup.js b/test/functional/setup.js new file mode 100644 index 0000000..992ffc6 --- /dev/null +++ b/test/functional/setup.js @@ -0,0 +1,26 @@ +/* global before */ +/* jshint maxlen: 200 */ +'use strict'; + +var config = require('../../config/test.json'); +var createNavigator = require('./helper/navigate'); +var request = require('request'); + +// Run before all tests +before(function (done) { + this.baseUrl = 'http://localhost:' + config.port; + this.last = {}; + this.navigate = createNavigator(this.baseUrl, this.last); + assertTestAppIsRunning(this.baseUrl, done); +}); + +// Check that the test application is running, and exit if not +function assertTestAppIsRunning (url, done) { + request(url, function (err) { + if (err) { + console.error('Error: Test app not started; run with `grunt start-test`'); + process.exit(1); + } + done(); + }); +} diff --git a/view/partial/tasks.html b/view/partial/tasks.html index bb6de38..4daec67 100644 --- a/view/partial/tasks.html +++ b/view/partial/tasks.html @@ -8,7 +8,7 @@

+

{{else}} - +

Add new URL

+