[tests] Disallow unasserted console.log (#28708)
Followup from https://github.com/facebook/react/pull/28693 and https://github.com/facebook/react/pull/28680. In CI, we fail the test for any unasserted console.log. In DEV, we don't fail, but you can still use the matchers and we'll assert on them.
Ricky committed
Apr 1, 2024 at 17:45 UTC
6e650109999e5f483fcb910ff20fe8148a566cb2
3 files changed
+44
-3
scripts/jest/matchers/__tests__/toWarnDev-test.js
+17
@@ -416,3 +416,20 @@ describe('toWarnDev', () => {
416
});
417
}
418
});
419
+
420
+describe('toLogDev', () => {
421
+ it('does not fail if warnings do not include a stack', () => {
422
+ expect(() => {
423
+ if (__DEV__) {
424
+ console.log('Hello');
425
+ }
426
+ }).toLogDev('Hello');
427
+ expect(() => {
428
+ if (__DEV__) {
429
+ console.log('Hello');
430
+ console.log('Good day');
431
+ console.log('Bye');
432
+ }
433
+ }).toLogDev(['Hello', 'Good day', 'Bye']);
434
+ });
435
+});
scripts/jest/matchers/toWarnDev.js
+4
-1
@@ -178,7 +178,9 @@ const createMatcherFor = (consoleMethod, matcherName) =>
178
};
179
}
180
181
- if (typeof withoutStack === 'number') {
181
+ if (consoleMethod === 'log') {
182
+ // We don't expect any console.log calls to have a stack.
183
+ } else if (typeof withoutStack === 'number') {
184
// We're expecting a particular number of warnings without stacks.
185
if (withoutStack !== warningsWithoutComponentStack.length) {
186
return {
@@ -309,4 +311,5 @@ const createMatcherFor = (consoleMethod, matcherName) =>
311
module.exports = {
312
toWarnDev: createMatcherFor('warn', 'toWarnDev'),
313
toErrorDev: createMatcherFor('error', 'toErrorDev'),
314
+ toLogDev: createMatcherFor('log', 'toLogDev'),
315
};
scripts/jest/setupTests.js
+23
-2
@@ -116,18 +116,19 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
116
.join('\n')}`
117
);
118
119
+ const type = methodName === 'log' ? 'log' : 'warning';
120
const message =
121
`Expected test not to call ${chalk.bold(
122
`console.${methodName}()`
123
)}.\n\n` +
123
- 'If the warning is expected, test for it explicitly by:\n' +
124
+ `If the ${type} is expected, test for it explicitly by:\n` +
125
`1. Using the ${chalk.bold('.' + expectedMatcher + '()')} ` +
126
`matcher, or...\n` +
127
`2. Mock it out using ${chalk.bold(
128
'spyOnDev'
129
)}(console, '${methodName}') or ${chalk.bold(
130
'spyOnProd'
130
- )}(console, '${methodName}'), and test that the warning occurs.`;
131
+ )}(console, '${methodName}'), and test that the ${type} occurs.`;
132
133
throw new Error(`${message}\n\n${messages.join('\n\n')}`);
134
}
@@ -135,9 +136,17 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
136
137
const unexpectedErrorCallStacks = [];
138
const unexpectedWarnCallStacks = [];
139
+ const unexpectedLogCallStacks = [];
140
141
const errorMethod = patchConsoleMethod('error', unexpectedErrorCallStacks);
142
const warnMethod = patchConsoleMethod('warn', unexpectedWarnCallStacks);
143
+ let logMethod;
144
+
145
+ // Only assert console.log isn't called in CI so you can debug tests in DEV.
146
+ // The matchers will still work in DEV, so you can assert locally.
147
+ if (process.env.CI) {
148
+ logMethod = patchConsoleMethod('log', unexpectedLogCallStacks);
149
+ }
150
151
const flushAllUnexpectedConsoleCalls = () => {
152
flushUnexpectedConsoleCalls(
@@ -152,6 +161,15 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
161
'toWarnDev',
162
unexpectedWarnCallStacks
163
);
164
+ if (logMethod) {
165
+ flushUnexpectedConsoleCalls(
166
+ logMethod,
167
+ 'log',
168
+ 'toLogDev',
169
+ unexpectedLogCallStacks
170
+ );
171
+ unexpectedLogCallStacks.length = 0;
172
+ }
173
unexpectedErrorCallStacks.length = 0;
174
unexpectedWarnCallStacks.length = 0;
175
};
@@ -159,6 +177,9 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
177
const resetAllUnexpectedConsoleCalls = () => {
178
unexpectedErrorCallStacks.length = 0;
179
unexpectedWarnCallStacks.length = 0;
180
+ if (logMethod) {
181
+ unexpectedLogCallStacks.length = 0;
182
+ }
183
};
184
185
beforeEach(resetAllUnexpectedConsoleCalls);