0
# Path Resolution
1
2
Snapshot file path management system that handles the relationship between test files and their corresponding snapshot files. Provides flexible path resolution with support for custom snapshot resolvers.
3
4
## Capabilities
5
6
### Snapshot Resolver
7
8
Interface for converting between test file paths and snapshot file paths, enabling customizable snapshot file organization.
9
10
```typescript { .api }
11
interface SnapshotResolver {
12
/**
13
* Resolves from test path to snapshot path
14
* @param testPath - Path to the test file
15
* @param snapshotExtension - Optional snapshot file extension (defaults to 'snap')
16
* @returns Path to the corresponding snapshot file
17
*/
18
resolveSnapshotPath(testPath: string, snapshotExtension?: string): string;
19
20
/**
21
* Resolves from snapshot path to test path
22
* @param snapshotPath - Path to the snapshot file
23
* @param snapshotExtension - Optional snapshot file extension (defaults to 'snap')
24
* @returns Path to the corresponding test file
25
*/
26
resolveTestPath(snapshotPath: string, snapshotExtension?: string): string;
27
28
/**
29
* Example test path used for consistency checking
30
* Must be a valid test path that can be resolved both ways
31
*/
32
testPathForConsistencyCheck: string;
33
}
34
```
35
36
### buildSnapshotResolver
37
38
Creates a snapshot resolver instance based on Jest configuration, with support for custom resolvers and caching.
39
40
```typescript { .api }
41
/**
42
* Builds a snapshot resolver for converting between test and snapshot paths
43
* @param config - Jest project configuration
44
* @param localRequire - Optional require function for loading custom resolvers
45
* @returns Promise resolving to a SnapshotResolver instance
46
*/
47
async function buildSnapshotResolver(
48
config: Config.ProjectConfig,
49
localRequire?: Promise<LocalRequire> | LocalRequire
50
): Promise<SnapshotResolver>;
51
52
type LocalRequire = (module: string) => unknown;
53
```
54
55
**Usage Examples:**
56
57
```typescript
58
import { buildSnapshotResolver } from "jest-snapshot";
59
60
// Basic resolver creation
61
const resolver = await buildSnapshotResolver({
62
rootDir: '/project/root',
63
snapshotResolver: undefined // use default resolver
64
});
65
66
// Custom resolver
67
const resolver = await buildSnapshotResolver({
68
rootDir: '/project/root',
69
snapshotResolver: './custom-snapshot-resolver.js'
70
});
71
72
// Use resolver to convert paths
73
const snapshotPath = resolver.resolveSnapshotPath(
74
'/project/src/components/Button.test.js'
75
);
76
// Returns: '/project/src/components/__snapshots__/Button.test.js.snap'
77
78
const testPath = resolver.resolveTestPath(
79
'/project/src/__snapshots__/utils.test.js.snap'
80
);
81
// Returns: '/project/src/utils.test.js'
82
```
83
84
### Default Path Resolution
85
86
The default snapshot resolver follows Jest's standard conventions:
87
88
**Test to Snapshot Path:**
89
- `src/components/Button.test.js` → `src/components/__snapshots__/Button.test.js.snap`
90
- `tests/user.spec.ts` → `tests/__snapshots__/user.spec.ts.snap`
91
- `app.test.jsx` → `__snapshots__/app.test.jsx.snap`
92
93
**Snapshot to Test Path:**
94
- `__snapshots__/Button.test.js.snap` → `Button.test.js`
95
- `src/__snapshots__/utils.spec.ts.snap` → `src/utils.spec.ts`
96
97
### Custom Snapshot Resolvers
98
99
Create custom resolvers to implement different snapshot organization strategies:
100
101
```javascript
102
// custom-snapshot-resolver.js
103
module.exports = {
104
// Resolve from test path to snapshot path
105
resolveSnapshotPath: (testPath, snapshotExtension) => {
106
// Custom logic: place all snapshots in a single directory
107
const testName = path.basename(testPath);
108
return path.join(
109
path.dirname(testPath),
110
'snapshots',
111
`${testName}.${snapshotExtension || 'snap'}`
112
);
113
},
114
115
// Resolve from snapshot path to test path
116
resolveTestPath: (snapshotPath, snapshotExtension) => {
117
// Reverse the custom logic
118
const snapshotName = path.basename(snapshotPath, `.${snapshotExtension || 'snap'}`);
119
return path.join(path.dirname(path.dirname(snapshotPath)), snapshotName);
120
},
121
122
// Example test path for consistency checking
123
testPathForConsistencyCheck: 'example.test.js'
124
};
125
```
126
127
### Path Utilities
128
129
Utility functions for working with snapshot file paths.
130
131
```typescript { .api }
132
/**
133
* Checks if a given path is a snapshot file
134
* @param path - File path to check
135
* @returns True if the path ends with the snapshot extension
136
*/
137
function isSnapshotPath(path: string): boolean;
138
139
/**
140
* Snapshot file extension constant
141
*/
142
const EXTENSION: string; // 'snap'
143
144
/**
145
* Dot-prefixed snapshot extension
146
*/
147
const DOT_EXTENSION: string; // '.snap'
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
import { isSnapshotPath, EXTENSION, DOT_EXTENSION } from "jest-snapshot";
154
155
// Check if path is a snapshot file
156
console.log(isSnapshotPath('Button.test.js.snap')); // true
157
console.log(isSnapshotPath('Button.test.js')); // false
158
159
// Use extension constants
160
const snapshotFile = `test.${EXTENSION}`; // 'test.snap'
161
const pattern = `*${DOT_EXTENSION}`; // '*.snap'
162
```
163
164
### Resolver Caching
165
166
The `buildSnapshotResolver` function implements caching to avoid recreating resolvers:
167
168
```typescript
169
// Cached by config.rootDir
170
const resolver1 = await buildSnapshotResolver(config);
171
const resolver2 = await buildSnapshotResolver(config);
172
// resolver1 === resolver2 (same instance from cache)
173
174
// Different rootDir = different cache entry
175
const differentConfig = { ...config, rootDir: '/different/path' };
176
const resolver3 = await buildSnapshotResolver(differentConfig);
177
// resolver3 !== resolver1 (different instance)
178
```
179
180
### Resolver Validation
181
182
Custom resolvers must pass consistency checks:
183
184
```typescript
185
// Resolver consistency check
186
const resolver = {
187
resolveSnapshotPath: (testPath) => `/snapshots/${path.basename(testPath)}.snap`,
188
resolveTestPath: (snapshotPath) => path.basename(snapshotPath, '.snap'),
189
testPathForConsistencyCheck: 'example.test.js'
190
};
191
192
// Jest validates:
193
// 1. testPath -> snapshotPath -> testPath should return original
194
// 2. Both functions should be consistent
195
```
196
197
### Integration with FileSystem
198
199
Resolvers work with Jest's file system abstraction:
200
201
```typescript
202
import { cleanup } from "jest-snapshot";
203
204
// Use resolver in cleanup operations
205
const result = cleanup(
206
fileSystem,
207
updateMode,
208
resolver,
209
testPathIgnorePatterns
210
);
211
212
// Resolver is used to:
213
// 1. Find all snapshot files matching the pattern
214
// 2. Convert snapshot paths back to test paths
215
// 3. Check if corresponding test files exist
216
```
217
218
## Error Handling
219
220
```typescript
221
// Invalid custom resolver
222
await buildSnapshotResolver({
223
rootDir: '/project',
224
snapshotResolver: './missing-resolver.js'
225
});
226
// Error: Cannot resolve module './missing-resolver.js'
227
228
// Inconsistent resolver functions
229
const badResolver = {
230
resolveSnapshotPath: (testPath) => 'snapshot.snap',
231
resolveTestPath: (snapshotPath) => 'different.test.js',
232
testPathForConsistencyCheck: 'test.js'
233
};
234
// Error: Inconsistent snapshot resolver implementation
235
236
// Missing required methods
237
const incompleteResolver = {
238
resolveSnapshotPath: (testPath) => `${testPath}.snap`
239
// Missing resolveTestPath and testPathForConsistencyCheck
240
};
241
// Error: Invalid snapshot resolver
242
```
243
244
## Types
245
246
```typescript { .api }
247
interface Config {
248
rootDir: string;
249
snapshotResolver?: string; // Path to custom resolver module
250
}
251
252
type LocalRequire = (module: string) => unknown;
253
254
interface ResolverCache extends Map<string, SnapshotResolver> {}
255
```