All tests pass, but the terminal is full of red console.error output. This is common and easy to ignore β the tests passed, after all. But those errors don’t appear out of nowhere. Something went wrong; nobody just noticed.
vitest-fail-on-console does one thing: if console.error or console.warn appears during a test, that test fails. It forces you to acknowledge these messages instead of letting them drown in noise.
Why console.error in Tests Is a Code Smell
Vitest doesn’t care about console output by default. You can console.error all day and tests still pass.
The problem is that console.error usually means something. It might be:
- A React prop type warning
- An async error that was caught but not properly handled
- A third-party package telling you you’re using it wrong
- An error handler in your own code getting triggered
When these appear in tests, the test is running in a slightly broken state β it just didn’t throw. Over time the test output becomes pure noise. Nobody reads it anymore, and the real signals get buried.
vitest-fail-on-console flips this: make console output a test failure, so you’re forced to address it.
Installation
| |
Setup
Import and call it in your setup file:
| |
Then wire up the setup file in vitest.config.ts:
| |
That’s it. Any test that triggers console.error or console.warn will now fail.
Options
failOnConsole() accepts an options object to control which console methods trigger failures:
| |
error and warn are usually enough. Whether to include log / info / debug depends on your project’s conventions.
allowMessage
Allow specific messages through without failing β useful for known third-party issues you can’t fix right now:
| |
silenceMessage
Like allowMessage, but also suppresses the console output entirely:
| |
skipTest
Skip specific test files or test names entirely:
| |
afterEachDelay
Sometimes async operations call console methods after a test ends. This option adds a delay before checking:
| |
Handling Expected console.error Calls
After installing vitest-fail-on-console, if a test is specifically verifying that console.error gets called, letting it fire naturally will cause the test to fail.
The correct approach is to mock it with vi.spyOn:
| |
This does two things: the test explicitly declares “I know an error will be logged here,” and it asserts the exact message. Much stricter than silently letting console.error through.
Pair It with a Clean Test Environment
vitest-fail-on-console handles the console output side. If your tests also have I/O boundaries to replace β filesystem, file watchers β you can pair it with memfs using the same philosophy: every aspect of the test environment should be under your control.
See Testing a Filesystem Service with memfs + FakeWatchService for that approach.
