diff --git a/docs/config/browser/expect.md b/docs/config/browser/expect.md index 45c3a21a3..42580174c 100644 --- a/docs/config/browser/expect.md +++ b/docs/config/browser/expect.md @@ -46,10 +46,19 @@ export default defineConfig({ can be configured here. Additionally, two path resolution functions are available: `resolveScreenshotPath` and `resolveDiffPath`. +## browser.expect.toMatchScreenshot.screenshotDirectory + +- **Type:** `string | undefined` +- **Default:** `__screenshots__` + +The directory name used for storing reference screenshots. + +This value is passed as `screenshotDirectory` to [`browser.expect.toMatchScreenshot.resolveScreenshotPath`](#browserexpecttomatchscreenshotresolvescreenshotpath) and [`browser.expect.toMatchScreenshot.resolveDiffPath`](#browserexpecttomatchscreenshotresolvediffpath), and used in the default path resolution of `resolveScreenshotPath`. + ## browser.expect.toMatchScreenshot.resolveScreenshotPath - **Type:** `(data: PathResolveData) => string` -- **Default output:** `` `${root}/${testFileDirectory}/${screenshotDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` `` +- **Default output:** ``path.resolve(root, testFileDirectory, screenshotDirectory, testFileName, `${arg}-${browserName}-${platform}${ext}`)`` A function to customize where reference screenshots are stored. The function receives an object with the following properties: @@ -92,9 +101,7 @@ receives an object with the following properties: - `screenshotDirectory: string` - The value provided to - [`browser.screenshotDirectory`](/config/browser/screenshotdirectory), - if none is provided, its default value. + The value provided to [`browser.expect.toMatchScreenshot.screenshotDirectory`](#browserexpecttomatchscreenshotscreenshotdirectory), if none is provided, its default value (`__screenshots__`). - `root: string` @@ -132,7 +139,7 @@ resolveScreenshotPath: ({ arg, browserName, ext, root, testFileName }) => ## browser.expect.toMatchScreenshot.resolveDiffPath - **Type:** `(data: PathResolveData) => string` -- **Default output:** `` `${root}/${attachmentsDir}/${testFileDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` `` +- **Default output:** ``path.resolve(root, attachmentsDir, testFileDirectory, testFileName, `${arg}-${browserName}-${platform}${ext}`)`` A function to customize where diff images are stored when screenshot comparisons fail. Receives the same data object as diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 73b91fb56..10e60690e 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -182,6 +182,32 @@ Vitest now uses a single `.vitest` directory at the project root as the shared a - **Blob reporter** and `--merge-reports`: `.vitest-reports/blob-*.json` → `.vitest/blob/blob-*.json` - **HTML reporter** ([`html`](/guide/reporters#html-reporter)): `html/index.html` → `.vitest/index.html`, and its option changed from `outputFile` (a file) to `outputDir` (a directory) +### `toMatchScreenshot` Now Uses a Dedicated Screenshot Directory Config + +Previously, reference screenshots for `toMatchScreenshot` did not correctly respect `browser.screenshotDirectory`. As a result, screenshots were saved in an unintended location when a custom directory was configured. + +This has now been fixed by introducing a dedicated option: `browser.expect.toMatchScreenshot.screenshotDirectory`. Its default value is `__screenshots__`. + +- If you did not set `browser.screenshotDirectory`, no changes are required. +- If you did set `browser.screenshotDirectory`, you must now explicitly configure the new option: + + ```ts [vitest.config.ts] + export default defineConfig({ + test: { + browser: { + screenshotDirectory: 'my-screenshots', + expect: { // [!code ++] + toMatchScreenshot: { // [!code ++] + screenshotDirectory: 'my-screenshots', // [!code ++] + }, // [!code ++] + }, // [!code ++] + }, + }, + }) + ``` + + Then either move existing reference screenshots to the new location or regenerate them. + ## Migrating to Vitest 4.0 {#vitest-4} ::: warning Prerequisites diff --git a/packages/browser/src/node/commands/screenshotMatcher/utils.ts b/packages/browser/src/node/commands/screenshotMatcher/utils.ts index 242f8aed3..2b60575c0 100644 --- a/packages/browser/src/node/commands/screenshotMatcher/utils.ts +++ b/packages/browser/src/node/commands/screenshotMatcher/utils.ts @@ -17,7 +17,7 @@ type GlobalOptions = Required['toMatchScreenshot'] & NonNullable> >, - 'comparators' + 'comparators' | 'screenshotDirectory' >> const defaultOptions = { @@ -135,10 +135,7 @@ export function resolveOptions( ext: `.${extension}`, platform: platform(), root, - screenshotDirectory: relative( - root, - join(root, context.project.config.browser.screenshotDirectory ?? '__screenshots__'), - ), + screenshotDirectory: context.project.config.browser.expect?.toMatchScreenshot?.screenshotDirectory ?? '__screenshots__', attachmentsDir: relative(root, context.project.config.attachmentsDir), testFileDirectory: relative(root, dirname(context.testPath)), testFileName: basename(context.testPath), diff --git a/packages/vitest/src/node/types/browser.ts b/packages/vitest/src/node/types/browser.ts index 06ef6c766..c18edee66 100644 --- a/packages/vitest/src/node/types/browser.ts +++ b/packages/vitest/src/node/types/browser.ts @@ -518,9 +518,7 @@ type ToMatchScreenshotResolvePath = (data: { */ platform: NodeJS.Platform /** - * The value provided to - * {@linkcode https://vitest.dev/config/browser/screenshotdirectory|browser.screenshotDirectory}, - * if none is provided, its default value. + * The value provided to {@linkcode ToMatchScreenshotOptions.screenshotDirectory|browser.expect.toMatchScreenshot.screenshotDirectory}, if none is provided, its default value (`__screenshots__`). */ screenshotDirectory: string /** @@ -557,16 +555,24 @@ type ToMatchScreenshotResolvePath = (data: { }) => string export interface ToMatchScreenshotOptions { + /** + * The directory name used for storing reference screenshots. + * + * This value is passed as `screenshotDirectory` to {@linkcode resolveScreenshotPath|browser.expect.toMatchScreenshot.resolveScreenshotPath} and {@linkcode resolveDiffPath|browser.expect.toMatchScreenshot.resolveDiffPath}, and used in the default path resolution of `resolveScreenshotPath`. + * + * @default `__screenshots__`. + */ + screenshotDirectory?: string /** * Overrides default reference screenshot path. * - * @default `${root}/${testFileDirectory}/${screenshotDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` + * @default path.resolve(root, testFileDirectory, screenshotDirectory, testFileName, `${arg}-${browserName}-${platform}${ext}`) */ resolveScreenshotPath?: ToMatchScreenshotResolvePath /** * Overrides default screenshot path used for diffs. * - * @default `${root}/${attachmentsDir}/${testFileDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` + * @default path.resolve(root, attachmentsDir, testFileDirectory, testFileName, `${arg}-${browserName}-${platform}${ext}`) */ resolveDiffPath?: ToMatchScreenshotResolvePath } diff --git a/test/browser/specs/to-match-screenshot.test.ts b/test/browser/specs/to-match-screenshot.test.ts index d652a1cbe..8843f1e87 100644 --- a/test/browser/specs/to-match-screenshot.test.ts +++ b/test/browser/specs/to-match-screenshot.test.ts @@ -131,6 +131,47 @@ describe('--watch', () => { }, ) + test( + 'uses the `screenshotDirectory` option from config', + async () => { + const customDir = 'my-screenshots' + + const { stderr } = await runBrowserTests( + { + [testFilename]: testContent, + 'utils.ts': utilsContent, + }, + { + browser: { + enabled: true, + screenshotFailures: false, + provider, + headless: true, + instances, + viewport: { + width: 400, + height: 200, + }, + expect: { + toMatchScreenshot: { + screenshotDirectory: customDir, + }, + }, + }, + update: 'new', + }, + ) + + const references = extractToMatchScreenshotPaths(stderr, testName) + + expect(references.length).toBeGreaterThan(0) + + for (const referencePath of references) { + expect(referencePath).toContain(`/${customDir}/`) + } + }, + ) + describe('--update', () => { test( 'creates snapshot and does NOT update it if reference matches',