1 | const Base = require('mocha/lib/reporters/base');
|
2 | const mochaPkg = require('mocha/package.json');
|
3 | const uuid = require('uuid');
|
4 | const marge = require('mochawesome-report-generator');
|
5 | const margePkg = require('mochawesome-report-generator/package.json');
|
6 | const conf = require('./config');
|
7 | const utils = require('./utils');
|
8 | const pkg = require('../package.json');
|
9 | const Mocha = require('mocha');
|
10 | const { EVENT_SUITE_END } = Mocha.Runner.constants;
|
11 |
|
12 |
|
13 | const { log, mapSuites } = utils;
|
14 |
|
15 |
|
16 | const testTotals = {
|
17 | registered: 0,
|
18 | skipped: 0
|
19 | }
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | function done(output, options, config, failures, exit) {
|
35 | return marge
|
36 | .create(output, options)
|
37 | .then(([htmlFile, jsonFile]) => {
|
38 | if (!htmlFile && !jsonFile) {
|
39 | log('No files were generated', 'warn', config);
|
40 | } else {
|
41 | jsonFile && log(`Report JSON saved to ${jsonFile}`, null, config);
|
42 | htmlFile && log(`Report HTML saved to ${htmlFile}`, null, config);
|
43 | }
|
44 | })
|
45 | .catch(err => {
|
46 | log(err, 'error', config);
|
47 | })
|
48 | .then(() => {
|
49 | exit && exit(failures > 0 ? 1 : 0);
|
50 | });
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | function consoleReporter(reporter) {
|
65 | if (reporter) {
|
66 | try {
|
67 | return require(`mocha/lib/reporters/${reporter}`);
|
68 | } catch (e) {
|
69 | log(`Unknown console reporter '${reporter}', defaulting to spec`);
|
70 | }
|
71 | }
|
72 |
|
73 | return require('mocha/lib/reporters/spec');
|
74 | }
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | function Mochawesome(runner, options) {
|
83 |
|
84 | this.config = conf(options);
|
85 |
|
86 |
|
87 | if (!runner.stats) {
|
88 | const createStatsCollector = require('mocha/lib/stats-collector');
|
89 | createStatsCollector(runner);
|
90 | }
|
91 |
|
92 |
|
93 | const reporterOptions = {
|
94 | ...options.reporterOptions,
|
95 | reportFilename: this.config.reportFilename,
|
96 | saveHtml: this.config.saveHtml,
|
97 | saveJson: this.config.saveJson,
|
98 | };
|
99 |
|
100 |
|
101 |
|
102 | this.done = (failures, exit) =>
|
103 | done(this.output, reporterOptions, this.config, failures, exit);
|
104 |
|
105 |
|
106 | testTotals.registered = 0;
|
107 | testTotals.skipped = 0;
|
108 |
|
109 |
|
110 | Base.call(this, runner);
|
111 |
|
112 | const reporterName = reporterOptions.consoleReporter;
|
113 | if (reporterName !== 'none') {
|
114 | const ConsoleReporter = consoleReporter(reporterName);
|
115 | new ConsoleReporter(runner);
|
116 | }
|
117 |
|
118 | let endCalled = false;
|
119 |
|
120 |
|
121 | ['suite', 'test', 'hook', 'pending'].forEach(type => {
|
122 | runner.on(type, item => {
|
123 | item.uuid = uuid.v4();
|
124 | });
|
125 | });
|
126 |
|
127 |
|
128 | if (runner.constructor.name === 'ParallelBufferedRunner') {
|
129 | const setSuiteDefaults = suite => {
|
130 | [
|
131 | 'suites',
|
132 | 'tests',
|
133 | '_beforeAll',
|
134 | '_beforeEach',
|
135 | '_afterEach',
|
136 | '_afterAll',
|
137 | ].forEach(field => {
|
138 | suite[field] = suite[field] || [];
|
139 | });
|
140 | suite.suites.forEach(it => setSuiteDefaults(it));
|
141 | };
|
142 |
|
143 | runner.on(EVENT_SUITE_END, function (suite) {
|
144 | if (suite.root) {
|
145 | setSuiteDefaults(suite);
|
146 | runner.suite.suites.push(...suite.suites)
|
147 | }
|
148 | });
|
149 | }
|
150 |
|
151 |
|
152 | runner.on('end', () => {
|
153 | try {
|
154 |
|
155 | if (!endCalled) {
|
156 |
|
157 |
|
158 | endCalled = true;
|
159 |
|
160 | const rootSuite = mapSuites(
|
161 | this.runner.suite,
|
162 | testTotals,
|
163 | this.config
|
164 | );
|
165 |
|
166 | const obj = {
|
167 | stats: this.stats,
|
168 | results: [rootSuite],
|
169 | meta: {
|
170 | mocha: {
|
171 | version: mochaPkg.version,
|
172 | },
|
173 | mochawesome: {
|
174 | options: this.config,
|
175 | version: pkg.version,
|
176 | },
|
177 | marge: {
|
178 | options: options.reporterOptions,
|
179 | version: margePkg.version,
|
180 | },
|
181 | },
|
182 | };
|
183 |
|
184 | obj.stats.testsRegistered = testTotals.registered;
|
185 |
|
186 | const { passes, failures, pending, tests, testsRegistered } = obj.stats;
|
187 | const passPercentage = (passes / (testsRegistered - pending)) * 100;
|
188 | const pendingPercentage = (pending / testsRegistered) * 100;
|
189 |
|
190 | obj.stats.passPercent = passPercentage;
|
191 | obj.stats.pendingPercent = pendingPercentage;
|
192 | obj.stats.other = passes + failures + pending - tests;
|
193 | obj.stats.hasOther = obj.stats.other > 0;
|
194 | obj.stats.skipped = testTotals.skipped;
|
195 | obj.stats.hasSkipped = obj.stats.skipped > 0;
|
196 | obj.stats.failures -= obj.stats.other;
|
197 |
|
198 |
|
199 | this.output = obj;
|
200 | }
|
201 | } catch (e) {
|
202 |
|
203 |
|
204 |
|
205 | log(`Problem with mochawesome: ${e.stack}`, 'error');
|
206 | }
|
207 | });
|
208 | }
|
209 |
|
210 | module.exports = Mochawesome;
|