UNPKG

3.01 kBJavaScriptView Raw
1// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
2// Node module: @loopback/build
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6'use strict';
7
8const util = require('util');
9
10const mochaHooks = {
11 beforeAll: startRecording,
12 beforeEach: saveCurrentTest,
13 afterEach: checkTestFailure,
14 afterAll: stopRecordingAndReportProblems,
15};
16
17module.exports = {
18 mochaHooks,
19};
20
21const INTERCEPTED_METHODS = ['log', 'error', 'warn'];
22const originalConsole = {};
23for (const m of INTERCEPTED_METHODS) {
24 originalConsole[m] = console[m];
25}
26
27let problems = [];
28let warnings = [];
29let currentTest;
30let someTestsFailed = false;
31
32function 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
45function recordForbiddenCall(methodName) {
46 return function recordForbiddenConsoleUsage(...args) {
47 // Print the original message
48 originalConsole[methodName](...args);
49
50 // Find out who called us.
51 // The first line is the error message,
52 // the second line points to this very function.
53 const stack = new Error().stack.split(/\n/).slice(2);
54
55 // Mocha reporters are allowed to call console functions
56 if (/[\/\\]node_modules[\/\\]mocha[\/\\]/.test(stack[0])) {
57 return;
58 }
59
60 // Record the problem otherwise
61 const msg = util.format(...args);
62 problems.push({msg, stack});
63 };
64}
65
66/** @this {Mocha.Context} */
67function saveCurrentTest() {
68 currentTest = this.currentTest;
69}
70
71function checkTestFailure() {
72 if (currentTest.state === 'failed') someTestsFailed = true;
73}
74
75function stopRecordingAndReportProblems() {
76 // First of all, restore original console methods
77 for (const m of INTERCEPTED_METHODS) {
78 console[m] = originalConsole[m];
79 }
80
81 // Don't complain about console logs when some of the tests have failed.
82 // It's a common practice to add temporary console logs while troubleshooting.
83 // NOTE: When running tests in parallel, console logs from non-failing tests
84 // executed in a different worker process are going to be still reported.
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 // print the first line of the console log
103 log(p.msg.split(/\n/)[0]);
104 // print the stack trace
105 log(p.stack.join('\n'));
106 // add an empty line as a delimiter
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}