Check out a free preview of the full Enterprise UI Development: Testing & Code Quality course:
The "Testing Project: Item in List" Lesson is part of the full, Enterprise UI Development: Testing & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve continues coding the solution to the Testing Project exercise. The tests written verify items are added to the "Unpacked Items List" when the "Add New Item" button is clicked. Testing the removal of an item is also included in this lesson.

Get Unlimited Access Now

Transcript from the "Testing Project: Item in List" Lesson

[00:00:00]
>> So then we wanna see that it's adding that item to the list. And here is where we get into a philosophical conundrum, which is this test that I'm gonna write is flawed. And before I was like, yeah, if you just had one test that went through the entire flow, that would totally work.

[00:00:23] Except that if I had done that, I would not have found that this test was flawed. This test, when I wrote it, I did not aspire to write a flawed test just to mess with you, right? I supposed to write a test to teach you something, and then I found out later it was flawed.

[00:00:39] And I kept it flawed, because then there was something more important to talk about based on that flaw. So we will do it, and I'm not gonna tell you what the flaw is just yet, because I feel like I would like to keep you in suspense. But if you can see it beforehand, you will get 50 points.

[00:00:59] Points work the same way they do in Super Mario Bros., which is they don't do anything, but you can get them. And so if anyone both in the chat, and in the room, and also if you're watching this later, you can also have 50 points if you get it before I tell you the answer.

[00:01:17] Cool, so we've got that in place and like I said, we copy and pasted some of the initial selectors, and we'll say, await user.type. NewItemInput, at this point, we'll grab, Let's grab an iPad Pro this time. And we'll type that in, and then we'll wait and we'll hit New, we'll hit that button.

[00:01:53] We'll click it, and we'll New item button. Boom, and then we can expect that, so by check boxes because I'm a good person, relatively speaking, have labels with the text. If you click the label, it also checks the checkbox so I can do get by label again. getByLabelText, and we want iPad pro.

[00:02:27] And we'll say that should not be checked in this case, not to be checked. Out of just pure curious as a bonus lap, I am pretty sure that should empty out the field and, I'm just fill and disables the button again. So if one wanted to go for a bonus round, they could then maybe expand this test to see if the input feels now empty again and the button is disabled.

[00:03:00] I think that would be good as well. Obviously, there's a lot more things that you could test. But a lot of this is just watching me select items and firing user events at them, which I think you've gotten the point. Okay, so that is basically more of a accurate in real world version barring network requests and other things you don't control, that's later.

[00:03:23] Where we can kind of just grab a component and kick the tires on. Again, I think component testing where I choose to use it the most is in particularly stuff like form validation, which is everyone's favorite part about being a front end engineer. And stuff along those lines where you can just do all sorts of stuff really fast, run through everything, get that immediate feedback that the form still works as expected, right?

[00:03:45] You could do the watch in this case, and just as you're making changes, see what you have. And to that just psychological aspect, writing the test first, getting them, failing them, watching them as they slowly turn green is very rewarding. Okay, so all my tests passed, it's not clear how I quietly sidestepped the issue here.

[00:04:10] But if you squint, you can see that I made a choice to avoid an issue here. Seems like super convenient for all the copy and pasting that I did that I chose for one test to use a MacBook Pro and the other one to use an iPad Pro, right?

[00:04:26] Seems like really, really just convenient that I made that choice. What happens if I change that back? We'll go ahead and we'll run that. This time, I might do in the terminal so I get, that one's running the test in isolation. I'm already ruining my own surprise. I'll go into source, and then we wanted the packing examples, packing list, npm test.

[00:05:04] Why is my tests passing all of a sudden? It's gonna ruin my whole surprise here. We've got it, because I know they got really ahead of myself here. Let's go ahead and write another one, remove it. And now, I've ruined the surprise.
>> You did the right one.

[00:05:22]
>> What's that?
>> You did it the right way?
>> No, I just thought that those tests, I actually I had it. And I'm like, you know what, it was just running the second time. And we'll get it and then, since I ruined my own surprise, I've tried to built it up too.

[00:05:38] Look, it fails, which is weird, cuz all I did was copy and paste the same test. It's totally passed, right? And this is what we're talking about the difference between getBy and I thought I was leaving something for later. We've got to getBy MacBook Pro, and it says, let's read the error message.

[00:06:00] It says, scrolling up, is it down here? No, I guess scroll up a little bit more. Which is nice, I get to see the DOM in this case, right? Look, found multiple elements with the text MacBook Pro. Here are the matching elements, and they look roughly the same.

[00:06:20] They have two different IDs. But other than that, they're on the page. But why? How did that happen? I don't understand what's going on here. Clearly, and we'll see that if I skip this other test. Then everything is fine. So one of the things we look for in our tests is this idea of test isolation, right?

[00:06:45] The idea is running two tests should not break each other, right? And this is one of those things where it is very easy to be like, know you what, I'm just gonna leave both those tests as I was going, open the PR, hope nobody notices. Because you don't have the checks that we're talking about the GitHub actions.

[00:07:05] You try to slide it in there, you get the ticket marked down, you get it merged in, then you go on your weekend, right? That's why you need the build process in there with the GitHub actions to test for the code coverage. Are there ways even tests like, hey, for this given file, are there enough tests, so on and so forth.

[00:07:21] I might if I didn't have to like stand up here in front of you all, and it was I might choose to delete one of these tests. So in this one, let's make this one a real test. Removes an item. So the goal is effectively at the end here to say, We'll say, const, removeItem is screen.getByLabelText MacBook Pro.

[00:08:03] This doesn't really matter, cuz this test will blow up no matter what for the reasons it blew up before. And then we'll say, await, I need the, let me look at the DOM real quick. Yeah, there's only one Remove button on the page in this test. So let's actually getByLabelText, Remove, await use.click, removeItem.

[00:08:43] And then we'll, There's a blow up, and then we'll deal with it afterwards. This test is also good, because it still blows up for the same reason. And when it gets passed on, we could add more to it. So my problem here is that I don't have test isolation, which is tricky, because like I am rendering that component brand new every time as a fresh component and different from the last one.