Coverage

59%
69
41
28

/home/ubuntu/src/github.com/dalekjs/dalek-reporter-json/index.js

59%
69
41
28
LineHitsSource
1/*!
2 *
3 * Copyright (c) 2013 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
251'use strict';
26
27// ext. libs
281var fs = require('fs');
291var path = require('path');
30
31// int. global
321var reporter = null;
33
34/**
35 * The JSON reporter can produce a file with the results of your testrun.
36 *
37 * The reporter can be installed with the following command:
38 * ```
39 * $ npm install dalek-reporter-json --save-dev
40 * ```
41 *
42 * The file will follow the following format. This is a first draft and will
43 * definitly change in future versions.
44 *
45 * ```javascript
46 * {
47 * "tests": [
48 * {
49 * "id": "test806",
50 * "name": "Can get !url (OK, TDD style, message, chained)",
51 * "browser": "Chrome",
52 * "status": true,
53 * "passedAssertions": 1,
54 * "failedAssertions": 0,
55 * "actions": [
56 * {
57 * "value": "http://localhost:5000/index.html",
58 * "type": "open",
59 * "uuid": "6ea84fc0-58bf-4e1f-bb9c-f035c6e6fae2",
60 * "kind": "action",
61 * "isAction": true
62 * },
63 * {
64 * "success": true,
65 * "expected": "http://localhost:5000/guinea.html",
66 * "value": "http://localhost:5000/index.html",
67 * "message": "Url is not whatever",
68 * "type": "url",
69 * "kind": "assertion",
70 * "isAssertion": true
71 * }
72 * ]
73 * }
74 * ],
75 * "elapsedTime": {
76 * "minutes": 1,
77 * "seconds": 43.328535046
78 * },
79 * "status": true,
80 * "assertions": 1,
81 * "assertionsFailed": 0,
82 * "assertionsPassed": 1
83 * }
84 * ```
85 *
86 * By default the file will be written to `report/dalek.json`,
87 * you can change this by adding a config option to the your Dalekfile
88 *
89 * ```javascript
90 * "json-reporter": {
91 * "dest": "your/folder/your_file.json"
92 * }
93 * ```
94 *
95 * @class Reporter
96 * @constructor
97 * @part JSON
98 * @api
99 */
100
1011function Reporter (opts) {
1021 this.events = opts.events;
1031 this.config = opts.config;
1041 this.data = {};
1051 this.actionQueue = [];
1061 this.data.tests = [];
1071 this.browser = null;
108
1091 var defaultReportFolder = 'report';
1101 this.dest = this.config.get('json-reporter') && this.config.get('json-reporter').dest ? this.config.get('json-reporter').dest : defaultReportFolder;
111
1121 this.startListening();
113}
114
115/**
116 * @module Reporter
117 */
118
1191module.exports = function (opts) {
1206 if (reporter === null) {
1211 reporter = new Reporter(opts);
122 }
123
1246 return reporter;
125};
126
1271Reporter.prototype = {
128
129 /**
130 * Connects to all the event listeners
131 *
132 * @method startListening
133 * @chainable
134 */
135
136 startListening: function () {
1371 this.events.on('report:run:browser', this.runBrowser.bind(this));
1381 this.events.on('report:assertion', this.assertion.bind(this));
1391 this.events.on('report:action', this.action.bind(this));
1401 this.events.on('report:test:started', this.testStarted.bind(this));
1411 this.events.on('report:test:finished', this.testFinished.bind(this));
1421 this.events.on('report:runner:finished', this.runnerFinished.bind(this));
1431 this.events.on('report:log:user',this.messageLog.bind(this));
1441 this.events.on('report:screenshot',this.screenshot.bind(this));
1451 return this;
146 },
147
148 /**
149 * Stores the current browser name
150 *
151 * @method runBrowser
152 * @param {string} browser Browser name
153 * @chainable
154 */
155
156 runBrowser: function (browser) {
1573 this.browser = browser;
1583 return this;
159 },
160
161 /**
162 * Generates JSON for an action
163 *
164 * @method action
165 * @param {object} data Event data
166 * @chainable
167 */
168
169 action: function (data) {
1701 data.kind = 'action';
1711 this.actionQueue.push(data);
1721 return this;
173 },
174
175 /**
176 * Generates JSON for an assertion
177 *
178 * @method assertion
179 * @param {object} data Event data
180 * @chainable
181 */
182
183 assertion: function (data) {
1841 data.kind = 'assertion';
1851 this.actionQueue.push(data);
1861 return this;
187 },
188
189 /**
190 * Sets up a new testcase
191 *
192 * @method testStarted
193 * @param {object} data Event data
194 * @chainable
195 */
196
197 testStarted: function (data) {
1981 this.currentTest = data;
1991 this.actionQueue = [];
2001 return this;
201 },
202
203 /**
204 * Writes data for a finished testcase
205 *
206 * @method testFinished
207 * @param {object} data Event data
208 * @chainable
209 */
210
211 testFinished: function (data) {
2121 this.data.tests.push({
213 id: data.id,
214 name: data.name,
215 browser: this.browser,
216 status: data.status,
217 passedAssertions: data.passedAssertions,
218 failedAssertions: data.failedAssertions,
219 actions: this.actionQueue
220 });
2211 return this;
222 },
223
224 /**
225 * Serializes JSON and writes file to the file system
226 *
227 * @method runnerFinished
228 * @param {object} data Event data
229 * @chainable
230 */
231
232 runnerFinished: function (data) {
2330 this.data.elapsedTime = data.elapsedTime;
2340 this.data.status = data.status;
2350 this.data.assertions = data.assertions;
2360 this.data.assertionsFailed = data.assertionsFailed;
2370 this.data.assertionsPassed = data.assertionsPassed;
238
2390 var contents = JSON.stringify(this.data, false, 4);
240
2410 if (path.extname(this.dest) !== '.json') {
2420 this.dest = this.dest + '/dalek.json';
243 }
244
2450 this.events.emit('report:written', {type: 'json', dest: this.dest});
2460 this._recursiveMakeDirSync(path.dirname(this.dest.replace(path.basename(this.dest, ''))));
2470 fs.writeFileSync(this.dest, contents, 'utf8');
2480 return this;
249 },
250
251 /**
252 * Generates JSON for a message.log
253 *
254 * @method assertion
255 * @param {object} data Event data
256 * @chainable
257 */
258
259 messageLog: function(data) {
2600 var logData = {
261 kind: 'message',
262 message: data
263 };
2640 this.actionQueue.push(logData);
2650 return this;
266 },
267
268 /**
269 * Generates JSON for a screenshot
270 *
271 * @method assertion
272 * @param {object} data Event data
273 * @chainable
274 */
275
276 screenshot : function(data) {
2770 data.kind = 'screenshot';
2780 this.actionQueue.push(data);
2790 return this;
280 },
281
282
283 /**
284 * Helper method to generate deeper nested directory structures
285 *
286 * @method _recursiveMakeDirSync
287 * @param {string} path PAth to create
288 */
289
290 _recursiveMakeDirSync: function (path) {
2910 var pathSep = require('path').sep;
2920 var dirs = path.split(pathSep);
2930 var root = '';
294
2950 while (dirs.length > 0) {
2960 var dir = dirs.shift();
2970 if (dir === '') {
2980 root = pathSep;
299 }
3000 if (!fs.existsSync(root + dir)) {
3010 fs.mkdirSync(root + dir);
302 }
3030 root += dir + pathSep;
304 }
305 }
306};
307