Check out a free preview of the full Intermediate React, v4 course:
The "Snapshots" Lesson is part of the full, Intermediate React, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates how snapshots save a rendered version of a component to a __snaps__ directory in the project. Future tests of the component will compare what's rendered currently to the snapshot. If the component is different, the test will fail. Shallow renders are also covered in this segment.

Get Unlimited Access Now

Transcript from the "Snapshots" Lesson

[00:00:00]
>> So I'm gonna show you a feature of, Jest that I'm not a huge fan of, but I think you should know about it. It's called Snapshot. It's very divisive, people either love it or they hate it. They're called low confidence, low cost tests, because they're super easy to implement, but they mean next to nothing, not quite nothing, next to it.

[00:00:32] So make a new file here. We're gonna write a test for Results.test.js. Need our pragma, I'm just gonna copy that here from that, and then we're going to import ( expect, test) from @jest, Jest/globals. Import {create} from react-test-render, which we're gonna have to NPM install here in just a second, and import Results from ../Results So react-test-render, actually, is put out by the react team themselves, it's just a really simple render, it's even simpler than react-test-library.

[00:01:42] So go ahead and with me say npm install -D, react-test-renderer, right? Make sure that you have erer, I know that's kind of odd, but it's a renderer, @17.0.2. So this will match whatever version of react you are using, right, they release those things all at the same time.

[00:02:09] Okay, now we have that. We can run our test watch again, that's fine. It's failing at the moment, that's expected. Test renders correctly with no pets. This one doesn't have to be async, it could be, doesn't matter. const tree = create(Results). pets equals nothing, right, so we're not gonna give it anything at the moment.

[00:02:49] And we're gonna get that toJSON. And then we're gonna say expect(tree) toMatchSnapshot, that went down there. So you can see here, this test immediately passed, and you can see here one snapshot was written. So you can see here it created this _snaps directory here, and if I click on this and look at that, we get this.

[00:03:27] You might not have syntax highlighting, you have to install an extension to get that, it might even prompt you like, hey, do you wanna install this? And the answer is maybe. So what it does here is it just renders it out and then it says, okay, this is what this looks like, and the first time you run it, it assumes this is correct.

[00:03:45] Now, if I go back and I say inside of Results and I just maybe add a couple of question marks, like this, right, so now it's gonna render something slightly different. Now, if I go look at my tests, it's gonna say your tests failed because last time I rendered this, I found this, and now that you have a bunch of question marks here, this does not match anymore.

[00:04:03] Therefore, I will fail your test. Now, I need you to ask yourself, do I think that's useful? This literally took me 10 seconds to write a test, right, so it's low cost, but do I care? My answer is no, I don't care, I don't write these tests anymore.

[00:04:31] But there's other people who love them because, this is the shortcut to get 100% test coverage. So that's what that is. Now, you can basically see here, say here, Let's say I'm happy with this and I actually do want it to have all those question marks, so I don't want it to fail anymore, I can say, if I hit u here, Or even better, I can hit i.

[00:05:09] So if I hit i, it's gonna say, I found this snapshot, do you wanna save this one? Let's say you broke a bunch of them all the same time, you could say, update this one, update this one, don't update this one. So this one, I'm gonna say, update, I updated the snapshot.

[00:05:26] And now if I look at my snapshot here, you'll see that this is correct, and it saves that, and this is something you would commit to Git. So again, I don't find this particularly useful, but you might. But let's take this a little step further, I got some dummy data here in Snapshots.

[00:05:50] If you wanna go copy and paste this cuz I definitely don't wanna, I do not wanna write that myself. Wow, don't do that. Okay, so I'm gonna go grab that. And here underneath that, Okay, I put in a bunch of dummy data now, that's fine. Okay, and then down here, I'm gonna, So this react-test-renderer, this is just going to blindly render out everything.

[00:06:37] And it's gonna go down to all of the leaf nodes as well. This can be problematic. So let's say I have this here, if I write a test here now using the same renderer, if you remember in Results.js, this renderer's pet, right? I actually don't wanna render all of my pets in my results snapshot, right, because if I have a problem in my Pet.js test, I want that test to fail.

[00:07:02] I don't want my results test to fail, because that's now misleading, right? The point of your test is to tell you precisely where something is going wrong, and if I have something going wrong and pet pointing at my results test, I'm gonna go check results, which is gonna waste a bunch of time.

[00:07:17] So what you can do is you can do what's called a shallow render, so we're gonna do that really quick here. So up at the top here, I'm going to import ( createRenderer ) from react-test-renderer/shallow. This one's fine, I don't have to do anything for that top test, this one.

[00:07:46] But here, in this test, my second one, I'm gonna do, Renders correctly, oops, I didn't put that in the string, renders correctly with some pets. Again, this doesn't need to be async cuz we are not doing anything async in here. And we're gonna say const tree =, What did I call that?

[00:08:21] createRenderer. Oops, there we go, sorry, const r = createRenderer. And then here, I will say r.render( <Results pets = (pets). And then I'll say expect( r.getRenderOutput), To match in line or to match snapshot. Okay, so now I got a second snapshot in here. Let's just minimize that, Okay, so now renders correctly with some pets.

[00:09:35] Notice it's not actually rendering what's inside of pet, it's rendering this kind of high level pet, right? It's rendering the name of the react component and it's not actually rendering what's inside of pet. This is much better cuz now I can just investigate like, all right, this is passing all the things that I expect into pet, and now I can write separate tests for pet that test all these various different things.

[00:09:57] So I have here my notes, if you wanna write it the other way to see what it looks like. But basically, it would just render everything here that's in pet, it would render the a tag, the div, all that kind of stuff, which is not what we wanna do.

[00:10:12] This is slightly maybe 5% more valuable, right? I can see what I expect from giving these sets of parameters into results, I expect these sorts of parameters going out. I see some value in that, but, again, there's such thrash in UI code that I just, in general, kinda skip these tests, cuz I feel like I'm just chasing coverage at that point.