Make console.error (and warn?) log a stack trace and codeframe like thrown errors do
See original GitHub issueš Feature Proposal
99% of the time, if console.error
and console.warn
are called during tests (and theyāre not mocked), itās something that needs to be fixed.
Motivation
In particular, with Reactās new act
warning, people are seeing output like this:
console.error node_modules/react-dom/cjs/react-dom.development.js:545
Warning: An update to User inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
in User
Itās not entirely helpful. It does show that this is happening in the User
component, but there could be any number of places within that component that could have triggered that error to be logged.
Example
Hereās a proof of concept of what Iām suggesting (definitely wouldnāt work like this if built-in):
const originalError = console.error
beforeAll(() => {
console.error = (...args) => {
console.log(new Error().stack)
originalError(...args)
}
})
afterAll(() => {
console.error = originalError
})
This would look like:
console.log src/__tests__/tmp.js:31
Error:
at CustomConsole.console.error (/Users/kentcdodds/code/react-testing-library/src/__tests__/tmp.js:31:17)
at warningWithoutStack (/Users/kentcdodds/code/react-testing-library/node_modules/react-dom/cjs/react-dom.development.js:545:32)
at warnIfNotCurrentlyActingUpdatesInDEV (/Users/kentcdodds/code/react-testing-library/node_modules/react-dom/cjs/react-dom.development.js:23281:7)
at dispatchAction (/Users/kentcdodds/code/react-testing-library/node_modules/react-dom/cjs/react-dom.development.js:15813:9)
at setUser (/Users/kentcdodds/code/react-testing-library/src/__tests__/tmp.js:8:5)
at processTicksAndRejections (internal/process/task_queues.js:89:5)
console.error src/__tests__/tmp.js:32
Warning: An update to User inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
in User
And visually:
And it could be potentially improved within Jest so itās even more helpful (with color coding to highlight the part of the code that triggered the error). Similar to when an error is thrown.
some error in React
6 | async function fetchUserData(id) {
7 | const response = await fetch(`/${id}`)
> 8 | setUser(await response.json())
| ^
9 | }
10 | React.useEffect(() => {
11 | fetchUserData(props.id)
at dispatchAction (node_modules/react-dom/cjs/react-dom.development.js:15809:11)
at setUser (src/__tests__/tmp.js:8:5)
And visually:
To be clear, what I mean is that console.error
could print out a stack trace and codeframe where the part of the stack trace which is not in user code could be dimmed to reduce confusion and the codeframe would show the part of the userās code which ultimately triggered the error to be logged.
Pitch
I think this would help more than just act
and it seems like the correct place for this to happen. It would help people get rid of error (and potentially warn) logs quicker, and move on to building their apps faster (which I believe is the goal of Jest).
Reference: https://github.com/testing-library/react-testing-library/issues/434
Iād love to hear what you all think!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:59
- Comments:39 (15 by maintainers)
Top GitHub Comments
Doing this only for
console.error
andconsole.warn
matches how browsers show expandable arrows with JS stack next to them. The implementation itself is justnew Error().stack
. Sure, itās not asynchronous ā but thatās a question to VM implementors. Eventually it would be (or maybe it already is in recent Nodes). This sounds like a simple enough proposal and likely doable in 30 minutes. Let me tweet this.Released in 25.4.0, please try it out š