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

serialization.mddocs/

0

# Serialization and Plugins

1

2

Pluggable serialization system for customizing how values are converted to snapshot strings. Supports built-in serializers for common data types and custom serializers for domain-specific objects.

3

4

## Capabilities

5

6

### Plugin Management

7

8

Functions for managing snapshot serialization plugins that control how different types of values are converted to string representations.

9

10

```typescript { .api }

11

/**

12

* Adds a custom serializer plugin to the beginning of the plugin list

13

* Plugins added later take precedence over earlier ones

14

* @param plugin - PrettyFormat plugin for custom serialization

15

*/

16

function addSerializer(plugin: PrettyFormatPlugin): void;

17

18

/**

19

* Gets all registered serializer plugins in priority order

20

* @returns Array of all registered plugins, with custom plugins first

21

*/

22

function getSerializers(): PrettyFormatPlugins;

23

24

type PrettyFormatPlugin = {

25

test: (val: unknown) => boolean;

26

serialize: (

27

val: unknown,

28

config: Config,

29

indentation: string,

30

depth: number,

31

refs: Refs,

32

printer: Printer

33

) => string;

34

};

35

36

type PrettyFormatPlugins = Array<PrettyFormatPlugin>;

37

```

38

39

**Usage Examples:**

40

41

```typescript

42

import { addSerializer, getSerializers } from "jest-snapshot";

43

44

// Custom serializer for Date objects

45

const dateSerializer = {

46

test: (val) => val instanceof Date,

47

serialize: (val) => `Date("${val.toISOString()}")`

48

};

49

50

addSerializer(dateSerializer);

51

52

// Custom serializer for database models

53

const modelSerializer = {

54

test: (val) => val && typeof val === 'object' && val.constructor.name === 'User',

55

serialize: (val, config, indentation, depth, refs, printer) => {

56

return `User(${printer(val.id, config, indentation, depth, refs)})`;

57

}

58

};

59

60

addSerializer(modelSerializer);

61

62

// Get all serializers (custom ones first)

63

const allSerializers = getSerializers();

64

console.log(allSerializers.length); // Built-in + custom serializers

65

```

66

67

### Built-in Serializers

68

69

Jest Snapshot includes several built-in serializers that handle common data types:

70

71

**React Components:**

72

- `ReactElement` - Serializes React elements and JSX

73

- `ReactTestComponent` - Handles React test renderer components

74

75

**DOM Elements:**

76

- `DOMElement` - Serializes DOM nodes and HTML elements

77

- `DOMCollection` - Handles NodeLists, HTMLCollections, etc.

78

79

**Data Structures:**

80

- `Immutable` - Serializes Immutable.js data structures

81

- `AsymmetricMatcher` - Handles Jest's `expect.any()`, `expect.objectContaining()`, etc.

82

83

**Jest Specific:**

84

- `jestMockSerializer` - Serializes Jest mock functions with call information

85

86

### Custom Serializer Implementation

87

88

Create custom serializers for domain-specific objects or to customize existing type serialization:

89

90

```typescript

91

// Custom serializer for URL objects

92

const urlSerializer = {

93

test: (val) => val instanceof URL,

94

serialize: (val) => `URL("${val.href}")`

95

};

96

97

addSerializer(urlSerializer);

98

99

// Before: URL { href: "https://example.com", protocol: "https:", ... }

100

// After: URL("https://example.com")

101

102

// Custom serializer for Error objects with stack traces

103

const errorSerializer = {

104

test: (val) => val instanceof Error,

105

serialize: (val, config, indentation, depth, refs, printer) => {

106

const name = val.constructor.name;

107

const message = val.message;

108

const stack = val.stack ? `\n${val.stack}` : '';

109

return `${name}: ${message}${stack}`;

110

}

111

};

112

113

addSerializer(errorSerializer);

114

115

// Complex custom serializer with nested printing

116

const apiResponseSerializer = {

117

test: (val) => val && typeof val === 'object' && val.type === 'api-response',

118

serialize: (val, config, indentation, depth, refs, printer) => {

119

const status = val.status;

120

const data = printer(val.data, config, indentation, depth, refs);

121

return `ApiResponse(${status}) ${data}`;

122

}

123

};

124

125

addSerializer(apiResponseSerializer);

126

```

127

128

### Serializer Priority

129

130

Serializers are tested in order, with the first matching serializer being used:

131

132

```typescript

133

// Order matters - first matching test() wins

134

addSerializer(specificSerializer); // Added last, tested first

135

addSerializer(generalSerializer); // Added earlier, tested later

136

137

// Built-in serializers are tested after all custom serializers

138

// Default object/primitive serialization happens last

139

```

140

141

### Serializer Testing

142

143

Serializers include a `test` function that determines whether they should handle a specific value:

144

145

```typescript

146

const customSerializer = {

147

// Test function - return true to handle this value

148

test: (val) => {

149

return val &&

150

typeof val === 'object' &&

151

val.constructor.name === 'CustomClass' &&

152

typeof val.serialize === 'function';

153

},

154

155

// Serialize function - convert value to string

156

serialize: (val, config, indentation, depth, refs, printer) => {

157

// Use the object's own serialize method

158

return val.serialize();

159

}

160

};

161

```

162

163

### Advanced Serialization Features

164

165

**Nested Object Printing**: Use the `printer` function to serialize nested values:

166

167

```typescript

168

const wrapperSerializer = {

169

test: (val) => val && val.type === 'wrapper',

170

serialize: (val, config, indentation, depth, refs, printer) => {

171

// Use printer for nested values to maintain formatting

172

const content = printer(val.content, config, indentation, depth, refs);

173

return `Wrapper(${content})`;

174

}

175

};

176

```

177

178

**Depth and Reference Handling**: Handle circular references and depth limits:

179

180

```typescript

181

const circularSafeSerializer = {

182

test: (val) => val && val.type === 'node',

183

serialize: (val, config, indentation, depth, refs, printer) => {

184

if (depth > 5) {

185

return '[Deep Object]';

186

}

187

188

const children = val.children.map(child =>

189

printer(child, config, indentation, depth + 1, refs)

190

);

191

192

return `Node(${children.join(', ')})`;

193

}

194

};

195

```

196

197

**Configuration-aware Serialization**: Access pretty-format configuration:

198

199

```typescript

200

const configAwareSerializer = {

201

test: (val) => val instanceof Map,

202

serialize: (val, config, indentation, depth, refs, printer) => {

203

const entries = Array.from(val.entries());

204

205

if (config.min) {

206

// Compact format for min config

207

return `Map(${entries.length})`;

208

}

209

210

// Full format

211

const items = entries.map(([key, value]) => {

212

const k = printer(key, config, indentation, depth, refs);

213

const v = printer(value, config, indentation, depth, refs);

214

return `${k} => ${v}`;

215

});

216

217

return `Map {\n${indentation} ${items.join(`,\n${indentation} `)}\n${indentation}}`;

218

}

219

};

220

```

221

222

### Serializer Removal

223

224

There's currently no built-in way to remove serializers, but you can work around this:

225

226

```typescript

227

// Get current serializers

228

const currentSerializers = getSerializers();

229

230

// Find built-in serializers (after your custom ones)

231

const builtInSerializers = currentSerializers.slice(customSerializerCount);

232

233

// Clear and re-add only desired serializers

234

// (This is a workaround - not officially supported)

235

```

236

237

### Integration with Snapshot Formatting

238

239

Serializers work with Jest's snapshot formatting options:

240

241

```typescript

242

// Snapshot format affects serializer output

243

const snapshotFormat = {

244

indent: 2,

245

printWidth: 80,

246

min: false,

247

escapeRegex: false,

248

escapeString: true,

249

plugins: getSerializers() // Your custom serializers included

250

};

251

```

252

253

## Types

254

255

```typescript { .api }

256

interface PrettyFormatPlugin {

257

test: (val: unknown) => boolean;

258

serialize: (

259

val: unknown,

260

config: Config,

261

indentation: string,

262

depth: number,

263

refs: Refs,

264

printer: Printer

265

) => string;

266

}

267

268

type PrettyFormatPlugins = Array<PrettyFormatPlugin>;

269

270

type Config = {

271

callToJSON: boolean;

272

compareKeys: undefined;

273

escapeRegex: boolean;

274

escapeString: boolean;

275

highlight: boolean;

276

indent: string;

277

maxDepth: number;

278

min: boolean;

279

plugins: PrettyFormatPlugins;

280

printBasicPrototype: boolean;

281

printFunctionName: boolean;

282

spacingInner: string;

283

spacingOuter: string;

284

theme: Theme;

285

};

286

287

type Printer = (

288

val: unknown,

289

config: Config,

290

indentation: string,

291

depth: number,

292

refs: Refs

293

) => string;

294

295

type Refs = Set<unknown>;

296

297

interface Theme {

298

comment: string;

299

content: string;

300

prop: string;

301

tag: string;

302

value: string;

303

}

304

```