or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cleanup.mderror-snapshots.mdindex.mdpath-resolution.mdserialization.mdsnapshot-matchers.mdstate-management.md
tile.json

cleanup.mddocs/

0

# Cleanup Operations

1

2

Utility functions for maintaining snapshot files and removing orphaned snapshots that no longer have corresponding test files. Essential for keeping snapshot directories clean and avoiding stale snapshot accumulation.

3

4

## Capabilities

5

6

### cleanup Function

7

8

Removes orphaned snapshot files that no longer have corresponding test files, with support for ignore patterns and different update modes.

9

10

```typescript { .api }

11

/**

12

* Removes orphaned snapshot files that no longer have corresponding test files

13

* @param fileSystem - File system interface for file operations

14

* @param update - Snapshot update mode controlling cleanup behavior

15

* @param snapshotResolver - Resolver for converting between test and snapshot paths

16

* @param testPathIgnorePatterns - Optional patterns for ignoring test paths

17

* @returns Summary of cleanup results

18

*/

19

function cleanup(

20

fileSystem: FileSystem,

21

update: Config.SnapshotUpdateState,

22

snapshotResolver: SnapshotResolver,

23

testPathIgnorePatterns?: string[]

24

): {

25

filesRemoved: number;

26

filesRemovedList: Array<string>;

27

};

28

29

type Config.SnapshotUpdateState = 'all' | 'new' | 'none';

30

```

31

32

**Usage Examples:**

33

34

```typescript

35

import { cleanup, buildSnapshotResolver } from "jest-snapshot";

36

37

// File system implementation (typically jest-haste-map's HasteFS)

38

const fileSystem = {

39

exists: (path) => fs.existsSync(path),

40

matchFiles: (pattern) => glob.sync(pattern, { cwd: projectRoot })

41

};

42

43

// Build snapshot resolver

44

const snapshotResolver = await buildSnapshotResolver({

45

rootDir: '/project/root',

46

snapshotResolver: undefined

47

});

48

49

// Clean up orphaned snapshots

50

const result = cleanup(

51

fileSystem,

52

'all', // Update mode: 'all' enables cleanup

53

snapshotResolver,

54

['**/node_modules/**'] // Ignore patterns

55

);

56

57

console.log(`Removed ${result.filesRemoved} orphaned snapshot files`);

58

console.log('Files removed:', result.filesRemovedList);

59

60

// Example output:

61

// Removed 3 orphaned snapshot files

62

// Files removed: [

63

// '/project/src/__snapshots__/DeletedComponent.test.js.snap',

64

// '/project/src/__snapshots__/RenamedFile.spec.js.snap',

65

// '/project/tests/__snapshots__/old-test.js.snap'

66

// ]

67

```

68

69

### Cleanup Process

70

71

The cleanup function follows a systematic process:

72

73

1. **Find Snapshot Files**: Uses the file system to find all files matching the snapshot pattern (`.snap` files)

74

2. **Resolve Test Paths**: For each snapshot file, uses the snapshot resolver to determine the corresponding test file path

75

3. **Check Test File Existence**: Verifies whether the test file still exists

76

4. **Apply Ignore Patterns**: Skips snapshots whose test paths match ignore patterns

77

5. **Remove Orphaned Files**: In 'all' update mode, removes snapshot files without corresponding tests

78

79

```typescript

80

// Internal cleanup logic (simplified)

81

const pattern = `\\.${EXTENSION}$`; // '\.snap$'

82

const snapshotFiles = fileSystem.matchFiles(pattern);

83

84

const orphanedFiles = snapshotFiles.filter(snapshotFile => {

85

// Get corresponding test path

86

const testPath = snapshotResolver.resolveTestPath(snapshotFile);

87

88

// Check ignore patterns

89

if (testIgnorePatternsRegex && testIgnorePatternsRegex.test(testPath)) {

90

return false; // Skip ignored test paths

91

}

92

93

// Check if test file exists

94

return !fileSystem.exists(testPath);

95

});

96

97

// Remove files if in 'all' update mode

98

if (update === 'all') {

99

orphanedFiles.forEach(file => fs.unlinkSync(file));

100

}

101

```

102

103

### Update Mode Behavior

104

105

The cleanup behavior depends on the snapshot update mode:

106

107

**`'all'` Mode**: Actively removes orphaned snapshot files

108

```typescript

109

const result = cleanup(fileSystem, 'all', resolver);

110

// Physically deletes orphaned .snap files

111

// result.filesRemoved > 0 if files were removed

112

```

113

114

**`'new'` or `'none'` Mode**: Only reports orphaned files without removing them

115

```typescript

116

const result = cleanup(fileSystem, 'none', resolver);

117

// Reports orphaned files but doesn't delete them

118

// result.filesRemoved = 0, but filesRemovedList shows what would be removed

119

```

120

121

### Ignore Patterns

122

123

Use ignore patterns to exclude certain test paths from cleanup consideration:

124

125

```typescript

126

// Common ignore patterns

127

const ignorePatterns = [

128

'**/node_modules/**', // Ignore dependencies

129

'**/dist/**', // Ignore build output

130

'**/*.d.ts', // Ignore TypeScript declarations

131

'**/fixtures/**', // Ignore test fixtures

132

'**/coverage/**' // Ignore coverage reports

133

];

134

135

const result = cleanup(

136

fileSystem,

137

'all',

138

resolver,

139

ignorePatterns

140

);

141

142

// Snapshots for tests matching these patterns won't be removed

143

// even if the test files appear to be missing

144

```

145

146

### FileSystem Interface

147

148

The cleanup function expects a file system interface that provides file existence checking and pattern matching:

149

150

```typescript { .api }

151

interface FileSystem {

152

/**

153

* Checks if a file exists at the given path

154

* @param path - File path to check

155

* @returns True if file exists, false otherwise

156

*/

157

exists(path: string): boolean;

158

159

/**

160

* Finds files matching a pattern

161

* @param pattern - RegExp or string pattern to match files

162

* @returns Array of matching file paths

163

*/

164

matchFiles(pattern: RegExp | string): Array<string>;

165

}

166

```

167

168

**Common FileSystem Implementations:**

169

170

```typescript

171

// Using Node.js fs and glob

172

const nodeFileSystem = {

173

exists: (path) => require('fs').existsSync(path),

174

matchFiles: (pattern) => require('glob').sync(pattern)

175

};

176

177

// Using jest-haste-map (typical in Jest environments)

178

const hasteFileSystem = {

179

exists: (path) => hasteFs.exists(path),

180

matchFiles: (pattern) => hasteFs.matchFiles(pattern)

181

};

182

183

// Custom implementation with caching

184

const cachedFileSystem = {

185

exists: (path) => {

186

if (!existsCache.has(path)) {

187

existsCache.set(path, fs.existsSync(path));

188

}

189

return existsCache.get(path);

190

},

191

matchFiles: (pattern) => glob.sync(pattern, { cache: globCache })

192

};

193

```

194

195

### Integration with Test Runners

196

197

Cleanup is typically integrated into test runner workflows:

198

199

```typescript

200

// Jest integration example

201

module.exports = {

202

// Jest configuration

203

setupFilesAfterEnv: ['<rootDir>/cleanup-snapshots.js']

204

};

205

206

// cleanup-snapshots.js

207

afterAll(async () => {

208

if (process.env.UPDATE_SNAPSHOTS === 'true') {

209

const result = cleanup(fileSystem, 'all', resolver);

210

console.log(`Cleaned up ${result.filesRemoved} orphaned snapshots`);

211

}

212

});

213

214

// CI/CD integration

215

if (process.env.CI && process.env.UPDATE_SNAPSHOTS) {

216

const result = cleanup(fileSystem, 'all', resolver);

217

218

if (result.filesRemoved > 0) {

219

console.log('Orphaned snapshots removed:', result.filesRemovedList);

220

process.exit(1); // Fail CI to highlight the cleanup

221

}

222

}

223

```

224

225

### Error Handling

226

227

Cleanup operations can encounter various error conditions:

228

229

```typescript

230

// File system errors

231

try {

232

const result = cleanup(fileSystem, 'all', resolver);

233

} catch (error) {

234

if (error.code === 'ENOENT') {

235

console.log('Snapshot directory not found');

236

} else if (error.code === 'EPERM') {

237

console.log('Permission denied removing snapshot file');

238

}

239

}

240

241

// Invalid resolver

242

const result = cleanup(fileSystem, 'all', null);

243

// Error: Invalid snapshot resolver

244

245

// Pattern matching errors

246

const faultyFileSystem = {

247

exists: () => true,

248

matchFiles: () => { throw new Error('Pattern error'); }

249

};

250

// Error: Failed to match snapshot files

251

```

252

253

### Cleanup Reporting

254

255

Detailed reporting helps understand what was cleaned up:

256

257

```typescript

258

const result = cleanup(fileSystem, 'all', resolver, ignorePatterns);

259

260

console.log(`Cleanup Summary:

261

Files Removed: ${result.filesRemoved}

262

Ignore Patterns: ${ignorePatterns?.length || 0}

263

264

Removed Files:`);

265

266

result.filesRemovedList.forEach(file => {

267

const testPath = resolver.resolveTestPath(file);

268

console.log(` ${file} (test: ${testPath})`);

269

});

270

```

271

272

## Types

273

274

```typescript { .api }

275

interface CleanupResult {

276

filesRemoved: number; // Count of files actually removed

277

filesRemovedList: Array<string>; // Paths of removed files

278

}

279

280

type SnapshotUpdateState = 'all' | 'new' | 'none';

281

282

interface FileSystem {

283

exists(path: string): boolean;

284

matchFiles(pattern: RegExp | string): Array<string>;

285

}

286

287

interface SnapshotResolver {

288

resolveTestPath(snapshotPath: string, snapshotExtension?: string): string;

289

resolveSnapshotPath(testPath: string, snapshotExtension?: string): string;

290

testPathForConsistencyCheck: string;

291

}

292

```