Skip to content

Commit 447a706

Browse files
9aoyCopilot
andauthored
feat: support resolveSnapshotPath option (#632)
Co-authored-by: Copilot <[email protected]>
1 parent 68dae3c commit 447a706

File tree

13 files changed

+120
-3
lines changed

13 files changed

+120
-3
lines changed

e2e/snapshot/file.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ describe('test snapshot', () => {
2929
});
3030

3131
await expectFile(snapshotFilePath, 3000);
32-
expect(fs.existsSync(snapshotFilePath)).toBeTruthy();
3332

3433
// should generator snapshot name correctly
3534
await expect
@@ -41,6 +40,33 @@ describe('test snapshot', () => {
4140
fs.rmSync(snapshotFilePath);
4241
});
4342

43+
it('resolveSnapshotPath', async () => {
44+
const snapshotFilePath = join(__dirname, 'fixtures/index.test.ts.snap');
45+
46+
fs.rmSync(snapshotFilePath, {
47+
force: true,
48+
});
49+
const { expectExecSuccess } = await runRstestCli({
50+
command: 'rstest',
51+
args: [
52+
'run',
53+
'fixtures/index.test.ts',
54+
'-u',
55+
'-c',
56+
'fixtures/rstest.snapshotPath.config.ts',
57+
],
58+
options: {
59+
nodeOptions: {
60+
cwd: __dirname,
61+
},
62+
},
63+
});
64+
65+
await expectExecSuccess();
66+
67+
await expectFile(snapshotFilePath, 3000);
68+
});
69+
4470
describe('test snapshot file state', () => {
4571
it('test toMatchSnapshot API', () => {
4672
expect('hello world').toMatchSnapshot();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Rstest Snapshot v1
2+
3+
exports[`test snapshot > test snapshot generate 1`] = `"hello world"`;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from '@rstest/core';
2+
3+
export default defineConfig({
4+
resolveSnapshotPath: (testPath, snapshotExtension) =>
5+
testPath + snapshotExtension,
6+
});

packages/core/src/pool/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os from 'node:os';
22
import type { SnapshotUpdateState } from '@vitest/snapshot';
3+
import { basename, dirname, join } from 'pathe';
34
import type {
45
EntryInfo,
56
FormattedError,
@@ -208,6 +209,21 @@ export const createPool = async ({
208209
reporters.map((reporter) => reporter.onTestFileStart?.(test)),
209210
);
210211
},
212+
resolveSnapshotPath: (testPath: string): string => {
213+
const snapExtension = '.snap';
214+
const resolver =
215+
context.normalizedConfig.resolveSnapshotPath ||
216+
// test/index.ts -> test/__snapshots__/index.ts.snap
217+
(() =>
218+
join(
219+
dirname(testPath),
220+
'__snapshots__',
221+
`${basename(testPath)}${snapExtension}`,
222+
));
223+
224+
const snapshotPath = resolver(testPath, snapExtension);
225+
return snapshotPath;
226+
},
211227
};
212228

213229
return {

packages/core/src/runtime/worker/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ const preparePool = async ({
9090
...context,
9191
snapshotOptions: {
9292
updateSnapshot,
93-
snapshotEnvironment: new RstestSnapshotEnvironment(),
93+
snapshotEnvironment: new RstestSnapshotEnvironment({
94+
resolveSnapshotPath: (filepath: string) =>
95+
rpc.resolveSnapshotPath(filepath),
96+
}),
9497
snapshotFormat,
9598
},
9699
distPath,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
22

33
export class RstestSnapshotEnvironment extends NodeSnapshotEnvironment {
4+
private resolveSnapshotPath: (filepath: string) => Promise<string>;
5+
6+
constructor(options: {
7+
resolveSnapshotPath: (filepath: string) => Promise<string>;
8+
}) {
9+
super();
10+
this.resolveSnapshotPath = options.resolveSnapshotPath;
11+
}
12+
413
override getHeader(): string {
514
return `// Rstest Snapshot v${this.getVersion()}`;
615
}
16+
17+
override resolvePath(filepath: string): Promise<string> {
18+
return this.resolveSnapshotPath(filepath);
19+
}
720
}

packages/core/src/types/config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ export interface RstestConfig {
224224
/** Format snapshot output */
225225
snapshotFormat?: SnapshotFormat;
226226

227+
/**
228+
* Resolve custom snapshot path
229+
*/
230+
resolveSnapshotPath?: (testPath: string, snapExtension: string) => string;
231+
227232
/**
228233
* Custom environment variables available on `process.env` during tests.
229234
*/
@@ -272,7 +277,8 @@ type OptionalKeys =
272277
| 'performance'
273278
| 'tools'
274279
| 'dev'
275-
| 'onConsoleLog';
280+
| 'onConsoleLog'
281+
| 'resolveSnapshotPath';
276282

277283
export type NormalizedConfig = Required<
278284
Omit<

packages/core/src/types/worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type RuntimeRPC = {
2424
}>;
2525
onTestCaseResult: (result: TestResult) => Promise<void>;
2626
onConsoleLog: (log: UserConsoleLog) => void;
27+
resolveSnapshotPath: (filepath: string) => string;
2728
};
2829

2930
export type RuntimeConfig = Pick<

website/docs/en/config/test/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"hideSkippedTests",
3333
"slowTestThreshold",
3434
"snapshotFormat",
35+
"resolveSnapshotPath",
3536
"printConsoleTrace",
3637
"onConsoleLog",
3738
"disableConsoleIntercept"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# resolveSnapshotPath
2+
3+
- **Type:** `(testPath: string, snapExtension: string) => string`
4+
- **Default:** `undefined`
5+
6+
Custom handler for resolving snapshot paths in tests.
7+
8+
By default, Rstest saves snapshot files in the same directory as the test files, under a `__snapshots__` folder.
9+
10+
You can use `resolveSnapshotPath` to customize this behavior and specify a different location for your snapshot files.
11+
12+
For example, store snapshots next to test files:
13+
14+
```ts title="rstest.config.ts"
15+
import { defineConfig } from '@rstest/core';
16+
17+
export default defineConfig({
18+
resolveSnapshotPath: (testPath, snapshotExtension) =>
19+
testPath + snapshotExtension,
20+
});
21+
```

0 commit comments

Comments
 (0)