تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Test File Conventions0:31

see we have these tools installed already. And we even have an example test here called app.test.js, which we'll take a look at in a second. Now to define your tests, as long as you provide a .test.js file or a .spec.js file, then Jest will find it and run it whenever you run your tests. So this is a common convention to name your test after your component, which is fine. Or sometimes you'll even see a tests folder. So I'm going to take that approach, I'm going to make a tests folder here. You'll often see it named with two underscores to avoid name collisions, but it doesn't matter. So let's put that test in there.

Running and Fixing Tests0:59

You'll often see it named with two underscores to avoid name collisions, but it doesn't matter. So let's put that test in there. And this should still work fine. Now to run our tests, if you take a look at the package.json file, you'll see we have this test script that we can make use of. So let's go ahead and do that. So we can say npm test. And you can see that it's failing here. And I think that's because we have to change the import. So I can't find the app in here, because we moved it.

And I think that's because we have to change the import. So I can't find the app in here, because we moved it. So we have to go up one, and then this should work. So if I save this file, the test should run automatically again. So let's save this. Tests are running again, and now it passes. So we'll take a look at this file in a second. But let's start off with basic tests with just Jest. So I'll make a new file here, basic.test.js. And within here, you can start defining your test methods.

Writing Basic Jest Tests1:49

So I'll make a new file here, basic.test.js. And within here, you can start defining your test methods. So let's do something really basic. Let's say it does basic math. So that's the name of our test method. We provide a callback where we can make assertions against our code. So we can use the expect method that Jest provides. So expect, let's say 3 + 2, then we can use toBe, which tests for equality, and it should be 5. So that's our first basic Jest test.

Now if you have a test that's not passing, let's change this to another number. You should see the expected result and what we got. So right here, expected 4, but received 6. So let's put that back. You can also use the test method interchangeably with the it method. The test works as well. Just use whatever reads better with your test name. So let me just save this to show you that it works. But for the name I have here, it reads better, so I'll stick with that. Now obviously you want to be testing your own code, so I have this other file here called file.php

Testing Imported Functions3:11

But for the name I have here, it reads better, so I'll stick with that. Now obviously you want to be testing your own code, so I have this other file here called math.js, which just exports a few functions that add, multiply, and subtract two numbers. So we can import this into our file here. Let's import those methods, so add, subtract, and multiply from it's up one and then math.js. And let's go ahead and make another test method here. Let's say it does basicMath from external file. And let's just replace this with our own methods here. So add(3, 2), now it's parameters, to be 5. Let's say multiply(3, 2) to be 6.

So add 3 plus 2, now it's parameters, to be 5. Let's say multiply 3 times 2 to be 6. And let's add 1 for subtract as well. So 3 minus 2 should be 1. And that should be subtract. Let's go ahead and save that. And our tests are passing. If you want, you can even group tests together using the describe method. So let's say describe, give it a name, so math.tests, and then provide a callback. And within here, we can group similar tests together.

So let's say describe, give it a name, so math.tests, and then provide a callback. And within here, we can group similar tests together. Save that, and that should still work, it does. So far we've just been using the toBe method here, but Jest comes with a bunch of other methods you can make use of as well. So if we take a look at the Jest documentation for expect, you'll see a bunch that you can make use of. Let's try one out right now, it's called toContain. And this checks if an item is in an array, or also if a string is within another string. So let's make a test here, let's put it within a describe block as well.

Testing React Components5:04

And this checks if an item is in an array, or also if a string is within another string. So let's make a test here, let's put it within a describe block as well. Let's say stringTests, let's only have one here. Let's say it contains a string, and we can say expect, let's say this is a string, toContain is a string, and that should pass. Save that, and everything is passing. Now what about testing our React components? So let's go back to our AppTest.js. You can see we're now making use of ReactTestingLibrary here, and we're importing the App component here.

You can see we're now making use of React Testing Library here, and we're importing the App component here. You can see we're using the render method to render the markup of this component here. We're selecting a link element here, and then we're testing if that link element is within the document. So again, with this render method here, what we're doing is rendering a component with any props or state already evaluated, and then asserting against its HTML. So in this case, it's going to be our App component here. It's going to render this HTML within our JSX with any state or props already evaluated, and then we can make assertions against that.

It's going to render this HTML within our JSX with any state or props already evaluated, and then we can make assertions against that. So to make this more clear, let's go into here, let's use screen.debug, and this will output the markup of this App component. So let's save this. Let's go into our test here, and you can see the markup right here. You can even see that it rendered our Counter component here. And then after that, it is grabbing a link element. So in this case, it's looking for text that says Learn React. It's making use of a regular expression here, which is case insensitive.

So let's go ahead and test that. So let me just duplicate this one. Let's say counter.test.js. And now we are importing the counter here. Okay. Let's make sure to render that here. And if you take a look at the counter code, I'm actually accepting a prop here. So you can see it here. I'm destructuring the title and then just outputting it here within H2. So if you look at the app.jsx, we're passing in a title here for our counter.

I'm destructuring the title and then just outputting it here within H2. So if you look at the app.jsx, we're passing in a title here for our counter. So how do we do that within React Testing Library? It's exactly the same as how you would do it in an actual component. So you would pass it like this within the render method. So let's go back to our test. Let's pass it in here. And let's just comment this out for now. Let's do screen.debug to see the markup of this component. And we should see that title within there.

Let's do screen.debug to see the markup of this component. And we should see that title within there. Let's save that. There is the title. So we can go ahead and assert against that to start with. Let's actually rename this test. It should be renders the Counter component. So let's go ahead and grab that element. Let's comment this out. Let's bring this back.

Let's comment this out. Let's bring this back. Let's name it title element. title element. And the text I'm searching for is myCounter. So let's replace this regular expression. Or you can just provide a string if you like. And we do expect it to be in the document. So this test should pass. And it does.

Choosing Better Queries9:14

see a section for priority. And based on those guiding principles, it says your test should resemble how users interact with your code. So when selecting elements, they recommend using these guidelines here. So far, we've been using getByText, which works fine for elements that are non interactive like divs and spans, which is what we've been asserting against so far. But we also have getByRole, getByLabelText, getByPlaceholderText, and so on. So this can get quite confusing, especially getByRole. So to help out with this, you can make use of the testing-playground extension, which allows you to select an element.

So to help out with this, you can make use of the testing playground extension, which allows you to select an element. And it's going to recommend a selector to use with testing library here. So one of these here. If you can find one. So for example, for our counter, if we wanted to select this, just go ahead and open dev tools. Let me just make this a bit smaller here. There should be a section here for testing playground. Go ahead and select the element you want to select.

Actually, that's for the title. Let's do one for the count as well. So by default, it should be zero. So let's duplicate this. Let's rename it count element. We'll use getByText here, and that should pass. And it does cool. So again, when you're querying elements, try to follow these guidelines here. But there can be some cases when this doesn't work out well for you. So you can just go back to querying the DOM the old-fashioned way.

Testing Button Interactions10:51

But there can be some cases when this doesn't work out well for you. So you can just go back to querying the DOM the old-fashioned way. So we'll take a look at that after we finish testing this component. So first, let's write another test for incrementing the counter. So let's duplicate this. Let's name it it increments the count or the counter. So we want to click the button that increments the count and then assert that the count did change. So how do we get the button here? Again, let's use this extension.

So how do we get the button here? Again, let's use this extension. Let's select the element. Let's select increment. And we are using the getByRole method with a role of button and a name of increment. So let's go ahead and use that. Let's get rid of this here. Space that in. Let's save that to a variable actually. So const incrementButton equals.

Let's save that to a variable actually. So const incrementButton equals. And if you want, you can assert that it's in the document like we did before. So let's do that. Let's get rid of this. It should be the incrementButton. Okay, let's save that. It does pass. But now we want to click that button. So there are a few ways we can fire events here.

But now we want to click that button. So there are a few ways we can fire events here. We can use fireEvent. And if I hit tab, that should import it from react-testing-library. There it is. And in this case, we want to click the increment button. Actually, this should be underneath. Okay. And now the count should be one. So we can go ahead and grab this.

And now the count should be one. So we can go ahead and grab this. I think I forgot to change this to count zero is what I meant. So let me change this to count zero. Let's grab this. Now it should be count one after we hit the button. So count one. And let's go ahead and save that and everything should pass. And it does cool. Now another way to fire events using the testing library is to make use of User::event.

fireEvent vs userEvent12:44

And it does cool. Now another way to fire events using testing library is to make use of User event. Now if you take a look at the difference between fireEvent, you'll see that fireEvent only dispatches the events you tell it to. So for the example we just did, it only fires the click event. But when you use User event, you can see that it dispatches events like they would happen if a real user interacted with the document. So for example, for click, not only would the click event fire, but we'll also have a hover. We'd have a mousePressDown that will focus the item and a mousePressUp.

a hover. We'd have a mouse press down that will focus the item and a mouse press up. Now if you do it this way, you're more likely to catch bugs that you wouldn't have caught if you just use fireEvent, because it better simulates the behavior of a user. So let's go ahead and make use of userEvent instead of fireEvent. So let's just duplicate this. Let's comment this out. And we can make use of userEvent instead. And we have to make sure to import that up here. And I believe it's import userEvent from 'testing-library/user-event'.

And we have to make sure to import that up here. And I believe it's import User event from testing library, User event. Okay, let's save that. And the test should still pass and it does. Let's go ahead and write one more test here for decrement pretty much the same thing as increment here. So we can duplicate this. Let's say it decrements the counter. And we just have to change the decrement button here, or the increment button to decrement. So say decrement button, the name should be decrement.

And we just have to change the decrement button here, or the increment button to decrement. So say decrementButton, the name should be decrement. And after we click on it, when it starts at zero, then it should be negative one. Okay, save that. Hopefully that passes. And it does. Cool. Let's write one more test here, which just makes use of DOM selectors. So like I said earlier, you want to make use of these queries that testing library recommends as much as you can.

Using DOM Selectors14:34

So like I said earlier, you want to make use of these queries that testing library recommends as much as you can. But sometimes that might not work out. So let's go ahead and duplicate this test here. But let's just make use of standard DOM selectors. So it renders the Counter component using selectors. So again, try to make use of these as much as you can. But if you can't, you can just make use of the selectors. So we render the component, but we can actually grab the container here. So let's say const container equals render.

So we render the component, but we can actually grab the container here. So let's say const container equals render. And if we console.log the container.outerHTML, that's pretty much the same as screen.debug. So let's console.log container.outerHTML. And it's just going to be the markup for the counter, just like screen.debug. So let's check that out. There it is. And if you take a look at my markup here, I did add some IDs for the title, id equals title and id equals count. So we can just select those as we usually would in JavaScript.

title and ID equals count. So we can just select those as we usually would in JavaScript. So for the title element, it will be container.querySelector. And in this case, it's title. And we can make an assertion here. So let's expect container.textContent to contain count zero. Actually, this is the title. So it should be my counter. Actually, this should be the title element that we just selected, title element. Okay, so let's try that out.

Actually, this should be the title element that we just selected, title element. Okay, so let's try that out. Hopefully this passes. Let's comment this out, save. And we are passing here. So let's go ahead and add one more for our count. So pretty much the same as this, say count element. The querySelector is now count. And we are checking the count here. So by default, it should be zero, save that.

Running tests with JestReact Testing LibraryTesting a Counter Component

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟