According to the Jest official documentation it states that snapshots are a great new way of testing UI components.
I so agree with that statement.
Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.
For example, if you were performing a UI test with Jest, a typical snapshot test case for a mobile app renders a UI component, takes a snapshot, then compares it to a reference snapshot file stored alongside the test.
The test will fail if the two snapshots do not match — either the change is unexpected, or the reference snapshot needs to be updated to the new version of the UI component.
This is how you could test the UI snapshot.
I could focus on the UI example, but for the sake of proving the snapshot concept in Jest I will look at something that goes beyond just the UI. In reality with Jest snapshots it's possible to test and assert the output of any serializable value.
To illustrate the example of snapshot testing in Jest, let's do the following:
Let's create a new file. Let's now save this file and call it snapshots.test.js
.
Now I'm going to be pasting some code in here and then talk you through it.
var itemStock = [
{ 'Id': '1', 'ItemName': 'Razors', 'Stock': '10' },
{ 'Id': '2', 'ItemName': 'Socks', 'Stock': '1'},
{ 'Id': '3', 'ItemName': 'Towels', 'Stock': '100' },
{ 'Id': '4', 'ItemName': 'Socks', 'Stock': '100'},
];
function filterItemStock(arr, key, term) {
return arr.filter(function(obj) {
return obj[key] === term
});}
test('it returns all items with matching Id',() =>{
expect(filterItemStock(itemStock,'Id', '1')).toEqual([
{ 'Id': '1', 'ItemName': 'Razors', 'Stock': '10' }
])
})
test('it returns all items with matching Item Name',() =>{
expect(filterItemStock(itemStock,'ItemName', 'Socks')).toEqual([
{ 'Id': '2', 'ItemName': 'Socks', 'Stock': '1'},
{ 'Id': '4', 'ItemName': 'Socks', 'Stock': '100'},
])
})
Let's save this file.
Let's assume the following scenario.
We have a list of items which we call itemStock
and it's stock count stored in some form of an array object.
In some way we want to be able to filter with one of its attributes. So as mentioned, this is our item’s stock count, which basically has an id and then the ItemName
with it stock count.
We then have the filter function filterItemStock
, which basically looks at the array above and then with specific keys
or terms
, it will filter by those and then return the object based on that filter.
Then we proceed to adding a test.
In here we basically have the test that will return all items with matching id.
In this instance, we look at the itemstock
and we have id equals to 1.
So, in that instance we have id equals to 1 which is “Razors” with a stock count of 10. That's what we assert on.
We then have a second test, which basically returns all items with matching item name.
In this instance, it’s “Socks”. As you can see, we have 2 items in the array — one with a stock count of 1, and one with the stock count of 100.
So, this is great; let's run this test and see what happens.
The tests passes as expected.
Usually when testing something similar to this, we need to manually type and assert each expected return value.
This looks awesome, but if in future we need to change our data, we need to manually update each test.
You can imagine what a boring, mundane task that could be. Especially if the data is prone to be changed consistently.
Well, don't fear. Enter snapshots.
With snapshots you could just replace some of the code above with the toMatchSnapshot
function.
Let's now look at that.
Let's copy the two tests that we have. Now let's paste this here below the other tests.
Now, instead of having this entire line:
Let's now replace this with toMatchSnapshot
.
Let's just copy this line. Now let's replace this entire part in the 2nd test.
var itemStock = [
{ 'Id': '1', 'ItemName': 'Razors', 'Stock': '10' },
{ 'Id': '2', 'ItemName': 'Socks', 'Stock': '1'},
{ 'Id': '3', 'ItemName': 'Towels', 'Stock': '100' },
{ 'Id': '4', 'ItemName': 'Socks', 'Stock': '100'},
];
function filterItemStock(arr, key, term) {
return arr.filter(function(obj) {
return obj[key] === term
});}
test('it returns all items with matching Id',() =>{
expect(filterItemStock(itemStock,'Id', '1')).toMatchSnapshot();
})
test('it returns all items with matching Item Name',() =>{
expect(filterItemStock(itemStock,'ItemName', 'Socks')).toMatchSnapshot();
})
Now let's save this.
Let's run this test now.
Just for the purpose of this example, I just want to expand this window.
npm run test snapshots.test.js
Great.
That test passed, but something else shows here.
It shows two snapshots written and then we look at a new folder that's created here.
So, let's look at this.
Let's expand this and see what's stored in here.
Wow! Look at this.
It's basically created snapshot of our expected value in here as an array that's basically similar to the assertion that we had previously.
Let's now change this value to that changing the item name to “azors” instead of “Razors”.
Let's save this test.
Now let's run it one more time and see what happens.
That now fails because we've changed our snapshot value.
As you can see, 1 snapshot failed.
So, let's revert that back.
Let's save this. Let's try it one more time.
There we go, it passes.
As you can see, snapshots are extremely powerful and definitely bring a nice fresh element to testing in Jest.
Congratulations.
You have now come to the end of the “Getting Started with Jest” course.
I hope you now know way more about Jest, and you should be well on your way to comfortably creating Jest tests.
Thank you and happy Jesting.