diff --git a/biome.json b/biome.json index 23c6797221..681707c749 100644 --- a/biome.json +++ b/biome.json @@ -360,6 +360,16 @@ } } }, + { + "includes": ["test/failOnConsole.ts"], + "linter": { + "rules": { + "suspicious": { + "noConsole": "off" + } + } + } + }, { "includes": ["**/*.js", "**/rolldown.config.ts"], "linter": { diff --git a/eslint.config.js b/eslint.config.js index 870d60a458..c566a50c0a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -630,8 +630,8 @@ export default defineConfig([ 'vitest/no-disabled-tests': 0, 'vitest/no-done-callback': 1, 'vitest/no-duplicate-hooks': 1, - 'vitest/no-focused-tests': 1, - 'vitest/no-hooks': 1, + 'vitest/no-focused-tests': [1, { fixable: false }], + 'vitest/no-hooks': 0, 'vitest/no-identical-title': 1, 'vitest/no-import-node-test': 1, 'vitest/no-importing-vitest-globals': 1, @@ -741,6 +741,16 @@ export default defineConfig([ } }, + { + name: 'tools', + + files: ['test/failOnConsole.ts'], + + rules: { + 'no-console': 0 + } + }, + { name: 'node', diff --git a/test/failOnConsole.ts b/test/failOnConsole.ts new file mode 100644 index 0000000000..791e26fc25 --- /dev/null +++ b/test/failOnConsole.ts @@ -0,0 +1,38 @@ +let consoleErrorOrConsoleWarnWereCalled = false; + +beforeAll(() => { + // replace instead of mutating `console` to avoid infinite loops + globalThis.console = { + ...console, + error(...params) { + if ( + params[0] instanceof Error && + params[0].message === 'ResizeObserver loop completed with undelivered notifications.' + ) { + return; + } + + consoleErrorOrConsoleWarnWereCalled = true; + console.log(...params); + }, + warn(...params) { + consoleErrorOrConsoleWarnWereCalled = true; + console.log(...params); + } + }; +}); + +afterEach(() => { + if (!consoleErrorOrConsoleWarnWereCalled) { + return; + } + + consoleErrorOrConsoleWarnWereCalled = false; + + // Errors thrown in `afterEach` will short-circuit subsequent `afterEach` hooks, + // thus preventing tests from being cleaned up properly and affecting other tests. + // We must therefore wait for tests to "finish" before throwing the error. + onTestFinished(() => { + throw new Error('console.error() and/or console.warn() were called during the test'); + }); +}); diff --git a/vite.config.ts b/vite.config.ts index 7cf97ba322..b92c96442e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -124,6 +124,7 @@ export default defineConfig( test: { dir: 'test', globals: true, + printConsoleTrace: true, coverage: { provider: 'istanbul', enabled: isCI, @@ -156,7 +157,7 @@ export default defineConfig( headless: true, screenshotFailures: !isCI }, - setupFiles: ['test/setupBrowser.ts'] + setupFiles: ['test/setupBrowser.ts', 'test/failOnConsole.ts'] } }, { @@ -171,7 +172,7 @@ export default defineConfig( headless: true, screenshotFailures: false }, - setupFiles: ['test/setupBrowser.ts'] + setupFiles: ['test/setupBrowser.ts', 'test/failOnConsole.ts'] } }, { @@ -179,7 +180,8 @@ export default defineConfig( test: { name: 'node', include: ['node/**/*.test.*'], - environment: 'node' + environment: 'node', + setupFiles: ['test/failOnConsole.ts'] } } ]