1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | const util = require('util');
|
9 |
|
10 | const mochaHooks = {
|
11 | beforeAll: startRecording,
|
12 | beforeEach: saveCurrentTest,
|
13 | afterEach: checkTestFailure,
|
14 | afterAll: stopRecordingAndReportProblems,
|
15 | };
|
16 |
|
17 | module.exports = {
|
18 | mochaHooks,
|
19 | };
|
20 |
|
21 | const INTERCEPTED_METHODS = ['log', 'error', 'warn'];
|
22 | const originalConsole = {};
|
23 | for (const m of INTERCEPTED_METHODS) {
|
24 | originalConsole[m] = console[m];
|
25 | }
|
26 |
|
27 | let problems = [];
|
28 | let warnings = [];
|
29 | let currentTest;
|
30 | let someTestsFailed = false;
|
31 |
|
32 | function startRecording() {
|
33 | problems = [];
|
34 | warnings = [];
|
35 |
|
36 | for (const m of INTERCEPTED_METHODS) {
|
37 | console[m] = recordForbiddenCall(m);
|
38 | }
|
39 |
|
40 | process.on('warning', warning => {
|
41 | warnings.push(warning);
|
42 | });
|
43 | }
|
44 |
|
45 | function recordForbiddenCall(methodName) {
|
46 | return function recordForbiddenConsoleUsage(...args) {
|
47 |
|
48 | originalConsole[methodName](...args);
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | const stack = new Error().stack.split(/\n/).slice(2);
|
54 |
|
55 |
|
56 | if (/[\/\\]node_modules[\/\\]mocha[\/\\]/.test(stack[0])) {
|
57 | return;
|
58 | }
|
59 |
|
60 |
|
61 | const msg = util.format(...args);
|
62 | problems.push({msg, stack});
|
63 | };
|
64 | }
|
65 |
|
66 |
|
67 | function saveCurrentTest() {
|
68 | currentTest = this.currentTest;
|
69 | }
|
70 |
|
71 | function checkTestFailure() {
|
72 | if (currentTest.state === 'failed') someTestsFailed = true;
|
73 | }
|
74 |
|
75 | function stopRecordingAndReportProblems() {
|
76 |
|
77 | for (const m of INTERCEPTED_METHODS) {
|
78 | console[m] = originalConsole[m];
|
79 | }
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | if (someTestsFailed) return;
|
86 |
|
87 | if (!warnings.length) {
|
88 | for (const w of warnings) {
|
89 | originalConsole.warn(w);
|
90 | }
|
91 | }
|
92 | if (!problems.length) return;
|
93 | const log = originalConsole.log;
|
94 |
|
95 | log(
|
96 | '\n=== ATTENTION - INVALID USAGE OF CONSOLE LOGS DETECTED ===',
|
97 | '\nLearn more at',
|
98 | 'https://github.com/loopbackio/loopback-next/blob/master/packages/build/README.md#a-note-on-console-logs-printed-by-tests\n',
|
99 | );
|
100 |
|
101 | for (const p of problems) {
|
102 |
|
103 | log(p.msg.split(/\n/)[0]);
|
104 |
|
105 | log(p.stack.join('\n'));
|
106 |
|
107 | log('\n');
|
108 | }
|
109 |
|
110 | throw new Error(
|
111 | 'Invalid usage of console logs detected. See the text above for more details.',
|
112 | );
|
113 | }
|