Jest Snapshot Serializers

Luis Vieira
Jul 25, 2017 · 3 min read

One of the best practices for properly using snapshots is to commit them, so that others can code review the changes you’ve made to the expected output.

For this process to work smoothly your snapshots need to have a clean and highly readable output, that makes it really easy for others to see and identify the changes made.

I’ve previously touched on some best practices for doing this with react components.

But if you’re using snapshots to test something else than a react component there are also some improvements you can do to improve the readability of your snapshots.

You can adjust and format the output of a snapshot to make it more readable by using snapshot serializers (note that snapshot serializers are available in Jest 19+).

Given the following example:

var ToDos = [
{ 'Id': '1', 'Title': 'Shop groceries', 'Status': 'done' },
{ 'Id': '2', 'Title': 'Go to gym', 'Status': 'pending' },
{ 'Id': '3', 'Title': 'Kill it with fire', 'Status': 'done' },
{ 'Id': '4', 'Title': 'Take snapshots', 'Status': 'done' },
{ 'Id': '5', 'Title': 'Be awesome', 'Status': 'pending' },
];
function filterTodos(arr, key, term) {
return arr.filter(function(obj) {
return obj[key] === term
});
}
test('it returns all todos with matching Id',() =>{
expect(filterTodos(ToDos,'Id', '1')).toMatchSnapshot()
})
test('it returns all todos with matching Title',() =>{
expect(
filterTodos(ToDos,'Title', 'Shop groceries')).toMatchSnapshot()

})
test('it returns all todos with matching Status',() =>{
expect(filterTodos(ToDos,'Done', 1)).toMatchSnapshot()
})

This would output the following snapshot:

exports[`it returns all todos with matching Id 1`] = `
Array [
Object {
"Id": "1",
"Status": "done",
"Title": "Shop groceries",
},
]
`;
exports[`it returns all todos with matching Status 1`] = `
Array [
Object {
"Id": "1",
"Status": "done",
"Title": "Shop groceries",
},
Object {
"Id": "3",
"Status": "done",
"Title": "Kill it with fire",
},
Object {
"Id": "4",
"Status": "done",
"Title": "Take snapshots",
},
]
`;
exports[`it returns all todos with matching Title 1`] = `
Array [
Object {
"Id": "1",
"Status": "done",
"Title": "Shop groceries",
},
]
`;

We can then ‘prettify’ this output with a serializer:

expect.addSnapshotSerializer({
test:(val) => val.Id && val.Title && val.Status && val.expiration,
print:(val) => `ID: ${val.Id}
Title: ${val.Title}
Status: ${val.Status}
Expiration: ${val.expiration}`
})

And then your output should be:

// Jest Snapshot v1, https://goo.gl/fbAQLPexports[`it returns all todos with matching Id: 1 1`] = `
Array [
ID: 1
Title: Shop groceries
Status: done
Expiration: 23/03/17
,
]
`;
exports[`it returns all todos with matching Status: done 1`] = `
Array [
ID: 1
Title: Shop groceries
Status: done
Expiration: 23/03/17
,
ID: 3
Title: Kill it with fire
Status: done
Expiration: 23/03/17
,
ID: 4
Title: Take snapshots
Status: done
Expiration: 23/03/17
,
]
`;
exports[`it returns all todos with matching Title: Shop groceries 1`] = `
Array [
ID: 1
Title: Shop groceries
Status: done
Expiration: 23/03/17
,
]
`;

How to create a serializer?
The ‘addSnapshotSerializer’ function gives you acces to two callbacks ‘test’ and ‘print’ which both receive each of the values returned by your test cases.
In the ‘test’ callback you can create a condition for the use of the serializer, like the existence of a given set of values. And in the ‘print’ callbak you can format the ouput of the snapshot by using each of the values as you please.

I haven´t found much documentation on creating serializers but this seems to be a handy tool when dealing with more complex snapshots.

This a great example of usage for a snapshot serializer:

Image for post
Image for post

This is a test for a binary search tree algorithm that outputs and diffs the test results as an actual tree, you can check the source at: https://github.com/jiayihu/pretty-algorithms

Resources:

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store