Check out a free preview of the full Enterprise UI Development: Testing & Code Quality course:
The "Testing Project: Disabled & Enabled Button" 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 the "Add New Item" button is disabled when no input is present and is enabled when text is entered into the input.

Get Unlimited Access Now

Transcript from the "Testing Project: Disabled & Enabled Button" Lesson

[00:00:00]
>> So it has an Add New Item button that is disabled when the input is empty, right? Cool, so things that I'm thinking as I look at this test is maybe I would want to make sure that the input field is empty. But then the other thing I'm thinking is I would wait for this test to break once or twice before I worried about all that.

[00:00:19] You know what I mean? But if it was one of those things, where for some reason, my test isolation was not good or in certain cases, right? If I was let's say, as an edit blog post, it might not always be empty, right? In those cases, I would maybe add some nuance, or set it to empty, or something along those lines.

[00:00:39] So but at this moment, that feels like a little over the top. So a pass and we'll render the packing list and if one wanted to, they could do it before each and keep an enclosure scope. I don't want to, like I said, in case I do wanna start passing it in props or something like that, maybe start to populate, again, if it was an edit blog post or something like that, I would then have to unwind all of that and put it back in.

[00:01:09] And honestly, this one line isn't bothering me enough to prematurely optimize that cuz, yeah, the cost of getting that wrong is higher than the good parts of getting it right. And like I said, yeah, definitely have great abstractions for your code, but your tests should aim to be just as explicit as possible even if they repeat themselves.

[00:01:37] Cool, so, let's see. I'll test both. Let's say we've got this new item input, Which is basically what we had up here. So I'll just grab that real quick. And we've got that in place, and then we're also gonna wanna have the Add New Item button. Add New Item button with an N.

[00:02:06] And they will do that it's kind of screen.getByRole, and this one will be a button, With the name. And we're gonna learn something together. Well, I already learned it as I was getting ready for this, which is, It does ignore the emoji.
>> No way.
>> Yeah, the Add New Item will work in this case.

[00:02:35] We'll verify that before we're all really proud of that one. Yeah, it gets that. It will ignore the emoji. I think that's how the browser does the names and the roles rather than anything else. You'd be like, Steve, why didn't you know that? Because no one allows me to put emojis and buttons at work.

[00:02:52] [LAUGH] It's only on my sample apps that I can shove emojis wherever I want to on buttons on anywhere, cuz one, I'm not a designer who can make my own icons. And two, I like emoji, but it's not a thing that I realized until I got to make my own little silly apps because Candace would be very mad at me if I started shoving emoji all over the UI without checking with her.

[00:03:15] Cool, so we've got that in place. But yeah, we all learned something together. And I can either expect that the input is empty or I could purposely set it to empty. Like I said before, I don't really have strong feelings on this. So [LAUGH] with the lack of strong feelings, I am gonna do what's in the solution file just for the sake of our viewers here so that they don't offer too much here.

[00:03:48] To have value of an empty string and then I can expect in that case that the Add New Item Button, To be disabled, right? And like we said before, these are all the helpers that were brought in by the testing library/Jest DOM Matchers that we can kind of pull in, Mark.

[00:04:17]
>> I came across a team where one person writes a test and another person makes the test pass.
>> Yeah, that's like-
>> What's your opinion of that? So the, I forget what it's called, but what you're supposed to do in that situation is one person writes the test and then the other person is supposed to do the most egregious or naive, or silliest implementation that makes the test pass so that the person writing the test has to do an even better test.

[00:04:51] Right, and so I liked that idea. It's one of those things which is, I think it's fun, I wonder if their teams would do that every day. Do you know what I mean? It's a fun game, I'm into it and I think there's value in doing it. But I don't know, maybe in companies where everyone programs all the time.

[00:05:12] As an introvert that's, I don't know, but I think on a very practical level, I think it's genius, right? I think my social battery, I have about 90 minutes of that in me a day at most. But yeah, I think it's super cool. And it will get you to that as you kinda make a game out of it, it will get you to those better tests.

[00:05:32] But you can also, I feel like the Galaxy Brain version of that is to be able to do that with yourself. That said, most of us are just trying to get our jobs done here, [LAUGH] and probably don't have the discipline to write a test and then write the most ridiculous implementation of that despite ourselves but it's a thing.

[00:05:55] So we've got both of these in place. Let's go make sure that passes as well. And so we're starting to get to the point where it's, I have to be defined. So we want to be disabled. So, yeah, who tests the tests?
>> getAllByLabelText versus getByLabelText. What was the difference again?

[00:06:16]
>> getAll will get you an array.
>> So that would fail unless you wrapped new item name in an array, would that make it pass if you had to getAllByLabelText on 20 there?
>> 20, get by label text, right?
>> Yeah, I actually had getAllByLabelText.
>> I mean, you'll still have them.

[00:06:37]
>> And it failed.
>> Yeah, cuz it won't have a value, it'll be an array.
>> All right, [CROSSTALK]
>> You might have a two length or something like that. To getAll is like if you had some way to identify them depending on how you got them. It's super interesting.

[00:06:52] Let's say if we added three things to the list, right, you would maybe wanna get all and check the length, right? There's a time and a place for it. This just isn't it. And that's a good call-out cuz, at one point, I just haven't done this enough in my life, I will probably make that mistake today.

[00:07:09] I'll probably be talking and I'll hit that tab, it autocompletes something and you'll I'll pretend like I did it to you on purpose. I won't have but, yeah, all right. So then enables the Add New button when there's text in the input field. So like we said before you can create some functions to kind of render it and go get all these things and give me a object that I can destructure and grab what I need out of.

[00:07:34] I will kind of leave that as an exercise reader. We did a little bit yesterday. I don't think anyone used to watch me do it again, but for now, a little bit of copy and paste also works in this case as well. So here, we'll get both of them.

[00:07:48] I don't need to expect that they exist anymore. But what I probably want to do is at least go in there and we have that, remember user event? So I can simulate the idea of typing. Could I fire a change event at that input field? I absolutely could.

[00:08:10] But again, to that even that point we made a little bit earlier, there is a certain amount of value in doing it from the user perspective and also considering it is the difference of just using a different method that I already have. I get a lot of value of not really any work.

[00:08:29] So we will go ahead and try that one out. And so what I will probably do in this case is I will, and, again, remember the big difference between fire event and the user event library. Is that the user event library because it's doing a series of different actions, instead of one event that's getting fired does, in fact, return a promise.

[00:08:50] So you will find that nothing works the way you expect if you do not await the user typing. So we'll go to the newItem input and we will type in MacBook Pro. Cool, and then, at that point, we should be able to expect the NewItem button or a NewItem, yeah, our addItem button, To be enabled.

[00:09:24] And then we'll go ahead and we'll run that test. And I got it. There we go, we got a little check mark. And it's kinda like on a dopamine level, very rewarding to kinda work down this list to get the checkboxes going.