UNPKG

2.85 kBJavaScriptView Raw
1'use strict';
2/**
3 * @module JSON
4 */
5/**
6 * Module dependencies.
7 */
8
9var Base = require('./base');
10var constants = require('../runner').constants;
11var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
12var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
13var EVENT_TEST_END = constants.EVENT_TEST_END;
14var EVENT_RUN_END = constants.EVENT_RUN_END;
15var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
16
17/**
18 * Expose `JSON`.
19 */
20
21exports = module.exports = JSONReporter;
22
23/**
24 * Constructs a new `JSON` reporter instance.
25 *
26 * @public
27 * @class JSON
28 * @memberof Mocha.reporters
29 * @extends Mocha.reporters.Base
30 * @param {Runner} runner - Instance triggers reporter actions.
31 * @param {Object} [options] - runner options
32 */
33function JSONReporter(runner, options) {
34 Base.call(this, runner, options);
35
36 var self = this;
37 var tests = [];
38 var pending = [];
39 var failures = [];
40 var passes = [];
41
42 runner.on(EVENT_TEST_END, function(test) {
43 tests.push(test);
44 });
45
46 runner.on(EVENT_TEST_PASS, function(test) {
47 passes.push(test);
48 });
49
50 runner.on(EVENT_TEST_FAIL, function(test) {
51 failures.push(test);
52 });
53
54 runner.on(EVENT_TEST_PENDING, function(test) {
55 pending.push(test);
56 });
57
58 runner.once(EVENT_RUN_END, function() {
59 var obj = {
60 stats: self.stats,
61 tests: tests.map(clean),
62 pending: pending.map(clean),
63 failures: failures.map(clean),
64 passes: passes.map(clean)
65 };
66
67 runner.testResults = obj;
68
69 process.stdout.write(JSON.stringify(obj, null, 2));
70 });
71}
72
73/**
74 * Return a plain-object representation of `test`
75 * free of cyclic properties etc.
76 *
77 * @private
78 * @param {Object} test
79 * @return {Object}
80 */
81function clean(test) {
82 var err = test.err || {};
83 if (err instanceof Error) {
84 err = errorJSON(err);
85 }
86
87 return {
88 title: test.title,
89 fullTitle: test.fullTitle(),
90 file: test.file,
91 duration: test.duration,
92 currentRetry: test.currentRetry(),
93 speed: test.speed,
94 err: cleanCycles(err)
95 };
96}
97
98/**
99 * Replaces any circular references inside `obj` with '[object Object]'
100 *
101 * @private
102 * @param {Object} obj
103 * @return {Object}
104 */
105function cleanCycles(obj) {
106 var cache = [];
107 return JSON.parse(
108 JSON.stringify(obj, function(key, value) {
109 if (typeof value === 'object' && value !== null) {
110 if (cache.indexOf(value) !== -1) {
111 // Instead of going in a circle, we'll print [object Object]
112 return '' + value;
113 }
114 cache.push(value);
115 }
116
117 return value;
118 })
119 );
120}
121
122/**
123 * Transform an Error object into a JSON object.
124 *
125 * @private
126 * @param {Error} err
127 * @return {Object}
128 */
129function errorJSON(err) {
130 var res = {};
131 Object.getOwnPropertyNames(err).forEach(function(key) {
132 res[key] = err[key];
133 }, err);
134 return res;
135}
136
137JSONReporter.description = 'single JSON object';