Skip to content

Commit

Permalink
[tests] Disallow unasserted console.log (#28708)
Browse files Browse the repository at this point in the history
Followup from #28693 and
#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.
  • Loading branch information
rickhanlonii authored Apr 1, 2024
1 parent 8833338 commit 6e65010
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
17 changes: 17 additions & 0 deletions scripts/jest/matchers/__tests__/toWarnDev-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,20 @@ describe('toWarnDev', () => {
});
}
});

describe('toLogDev', () => {
it('does not fail if warnings do not include a stack', () => {
expect(() => {
if (__DEV__) {
console.log('Hello');
}
}).toLogDev('Hello');
expect(() => {
if (__DEV__) {
console.log('Hello');
console.log('Good day');
console.log('Bye');
}
}).toLogDev(['Hello', 'Good day', 'Bye']);
});
});
5 changes: 4 additions & 1 deletion scripts/jest/matchers/toWarnDev.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ const createMatcherFor = (consoleMethod, matcherName) =>
};
}

if (typeof withoutStack === 'number') {
if (consoleMethod === 'log') {
// We don't expect any console.log calls to have a stack.
} else if (typeof withoutStack === 'number') {
// We're expecting a particular number of warnings without stacks.
if (withoutStack !== warningsWithoutComponentStack.length) {
return {
Expand Down Expand Up @@ -309,4 +311,5 @@ const createMatcherFor = (consoleMethod, matcherName) =>
module.exports = {
toWarnDev: createMatcherFor('warn', 'toWarnDev'),
toErrorDev: createMatcherFor('error', 'toErrorDev'),
toLogDev: createMatcherFor('log', 'toLogDev'),
};
25 changes: 23 additions & 2 deletions scripts/jest/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,28 +116,37 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
.join('\n')}`
);

const type = methodName === 'log' ? 'log' : 'warning';
const message =
`Expected test not to call ${chalk.bold(
`console.${methodName}()`
)}.\n\n` +
'If the warning is expected, test for it explicitly by:\n' +
`If the ${type} is expected, test for it explicitly by:\n` +
`1. Using the ${chalk.bold('.' + expectedMatcher + '()')} ` +
`matcher, or...\n` +
`2. Mock it out using ${chalk.bold(
'spyOnDev'
)}(console, '${methodName}') or ${chalk.bold(
'spyOnProd'
)}(console, '${methodName}'), and test that the warning occurs.`;
)}(console, '${methodName}'), and test that the ${type} occurs.`;

throw new Error(`${message}\n\n${messages.join('\n\n')}`);
}
};

const unexpectedErrorCallStacks = [];
const unexpectedWarnCallStacks = [];
const unexpectedLogCallStacks = [];

const errorMethod = patchConsoleMethod('error', unexpectedErrorCallStacks);
const warnMethod = patchConsoleMethod('warn', unexpectedWarnCallStacks);
let logMethod;

// Only assert console.log isn't called in CI so you can debug tests in DEV.
// The matchers will still work in DEV, so you can assert locally.
if (process.env.CI) {
logMethod = patchConsoleMethod('log', unexpectedLogCallStacks);
}

const flushAllUnexpectedConsoleCalls = () => {
flushUnexpectedConsoleCalls(
Expand All @@ -152,13 +161,25 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
'toWarnDev',
unexpectedWarnCallStacks
);
if (logMethod) {
flushUnexpectedConsoleCalls(
logMethod,
'log',
'toLogDev',
unexpectedLogCallStacks
);
unexpectedLogCallStacks.length = 0;
}
unexpectedErrorCallStacks.length = 0;
unexpectedWarnCallStacks.length = 0;
};

const resetAllUnexpectedConsoleCalls = () => {
unexpectedErrorCallStacks.length = 0;
unexpectedWarnCallStacks.length = 0;
if (logMethod) {
unexpectedLogCallStacks.length = 0;
}
};

beforeEach(resetAllUnexpectedConsoleCalls);
Expand Down

0 comments on commit 6e65010

Please sign in to comment.