0
# Snapshot Management
1
2
Jest Image Snapshot provides comprehensive snapshot management including automatic cleanup of obsolete snapshots and integration with Jest's snapshot update workflow.
3
4
## Capabilities
5
6
### Outdated Snapshot Reporter
7
8
Jest reporter that tracks snapshot files used during test runs and removes obsolete snapshots that are no longer referenced by tests.
9
10
```javascript { .api }
11
class OutdatedSnapshotReporter {
12
/**
13
* Mark a snapshot file as touched during test execution
14
* @param filePath - Absolute path to the snapshot file
15
*/
16
static markTouchedFile(filePath: string): void;
17
18
/**
19
* Read the list of touched files from the tracking file
20
* @returns Array of file paths that were touched during tests
21
*/
22
static readTouchedFileListFromDisk(): string[];
23
24
/**
25
* Called at the start of test run - clears tracking file
26
*/
27
onRunStart(): void;
28
29
/**
30
* Called at the end of test run - removes obsolete snapshots
31
*/
32
onRunComplete(): void;
33
}
34
```
35
36
**Usage Example:**
37
38
```json
39
{
40
"jest": {
41
"reporters": [
42
"default",
43
"jest-image-snapshot/src/outdated-snapshot-reporter.js"
44
]
45
}
46
}
47
```
48
49
**Environment Variable:**
50
51
```bash
52
# Enable snapshot cleanup
53
export JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1
54
jest
55
```
56
57
**Important Notes:**
58
59
- Only run with full test suite - partial runs may mark active snapshots as obsolete
60
- The reporter deletes files permanently - ensure you have version control backups
61
- Tracking file `.jest-image-snapshot-touched-files` is created in current working directory
62
63
### Snapshot Directory Structure
64
65
Jest Image Snapshot creates and manages several directory structures for organizing snapshots and related files.
66
67
```javascript { .api }
68
interface SnapshotDirectories {
69
/** Default snapshot directory name */
70
SNAPSHOTS_DIR: '__image_snapshots__';
71
/** Default received images directory */
72
receivedDir: '__received_output__';
73
/** Default diff images directory */
74
diffDir: '__diff_output__';
75
}
76
```
77
78
**Default Directory Structure:**
79
```
80
test-directory/
81
├── __image_snapshots__/ # Baseline snapshots
82
│ ├── test-spec-test-name-1-snap.png
83
│ └── test-spec-test-name-2-snap.png
84
├── __received_output__/ # Received images (on failure)
85
│ ├── test-spec-test-name-1-received.png
86
│ └── test-spec-test-name-2-received.png
87
└── __diff_output__/ # Diff images (on failure)
88
├── test-spec-test-name-1-diff.png
89
└── test-spec-test-name-2-diff.png
90
```
91
92
### Custom Directory Configuration
93
94
Configure custom directories for different types of images and organizational needs.
95
96
```javascript { .api }
97
interface CustomDirectoryOptions {
98
/** Custom absolute path for baseline snapshots */
99
customSnapshotsDir?: string;
100
/** Custom absolute path for received images */
101
customReceivedDir?: string;
102
/** Custom absolute path for diff images */
103
customDiffDir?: string;
104
/** Custom postfix for received image filenames (default: '-received') */
105
customReceivedPostfix?: string;
106
}
107
```
108
109
**Usage Examples:**
110
111
```javascript
112
// Custom snapshot directories
113
expect(imageBuffer).toMatchImageSnapshot({
114
customSnapshotsDir: path.join(__dirname, 'visual-snapshots'),
115
customDiffDir: path.join(__dirname, 'visual-diffs'),
116
customReceivedDir: path.join(__dirname, 'visual-received')
117
});
118
119
// Environment-specific directories
120
const snapshotDir = process.env.NODE_ENV === 'production'
121
? './snapshots/prod'
122
: './snapshots/dev';
123
124
expect(imageBuffer).toMatchImageSnapshot({
125
customSnapshotsDir: path.resolve(snapshotDir)
126
});
127
128
// Device-specific organization
129
expect(imageBuffer).toMatchImageSnapshot({
130
customSnapshotsDir: `./snapshots/${deviceType}`,
131
customSnapshotIdentifier: `${testName}-${deviceType}`
132
});
133
```
134
135
### Snapshot Naming
136
137
Control how snapshot files are named and organized within directories.
138
139
```javascript { .api }
140
interface SnapshotNaming {
141
/** Default naming pattern: {testFile}-{testName}-{counter}-snap.png */
142
defaultPattern: string;
143
/** Custom identifier string or function */
144
customSnapshotIdentifier?: string | CustomSnapshotIdentifierFunction;
145
}
146
147
interface CustomSnapshotIdentifierFunction {
148
(params: {
149
testPath: string;
150
currentTestName: string;
151
counter: number;
152
defaultIdentifier: string;
153
}): string;
154
}
155
```
156
157
**Naming Examples:**
158
159
```javascript
160
// Custom string identifier
161
expect(imageBuffer).toMatchImageSnapshot({
162
customSnapshotIdentifier: 'header-component-mobile'
163
});
164
165
// Function-based identifier
166
expect(imageBuffer).toMatchImageSnapshot({
167
customSnapshotIdentifier: ({ testPath, currentTestName, counter }) => {
168
const testFile = path.basename(testPath, '.spec.js');
169
return `${testFile}__${currentTestName}__${counter}`;
170
}
171
});
172
173
// Hierarchical naming with paths
174
expect(imageBuffer).toMatchImageSnapshot({
175
customSnapshotIdentifier: 'components/header/mobile-view'
176
}); // Creates: components/header/mobile-view.png
177
```
178
179
### Snapshot Updates
180
181
Integration with Jest's snapshot update workflow and custom update behaviors.
182
183
```javascript { .api }
184
interface SnapshotUpdateOptions {
185
/** Update snapshots even when tests pass (default: false) */
186
updatePassedSnapshot?: boolean;
187
/** Store received images on failure for CI debugging */
188
storeReceivedOnFailure?: boolean;
189
}
190
```
191
192
**Update Examples:**
193
194
```bash
195
# Update all snapshots (Jest standard)
196
jest --updateSnapshot
197
198
# Update specific test snapshots
199
jest --testNamePattern="header component" --updateSnapshot
200
```
201
202
```javascript
203
// Force update even passing snapshots
204
expect(imageBuffer).toMatchImageSnapshot({
205
updatePassedSnapshot: true
206
});
207
208
// Store received images for CI analysis
209
expect(imageBuffer).toMatchImageSnapshot({
210
storeReceivedOnFailure: true // Helpful in CI environments
211
});
212
```
213
214
### Cleanup and Maintenance
215
216
Best practices for managing snapshot files and preventing accumulation of obsolete snapshots.
217
218
**Automated Cleanup:**
219
220
```javascript
221
// package.json script for cleanup
222
{
223
"scripts": {
224
"test:visual": "JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1 jest",
225
"test:visual:update": "JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1 jest --updateSnapshot"
226
}
227
}
228
```
229
230
**Manual Cleanup Patterns:**
231
232
```javascript
233
// Clean up before test runs
234
beforeAll(async () => {
235
if (process.env.CLEAN_SNAPSHOTS) {
236
const snapshotDir = path.join(__dirname, '__image_snapshots__');
237
if (fs.existsSync(snapshotDir)) {
238
fs.rmSync(snapshotDir, { recursive: true });
239
}
240
}
241
});
242
```
243
244
**Git Integration:**
245
246
```gitignore
247
# .gitignore - typically commit snapshots but ignore temp files
248
__image_snapshots__/ # Commit baseline snapshots
249
!__received_output__/ # Ignore received images
250
!__diff_output__/ # Ignore diff images
251
.jest-image-snapshot-touched-files # Ignore tracking file
252
```
253
254
### Error Handling
255
256
Snapshot management error scenarios and recovery strategies.
257
258
**Common Issues:**
259
260
```javascript
261
// Directory creation failures
262
expect(imageBuffer).toMatchImageSnapshot({
263
customSnapshotsDir: '/readonly/path' // Will fail with permission error
264
});
265
266
// Invalid custom identifiers
267
expect(imageBuffer).toMatchImageSnapshot({
268
customSnapshotIdentifier: '../../../malicious-path' // Blocked by path validation
269
});
270
271
// Missing snapshots in CI
272
expect(imageBuffer).toMatchImageSnapshot();
273
// Fails in CI when no baseline exists and updates are disabled
274
```
275
276
**Recovery Strategies:**
277
278
- **Missing Snapshots**: Run tests locally with `--updateSnapshot` to create baselines
279
- **Permission Errors**: Ensure test directories have write permissions
280
- **Corrupted Snapshots**: Delete and regenerate affected snapshot files
281
- **Size Conflicts**: Use `allowSizeMismatch: true` or regenerate snapshots for size changes