Coverage

0%
103
1
102

/home/ubuntu/src/github.com/dalekjs/grunt-dalek/tasks/dalekjs.js

0%
103
1
102
LineHitsSource
1/*!
2 *
3 * Copyright (c) 2013 Peter Foerger & Sebastian Golasch
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/**
25 * Run browser tests with dalak
26 *
27 * ## Getting Started
28 * This plugin requires Grunt `~0.4.1`
29 *
30 * If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
31 *
32 * ```bash
33 * npm install grunt-dalek --save-dev
34 * ```
35 *
36 * Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
37 *
38 * ```javascript
39 * grunt.loadNpmTasks('grunt-dalek');
40 * ```
41 *
42 * ## The "dalek" task
43 *
44 * ### Overview
45 * In your project's Gruntfile, add a section named `dalek` to the data object passed into `grunt.initConfig()`.
46 *
47 * ```javascript
48 * grunt.initConfig({
49 * dalek: {
50 * options: {
51 * // Task-specific options go here.
52 * },
53 * your_target: {
54 * // Target-specific file lists and/or options go here.
55 * },
56 * },
57 * })
58 * ```
59 *
60 * ### Options
61 *
62 * #### options.dalekfile
63 * Type: `Boolean`
64 * Default: `true`
65 *
66 * Grunt should load the config options from your Dalekfile
67 *
68 * #### options.browser
69 * Type: `Array`
70 * Default: `['phantomjs']`
71 *
72 * The browsers you would like to test
73 * Note: For other browsers than PhantomJS, you need to have the Dalek browser plugin installed.
74 *
75 * #### options.reporter
76 * Type: `Array`
77 * Default: `null`
78 *
79 * The reporters you would like to invoke
80 * Note: For other reporters than the grunt console output, you need to have the corresponding Dalek reporter plugin installed.
81 *
82 * #### options.advanced
83 * Type: `Object`
84 * Default: `null`
85 *
86 * All the options you else would define in your Dalekfile.
87 * This overwrites the contents of your Dalekfile.
88 *
89 * ## Examples
90 *
91 * ### Configuration Example
92 *
93 * Basic example of a Grunt config containing the dalek task.
94 *
95 * ```javascript
96 * grunt.initConfig({
97 * dalek: {
98 * dist: {
99 * src: ['test/example/test-github.js']
100 * }
101 * }
102 *
103 * });
104 *
105 * // Loads tasks located in the tasks directory.
106 * grunt.loadTasks('tasks');
107 *
108 * grunt.registerTask('default', ['dalek']);
109 * ```
110 *
111 * ### Multiple Files
112 *
113 * Running dalekjs against multiple files.
114 *
115 * ```javascript
116 * dalek: {
117 * dist: {
118 * src: ['test/example/test-dkd.js','test/example/test-github.js']
119 * }
120 * }
121 * ```
122 *
123 * ### Specifying Options
124 *
125 * ```javascript
126 * dalek: {
127 * options: {
128 * // invoke phantomjs, chrome & chrome canary
129 * browser: ['phantomjs', 'chrome', 'chrome:canary'],
130 * // generate an html & an jUnit report
131 * reporter: ['html', 'junit'],
132 * // don't load config from an Dalekfile
133 * dalekfile: false,
134 * // specify advanced options (that else would be in your Dalekfile)
135 * advanced: {
136 * // specify a port for chrome
137 * browsers: [{
138 * chrome: {
139 * port: 4000
140 * }
141 * }]
142 * }
143 * }
144 * }
145 * ```
146 *
147 * @part Grunt
148 * @api
149 */
150
1511module.exports = function(grunt) {
1520 'use strict';
153
1540 grunt.registerMultiTask('dalek', 'dalekjs browser tests', function dalekMultiTask () {
155 // tagging this task as async
1560 var done = this.async();
157
158 // load dalek
1590 var Dalek = require('dalekjs');
160
161 // yeah, globals, but stored for a good reason
1620 var currentTest;
1630 var currentBrowser;
1640 var failedAssertions = [];
165
166 // setting defaults for user set options
1670 var options = this.options();
1680 var driver = [];
1690 var reporter = [];
1700 var browser = [];
171
172 // setting defaults for advanced & plugin options
1730 var loadDalekfile = true;
1740 var advanced = {};
175
176 // check if options are available,
177 // else use daleks defaults
1780 if (options) {
1790 driver = options.driver && Array.isArray(options.driver) ? options.driver : driver;
1800 reporter = options.reporter && Array.isArray(options.reporter) ? options.reporter : reporter;
1810 browser = options.browser && Array.isArray(options.browser) ? options.browser : browser;
182 }
183
184 // check if advanced options are available
1850 if (options) {
1860 loadDalekfile = (options.dalekfile || options.dalekfile === false) ? options.dalekfile : loadDalekfile;
1870 if (options.advanced && typeof options.advanced === 'object') {
1880 advanced = options.advanced;
189 }
190
1910 advanced.dalekfile = loadDalekfile;
192 }
193
194 // instanciate dalek with obligatory options
1950 var dalek = new Dalek({
196 tests: this.filesSrc,
197 driver: driver,
198 reporter: reporter,
199 browser: browser,
200 logLevel: -1,
201 noColors: true,
202 noSymbols: true,
203 advanced: advanced
204 });
205
206 // grunt logging
207 // -------------
208
209 // If options.force then log an error, otherwise exit with a warning
2100 var warnUnlessForced = function (message) {
2110 if (options && options.force) {
2120 grunt.log.error(message);
213 } else {
2140 grunt.warn(message);
215 }
216 };
217
218 // Log failed assertions
2190 var logFailedAssertions = function() {
2200 var assertion;
221 // Print each assertion error.
2220 while (assertion = failedAssertions.shift()) {
2230 grunt.verbose.or.error(assertion.testName);
2240 grunt.log.error('Message: ' + formatMessage(assertion.message));
2250 if (assertion.actual !== assertion.expected) {
2260 grunt.log.error('Actual: ' + formatMessage(assertion.actual));
2270 grunt.log.error('Expected: ' + formatMessage(assertion.expected));
228 }
2290 if (assertion.source) {
2300 grunt.log.error('Source:' + formatMessage(assertion.source.replace(/ {4}(at)/g, ' $1')));
231 }
2320 grunt.log.error('Browser: ' + formatMessage(assertion.browserName));
2330 grunt.log.writeln();
234 }
235 };
236
237 // Allow an error message to retain its color when split across multiple lines.
2380 var formatMessage = function(str) {
2390 return String(str).split('\n').map(function(s) { return s.magenta; }).join('\n');
240 };
241
242 // register browser launcher event
2430 dalek.reporterEvents.on('report:run:browser', function reportRunBrowser (browserName) {
2440 currentBrowser = browserName;
245 });
246
247 // register logging for runner finished
2480 dalek.reporterEvents.on('report:runner:finished', function reportRunnerFinished (data) {
2490 var message = '';
250 // Print assertion errors here, if verbose mode is disabled.
2510 if (!data.status) {
2520 message = data.assertionsPassed + '/' + data.assertions + ' assertions passed (';
2530 message += data.elapsedTime.hours ? data.elapsedTime.hours + ' hours' : '';
2540 message += data.elapsedTime.minutes ? data.elapsedTime.minutes + ' min' : '';
2550 message += data.elapsedTime.seconds ? Math.round(data.elapsedTime.seconds * Math.pow(10, 2)) / Math.pow(10, 2) + ' sec' : '';
2560 message += ')';
257
2580 if (!grunt.option('verbose')) {
2590 grunt.log.writeln();
2600 logFailedAssertions();
261 }
262
2630 grunt.log.writeln();
2640 warnUnlessForced(message);
265
2660 setTimeout(function () {
2670 done(false);
268 }, 250);
2690 } else if (data.assertions === 0) {
270 // create 0 assertions message
2710 message = '0/0 assertions ran (';
2720 message += data.elapsedTime.hours ? data.elapsedTime.hours + ' hours' : '';
2730 message += data.elapsedTime.minutes ? data.elapsedTime.minutes + ' min' : '';
2740 message += data.elapsedTime.seconds ? Math.round(data.elapsedTime.seconds * Math.pow(10, 2)) / Math.pow(10, 2) + ' sec' : '';
2750 message += ')';
276
277 // timeout hack to enable shutdown of 3rd party processes
2780 setTimeout(function () {
2790 warnUnlessForced(message);
2800 done(false);
281 }, 250);
282 } else {
283 // create passed assertions message
2840 message = data.assertions + '/' + data.assertions + ' assertions passed (';
2850 message += data.elapsedTime.hours ? data.elapsedTime.hours + ' hours' : '';
2860 message += data.elapsedTime.minutes ? data.elapsedTime.minutes + ' min' : '';
2870 message += data.elapsedTime.seconds ? Math.round(data.elapsedTime.seconds * Math.pow(10, 2)) / Math.pow(10, 2) + ' sec' : '';
2880 message += ')';
289
2900 setTimeout(function () {
2910 grunt.log.writeln('');
2920 grunt.log.ok(message);
2930 done(true);
294 }, 250);
295 }
296 });
297
298 // log assertion
2990 dalek.reporterEvents.on('report:assertion', function(data) {
3000 if (!data.success) {
3010 failedAssertions.push({
302 actual: data.value,
303 expected: data.expected,
304 message: (data.message || 'No message'),
305 source: data.type,
306 testName: currentTest,
307 browserName: currentBrowser
308 });
309 }
310 });
311
312 // log test started
3130 dalek.reporterEvents.on('report:test:started', function(data) {
3140 currentTest = data.name;
3150 grunt.verbose.write(currentTest + '...');
316 });
317
318 // log test finished
3190 dalek.reporterEvents.on('report:test:finished', function(data) {
320 // Log errors if necessary, otherwise success.
3210 if (!data.status) {
322 // list assertions
3230 if (grunt.option('verbose')) {
3240 grunt.log.error();
3250 logFailedAssertions();
326 } else {
3270 grunt.log.write('F'.red);
328 }
329 } else {
3300 grunt.verbose.ok().or.write('.');
331 }
332 });
333
334 // All tests have been run.
335
336 // log error
3370 dalek.reporterEvents.on('error', function(message) {
3380 setTimeout(function () {
3390 if (options && options.force) {
3400 grunt.log.error(message);
341 } else {
3420 grunt.warn(message);
343 }
344
3450 done(false);
346 }, 250);
347 });
348
349 // log warning
3500 dalek.reporterEvents.on('warning', function(message) {
3510 grunt.log.write('>> Warning: '.yellow + message + '\n');
352 });
353
354 // Re-broadcast dalek events on grunt.event.
3550 dalek.reporterEvents.onAny(function() {
3560 var args = [this.event].concat(grunt.util.toArray(arguments));
3570 args[0] = 'dalek:' + args[0];
3580 grunt.event.emit.apply(grunt.event, args);
359 });
360
361 // start dalek
3620 dalek.run();
363 });
364};