I've been setting up a new Ionic Framework (with React) project from scratch. I want it to be the baseline for all my future projects. I'm configuring it to have the development workflow I prefer including testing with React Testing Library.
In one of my tests, I take a snapshot of each route. This may not be a great idea, and I may remove it later. However, for now, it works. Unfortunately, after making a few modifications to the structure of the project, my snapshots started failing. This was due to adding a ViewManager
.
My snapshots began failing like this:
At first, I just went ahead and updated my snapshot because that's the new norm. Unfortunately, all the subseqent test runs also started failing with issues like this:
Clearly the IonRouterOutlet
is generating a unique id on every render. So, how to solve? After some digging, the solution turned out to be a custom Jest snapshot serializer.
At first, I had no idea what a serializer was doing under the hood; so, I resorted to the console log:
expect.addSnapshotSerializer({
test: val => typeof val === 'string',
print: val => {
console.log(`val="${val}"`);
return val;
},
});
The serializer has a test
that lets you decide if you're going to modify the value. In my case, I wanted to edit strings only. Next, I just logged out the value so I could see it in the terminal. It looked like this:
That string 8R2L6TJCYP
seemed to be the culprit. So, I just decided to rewrite to always be a consistent string:
expect.addSnapshotSerializer({
test: val => typeof val === 'string',
print: val => {
console.log(`val="${val}"`);
const newVal = val.replace(/^[A-Z0-9]{10}$/g, 'ABC123');
console.log(`newVal="${newVal}"`);
return `"${newVal}"`;
},
});
Basically, the regex looks for any 10 character string that has any combination of uppercase letters and numbers and replaces it with ABC123
.
Now, there is some risk to this approach. Some other string in the code could match that pattern. However, I feel pretty comfortable with it. I don't know any developers that use class names or properties with uppercase letters. If this ever became a problem, I could look at hardening this serializer.
Now, the logging looks like this:
One odd thing about the replacement string is that I had to wrap it in quotes. I don't know why exactly, but not doing so led to all quotes throughout the snapshot being replaced like this:
Now, my snapshots are no longer different between runs because they always look this:
You can do a lot more with serializers. For example, you can format test strings or modify objects as well. Checkout this example by Kent C. Dodds.