Transcript
00:00 Okay, who's ready to learn about component testing? We're going to be testing components. It's going to be awesome. So as part of this exercise, I want you to think about two users in particular. The end user who's going to be clicking the buttons of the components that you're rendering or just visually seeing,
00:18 or through a screen reader, seeing the different elements that you're rendering, and then the developer user that's going to be rendering your component. They're using the JSX syntax with your component and they're passing props, and they're expecting any callbacks that they pass to your component to be called in a certain way. So those are the two users that
00:38 our application components are going to have. But sometimes, we're going to write tests that bring in a third user that I call the test user. So this is basically a user that understands the implementation of your component and they should not.
00:57 So you want to avoid the test user in that your test should do only what the previous two users, these two users, could do with your component and nothing else. So if you're asserting on state of the component, like some internal state, which I don't think you can really do very reasonably well with hooks,
01:16 but I've learned that you never underestimate the length that people will go to test implementation details. So you're not going to be testing state, you're not going to be mocking the React hooks or anything like that. Just let those hooks do what they do and you interact with
01:33 your component the same way an end user or a developer would. So that always comes back to our guiding principle for testing. The more your tests resemble the way your software is used, the more confidence they can give you. So I want to give you a ton of confidence and that is why we're using testing library for testing. So as a quick example,
01:53 I've got here a counter that just uses some state and then increments every time you click on the button. To test this with testing library, we're going to render that counter to the document, and then we're going to get that button on the screen, and then we will expect the text content to be a certain value.
02:12 We'll click on that button using this user event utility that allows us to simulate browser events. If we're talking about our different users, then we've got our developer user who's going to be rendering our stuff to the screen, and then we've got our end user who's going to be finding the button,
02:32 and that end user is going to expect that count to be set to zero. Then our end user is going to click on that button, and then our end user is going to verify that it was incremented properly. So everything in your test, you should be able to look at this and be like, okay,
02:49 which one of those two users was it that this line of code is representing? This applies to more than just our component tests, it actually applies to all the tests that we write. You want to try and simulate
03:05 those two users and try to avoid anything that those users couldn't do. Speaking of simulation, we are actually also simulating a DOM. So our tests with VTest are all running in Node.js, but you can actually simulate a DOM environment. That's where our browser is going to be running,
03:23 our events like click events and everything like that, our component is going to be running in a real browser. But we want to keep our tests in Node because they'll run faster that way, there are a lot of really awesome features that we get out of VTest, or Jest if you're using that as your testing framework, you get a lot of value out of those.
03:42 So for that reason, we want to simulate the DOM environment in our Node environment. So there are a couple of solutions to this, and the most popular by far is called JSDOM. There's also another one called HappyDOM. But I use JSDOM primarily because it is more spec compliant.
04:00 It's not perfectly spec compliant and it doesn't implement everything that the browser has to offer. So sometimes you do have to go and run things in an actual browser, like in Playwright or something. But it does a pretty good job for most of the tests that we write. So you can add this pragma at the top of your file to say,
04:19 hey VTest, I want this file to be run with the JSDOM environment, and then it will have the JSDOM environment set up. So that way you can run all of your server-side tests and all of your DOM-based tests in the same test run, and each one can be in its own environment, which works out nicely.
04:37 Then finally, I wanted to talk about DOM assertions. So this up here where we have expect the text content to be this and whatever, the error messages you get from that are not super useful. I mean, they're not terrible, but we can make them better,
04:51 and that's why we have our custom assertions from JSDOM as a library, and it allows us to customize these assertions. Now, we're using JSDOM here, but it actually, because VTest is not really a fork,
05:08 but it's basically a sibling project alongside Jest and does use a lot of the same underlying libraries and things. For that reason, we actually can use those same assertion extensions. So once you include this, which we have set up,
05:26 then you can have assertions like to have text content, and a whole bunch of others that are really, really useful. What that does is it allows our test to be a little bit more expressive of our intent and also allows us to have much better error messages. So with all of that background information for you,
05:45 I'm excited for you to jump into this exercise. So have a good time testing components.