-
Notifications
You must be signed in to change notification settings - Fork 47k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move console mocks to internal-test-utils (#28710)
Moving this to `internal-test-utils` so I can add helpers in the next PR for: - assertLogDev - assertWarnDev - assertErrorDev Which will be exported from `internal-test-utils`. This isn't strictly necessary, but it makes the factoring nicer, so internal-test-until doesn't need to depend on `scripts/jest`.
- Loading branch information
1 parent
20e710a
commit a5aedd1
Showing
7 changed files
with
294 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
/* eslint-disable react-internal/no-production-logging */ | ||
const chalk = require('chalk'); | ||
const util = require('util'); | ||
const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError'); | ||
const shouldIgnoreConsoleWarn = require('./shouldIgnoreConsoleWarn'); | ||
|
||
const unexpectedErrorCallStacks = []; | ||
const unexpectedWarnCallStacks = []; | ||
const unexpectedLogCallStacks = []; | ||
|
||
// TODO: Consider consolidating this with `yieldValue`. In both cases, tests | ||
// should not be allowed to exit without asserting on the entire log. | ||
const patchConsoleMethod = (methodName, unexpectedConsoleCallStacks) => { | ||
const newMethod = function (format, ...args) { | ||
// Ignore uncaught errors reported by jsdom | ||
// and React addendums because they're too noisy. | ||
if (shouldIgnoreConsoleError(format, args)) { | ||
return; | ||
} | ||
|
||
// Ignore certain React warnings causing test failures | ||
if (methodName === 'warn' && shouldIgnoreConsoleWarn(format)) { | ||
return; | ||
} | ||
|
||
// Capture the call stack now so we can warn about it later. | ||
// The call stack has helpful information for the test author. | ||
// Don't throw yet though b'c it might be accidentally caught and suppressed. | ||
const stack = new Error().stack; | ||
unexpectedConsoleCallStacks.push([ | ||
stack.slice(stack.indexOf('\n') + 1), | ||
util.format(format, ...args), | ||
]); | ||
}; | ||
|
||
console[methodName] = newMethod; | ||
|
||
return newMethod; | ||
}; | ||
|
||
const flushUnexpectedConsoleCalls = ( | ||
mockMethod, | ||
methodName, | ||
expectedMatcher, | ||
unexpectedConsoleCallStacks, | ||
) => { | ||
if ( | ||
console[methodName] !== mockMethod && | ||
!jest.isMockFunction(console[methodName]) | ||
) { | ||
// throw new Error( | ||
// `Test did not tear down console.${methodName} mock properly.` | ||
// ); | ||
} | ||
if (unexpectedConsoleCallStacks.length > 0) { | ||
const messages = unexpectedConsoleCallStacks.map( | ||
([stack, message]) => | ||
`${chalk.red(message)}\n` + | ||
`${stack | ||
.split('\n') | ||
.map(line => chalk.gray(line)) | ||
.join('\n')}`, | ||
); | ||
|
||
const type = methodName === 'log' ? 'log' : 'warning'; | ||
const message = | ||
`Expected test not to call ${chalk.bold( | ||
`console.${methodName}()`, | ||
)}.\n\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 ${type} occurs.`; | ||
|
||
throw new Error(`${message}\n\n${messages.join('\n\n')}`); | ||
} | ||
}; | ||
|
||
let errorMethod; | ||
let warnMethod; | ||
let logMethod; | ||
export function patchConsoleMethods({includeLog} = {includeLog: false}) { | ||
errorMethod = patchConsoleMethod('error', unexpectedErrorCallStacks); | ||
warnMethod = patchConsoleMethod('warn', unexpectedWarnCallStacks); | ||
|
||
// 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 (includeLog) { | ||
logMethod = patchConsoleMethod('log', unexpectedLogCallStacks); | ||
} | ||
} | ||
|
||
export function flushAllUnexpectedConsoleCalls() { | ||
flushUnexpectedConsoleCalls( | ||
errorMethod, | ||
'error', | ||
'toErrorDev', | ||
unexpectedErrorCallStacks, | ||
); | ||
flushUnexpectedConsoleCalls( | ||
warnMethod, | ||
'warn', | ||
'toWarnDev', | ||
unexpectedWarnCallStacks, | ||
); | ||
if (logMethod) { | ||
flushUnexpectedConsoleCalls( | ||
logMethod, | ||
'log', | ||
'toLogDev', | ||
unexpectedLogCallStacks, | ||
); | ||
unexpectedLogCallStacks.length = 0; | ||
} | ||
unexpectedErrorCallStacks.length = 0; | ||
unexpectedWarnCallStacks.length = 0; | ||
} | ||
|
||
export function resetAllUnexpectedConsoleCalls() { | ||
unexpectedErrorCallStacks.length = 0; | ||
unexpectedWarnCallStacks.length = 0; | ||
if (logMethod) { | ||
unexpectedLogCallStacks.length = 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.