Testing React Components with JSDOM
00:00 So, let's pop open this file, and we need to add a JSDOM comment pragma at the top. So, by default, our tests are all running in Node, but for this particular test, even though we can server render React components and stuff, we're typically concerned about the client-side render of our components,
00:20 and more often than not, you're going to want to test user events and stuff like that. So, we're going to add the VTestEnvironmentJSDOM thing here. So, VTestEnvironmentJSDOM. So, that turns this into a JSDOM test. Let's test that out, actually.
00:38 So, we'll just say, test test. There we go. And we'll console.log window, and save that. And test is undefined. Of course, we're going to need to import, test, and expect from VTest. There we go. Okay. So, this is going to give us this global object.
01:00 We've got a whole bunch of nonsense on this thing. We can also do document. Document. There we go. And there's our document. Okay. If we don't have this JSDOM pragma in here, then we save that, and it's not defined. So, that's what the pragma is doing, is it's giving us a simulated DOM environment for
01:22 our lower-level tests that don't really make sense to run in a real browser, just because the extra weight that a real browser adds to our tests. And so, this is for when a simulated DOM environment using a tool like JSDOM can be quite helpful. But you do need to be aware that this is still running in Node.
01:41 It's not a real DOM. And often people will blame testing library for things that are actually problems with the simulated DOM. Testing library runs in real browsers, as well as in a simulated DOM. And most of the time, problems that you have with testing library are probably a result
01:59 of running with a simulated DOM, which is, yeah, it definitely comes with trade-offs. But this is still the way that I recommend you do these kinds of tests. And so, that's why we're doing it today. Okay, so let's actually write a real test.
02:18 So, the form error list test, it shows nothing when given an empty list. We're going to do the easiest case first. We're going to need to import the error list component, there we go, from the forms.
02:34 And we're also going to need to bring in a render and a screen, QRS. I like to try and alphabetize my imports, I don't know why. So, we bring in render. We're going to await that. So, this is async.
02:51 In a recent version of React testing library, render has turned to an async operation. So, we're going to say await render error list. And with that then, that's going to populate our DOM. So, here's what we're going to do. We're going to use a screen.log or debug right here.
03:11 And then we'll put a screen.debug right here. And so, here's the before and here's the after. Once we render that error list with no errors, then we do get this div. This is a div that's actually created for us by testing library when it renders our component.
03:28 And so, because we're not rendering any errors, we're going to get null in return here. So, that's why this container, this div has no children. But we could also test out h1 and hello h1. And you'll see that that does appear inside the container.
03:48 And so, this screen debug is actually a really, really helpful tool to give you an idea of what the DOM output looks like so that you can start querying around for things. So, what we want to do is if there are errors, then we say one, save that. And we've got a UL right here.
04:05 So, what we're looking for is just to make sure that there are no list items. And in testing library, with the number of queries that you have, the one query that you use when you want to assert that something is not there is screen.queryBy and then we'll do the role variant. So, we're going to query all of the list items.
04:26 And with that, we'll expect that to have length of zero. So, there should not be any of those. And that is failing, of course, because we changed our test there. So, let's get rid of that and save that. And let's see, we've got target cannot be null or undefined.
04:47 Oh, that's interesting. We want to actually say query all by role. So, we want to get all of the list items. What queryBy role is going to do is it's going to find the one list item that's on the page and it's going to return null if it can't find it. We want to get an array of all of them. And so, that is how we go about doing that. We have a length of zero.
05:08 Okay, awesome. And let's take a look at this to make sure we can break it. So, if I say li hi, then we do in fact break it. So, we are executing the code that we think we are. And of course, you can run the code coverage on this test to make sure that you're covering
05:26 the lines of code that you think you are. But again, whenever you do that, you want to focus on the experience of what the use case is rather than the lines of code. All right. So, just a quick review. We have VTestEnvironment.js DOM to give us a DOM to work with.
05:44 We grabbed render and screen from testing library. And then we await render error list and expect query all by role list item to have a length of zero. So, that's our first test with testing library.