diff --git a/docs/config/index.md b/docs/config/index.md index b297d11c926f..17d4ee6c5523 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -1137,6 +1137,10 @@ Clean coverage report on watch rerun - **Available for providers:** `'v8' | 'istanbul'` - **CLI:** `--coverage.reportsDirectory=` +::: warning +Vitest will delete this directory before running tests if `coverage.clean` is enabled (default value). +::: + Directory to write coverage report to. To preview the coverage report in the output of [HTML reporter](/guide/reporters.html#html-reporter), this option must be set as a sub-directory of the html report directory (for example `./html/coverage`). diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts index e1e46d16c6af..e52b8a21eaab 100644 --- a/packages/vitest/src/node/config.ts +++ b/packages/vitest/src/node/config.ts @@ -135,6 +135,7 @@ export function resolveConfig( } } + // TODO: V2.0.0 remove // @ts-expect-error -- check for removed API option if (resolved.coverage.provider === 'c8') throw new Error('"coverage.provider: c8" is not supported anymore. Use "coverage.provider: v8" instead') @@ -142,6 +143,13 @@ export function resolveConfig( if (resolved.coverage.provider === 'v8' && resolved.coverage.enabled && isBrowserEnabled(resolved)) throw new Error('@vitest/coverage-v8 does not work with --browser. Use @vitest/coverage-istanbul instead') + if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) { + const reportsDirectory = resolve(resolved.root, resolved.coverage.reportsDirectory) + + if (reportsDirectory === resolved.root || reportsDirectory === process.cwd()) + throw new Error(`You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`) + } + resolved.deps ??= {} resolved.deps.moduleDirectories ??= [] resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => { diff --git a/test/config/test/failures.test.ts b/test/config/test/failures.test.ts index 0007f55aac3f..33a6a5ea5f70 100644 --- a/test/config/test/failures.test.ts +++ b/test/config/test/failures.test.ts @@ -1,3 +1,4 @@ +import { resolve } from 'node:path' import { expect, test } from 'vitest' import type { UserConfig } from 'vitest/config' import { version } from 'vitest/package.json' @@ -67,6 +68,41 @@ test('v8 coverage provider cannot be used with browser in workspace', async () = expect(stderr).toMatch('Error: @vitest/coverage-v8 does not work with --browser. Use @vitest/coverage-istanbul instead') }) +test('coverage reportsDirectory cannot be current working directory', async () => { + const { stderr } = await runVitest({ + coverage: { + enabled: true, + reportsDirectory: './', + + // Additional options to make sure this test doesn't accidentally remove whole vitest project + clean: false, + cleanOnRerun: false, + provider: 'custom', + customProviderModule: 'non-existing-provider-so-that-reportsDirectory-is-not-removed', + }, + }) + + expect(stderr).toMatch(`Error: You cannot set "coverage.reportsDirectory" as ${resolve('./')}. Vitest needs to be able to remove this directory before test run`) +}) + +test('coverage reportsDirectory cannot be root', async () => { + const { stderr } = await runVitest({ + root: './fixtures', + coverage: { + enabled: true, + reportsDirectory: './', + + // Additional options to make sure this test doesn't accidentally remove whole vitest project + clean: false, + cleanOnRerun: false, + provider: 'custom', + customProviderModule: 'non-existing-provider-so-that-reportsDirectory-is-not-removed', + }, + }) + + expect(stderr).toMatch(`Error: You cannot set "coverage.reportsDirectory" as ${resolve('./fixtures')}. Vitest needs to be able to remove this directory before test run`) +}) + test('version number is printed when coverage provider fails to load', async () => { const { stderr, stdout } = await runVitest({ coverage: {