Testing Fundamentals

Accident Counter Solution

Steve Kinney

Steve Kinney

Temporal
Testing Fundamentals

Check out a free preview of the full Testing Fundamentals course

The "Accident Counter Solution" Lesson is part of the full, Testing Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Steve continues the solution for the Accident Counter exercise. This lesson includes the tests for displaying "day" when the count is 1 and decrementing the count when the decrement button is clicked.

Preview
Close

Transcript from the "Accident Counter Solution" Lesson

[00:00:00]
>> Steve Kinney: Displays day when the count is one, right? This is kind of a variation of the last two tests that we wrote. So in this case, we will need that increment button, which I'm just gonna steal from up here.
>> Steve Kinney: And we're gonna want that unit that we saw earlier.

[00:00:23]
>> Steve Kinney: And we'll do it, the act, from the very beginning here. Again, in this case, it doesn't really matter, but, again, you want your test to be resilient for known welcome changes. So in this case, we will say await, and we'll say.
>> Steve Kinney: And you can see that there are also the cool thing about the user event object is there are a whole bunch of other things you can do.

[00:00:53]
Obviously, in cut, copy, can hit various keyboard things, if you just wanted to hold down like left shift. You can do that with this library, right? And a whole bunch of other fun things like that as well. There's more than just the very basic events that you could fire, but that's all we really need in this case, userEvent.click on the incrementButton.

[00:01:18]
>> Steve Kinney: You gotta make this an async function, cool. Great, and so now we can expect that that unit,
>> Steve Kinney: To have text content day.
>> Steve Kinney: Awesome, decrements the count when the button is clicked. Okay, so this is an interesting philosophical dilemma here, which is how can we verify that the decrement button.

[00:01:59]
The count if it's not enabled unless we increment it, we have two choices. And it's really, this is a philosophical issue, there's not a right answer. Either a, you increment it and then decrement it, that'll do the trick, or b, you could theoretically have,
>> Steve Kinney: An initial count prop and start it at one, in which case that before each is no longer serving you.

[00:02:33]
Cuz you might wanna put that component in different states based on the props that you pass in. Which one do we wanna do? Do we wanna have a prop that we set up, or do we want to increment and then decrement it? Choice time.
>> Female Student 1: I say prop.

[00:02:49]
>> Steve Kinney: All right, let's prop it, so we've got initial count. I write TypeScript every day, and the idea that I don't have to go through all the hassle of typing this right now is disorienting to me, but I'm kinda into it. So we've got this count, and, really, all we need to do here is.

[00:03:10]
>> Steve Kinney: And for the ones that don't have that, I'm just gonna say that count is by default zero. Look, I refactored.
>> Female Student 1: [LAUGH]
>> Steve Kinney: And I know that I didn't break anything. Because my test pass, I was not even confident that was gonna be green. But I get to move on with my life because my test pass.

[00:03:31]
So, but the idea that we might wanna make this component in different states leads me to now resent the fact. And this is why I don't do it in my own code a lot of times, to be honest to you, that I have this before each, right?
>> Steve Kinney: Because, yeah, sure, I wanted to 0 the rest of the time.

[00:03:53]
And I kind of seeing it all in one place personally, you could argue that's tedious but I'm already doing tedious stuff, testing is tedious. Testing is an investment in future you.
>> Steve Kinney: All right, let's see. All right, decrements. All right, we'll render the counter, this time, we'll do it with an initial count of one, there are some other tests that I might choose to write here too beforehand, right?

[00:04:26]
Again, I could say that it is not disabled when the count is one, right?
>> Steve Kinney: Screen.getByRole
>> Steve Kinney: Button.
>> Steve Kinney: Decrement/i, this isn't the name of the test, but this is a test I would likely add to, which is, decrement button if the count is one, not toBeDisabled.
>> Steve Kinney: Start with that test, it failed.

[00:05:29]
Why you fail?
>> Steve Kinney: Because it's decrementButton and not decrement. Cool, so we expect it not toBeDisabled, now we know that that state is there. Now you can go refactor knowing that out of the box it will be disabled if the count is 0, and the decrement will be enabled if it's not 0 in this case.

[00:05:53]
And then cool. And again, I might choose to make that its own test as well, but for our purposes, I'll keep going. It decrements the count when things are clicked, so we're also gonna need that count.
>> Steve Kinney: GetByTestid, (`counter-count`).
>> Steve Kinney: Great, and then we'll do the full act thing just so we get in the habit now, so it doesn't hurt us later.

[00:06:36]
>> Steve Kinney: So now, we act on the fact that we want to go ahead and,
>> Steve Kinney: userEvent.click, and we'll say, on our (decrementButton).
>> Steve Kinney: And now we can expect.
>> Steve Kinney: Does it count? Yeah, it counts.
>> Steve Kinney: Cool, it passes, there are some other tests that would shake out of this, though.

[00:07:18]
We could write, which is we could have a test with if you pass in an initial count, that better be what I see on the screen, right? That's a test that would shake out of this. We can expect that if we have one where we set the initial count to 1 and make sure the same way we had a test making sure that the decrement and reset button were disabled when it was 0.

[00:07:40]
Well, if we set it to one, they shouldn't be disabled, right? You'd break that out into small tests, you're getting the same value out of voting into one test. But it's always nice when you see the test fail to know exactly what the issue is, right? Which is weird, cuz when we talk about Playwright later, the advice is the opposite.

[00:07:56]
Cuz the cost of spinning up the browser and tearing it down is so big that, spin it up, go through an entire flow and take it back down again. So all of these things are less immutable laws and more a reasoning behind them for your own happiness. In this case, I would probably start to break those out as well.

[00:08:18]
And arguably, if it was back down to 0, you could even write a test to say that it should be disabled again, right? You could overload a test, but then you might choose to name it differently, but let's just make our point. If it's back down to zero, then we assume that it's disabled again, right?

[00:08:39]
Now, if this test fails, you're gonna have to squint a little bit harder to figure out exactly what line it failed on what step. But you also know that you have one test that kind of exercise this component in set it to one, make sure the button is not disabled.

[00:08:52]
Hit the button, make sure it went down to zero. Make sure the button now is disabled. You got a decent amount of coverage out of one test, too, so it becomes a balancing act. Cool, this is a fun one, so we'll render that counter.
>> Steve Kinney: Okay, so it should be 0 at that point, and what we'll do is we'll go ahead and get that decrementButton again.

[00:09:22]
Which we know is disabled, but we wanna make sure that despite the fact this is disabled, that clicking on it, is not gonna break anything. Make sure all right, didn't have a to do sitting on it still. Okay, so then we can do,
>> Steve Kinney: I guess we need that count too.

[00:09:51]
>> Steve Kinney: So now, we'll say,
>> Steve Kinney: This one truly won't matter, because ideally nothing happens if you click a disabled button. So we'll say await userEvent.click on the decrementButton, and we expect count to still be 0 at that point, not -1 or anything like that.
>> Steve Kinney: Cool, so with this one, one of the things we can keep in mind with this one is we're not always stuck to only using the testing library stuff.

[00:10:39]
Like I said before, if you need to use document.queryselector, you can, right? There's nothing stopping you from using these things, but in this case, let's go ahead and we'll get the incrementButton again. IncrementButton = screen.getByText, no, I want getByRole. Button with the name, I've got to render that thing again this time, too, increment/i.

[00:11:11]
>> Steve Kinney: Right, and then we will, let's do the act again here. Yeah, this one will work without this, but I think it's important and we should do it. I'll show you a few other tricks in a second where we will, wait
>> Steve Kinney: UserEvent.click on that (incrementButton), and this might be one where I do a little test before and after.

[00:11:44]
I just gotta make that async too, or await it as well. And so at this point, I'm gonna just expect (document.title) to be
>> Steve Kinney: 1 day.
>> Steve Kinney: And we fell because I never rendered that thing, even though I was, I gotta remember to render that component again.
>> Steve Kinney: It's I got a full, that's fine, that's a good mistake.

[00:12:36]
>> Steve Kinney: I think that's a to start with, we're got to find that in one second. This is because I decided to put the title on the end.
>> Steve Kinney: I would probably for this one do
>> Steve Kinney: Cool, and so that way if I put the title of the app after the 1 day, or whatever.

[00:13:15]
So this one is just basically saying, as long as it has that 1 day in it, and I could click it again, make sure has 2 days. The other cool thing that this does as well is, right now, these are all starting from the screen. I could do something like this, which is const.

[00:13:40]
>> Steve Kinney: GetByRole, and this is going to then be scoped just to that component, rather than the whole screen as well. Which can also be useful if you just wanna that way, if you had, remember, we said, days could be many places you can kind of get to that lower level of granularity there too.

[00:13:58]
So this will be a scoped version for this instant as well, or you can use the one from screen, both will work.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now