React Testing Library Crash Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody welcome back to the channel in this video what we're gonna do is learn all about react testing library now i'm super excited because this video on youtube is going to be a section of a pretty large course that i have on udemy that teaches you well all about react testing library so if you want to learn some of the more complex features and really become a react testing library expert go ahead and enroll in the udemy course i'll have a link with a discount in the description below so go ahead and do that so let's just quickly go over what we're going to be building and testing in this course so over here we're going to be building and testing this very very simple form now this may seem very simple but you're going to learn a lot of concepts when it comes to react testing library so over here very simply all we need to do is input our email our password and confirm our password and then submit however if we don't input anything of course we're gonna get this error now if you were to input some sort of invalid email so for example if i were to put this well we still get the error because the email has to be valid so what we're going to do is we're going to build this and also test for these different scenarios in this course and of course now if you put in a valid email so let's put in late harbor or harblate gmail.com but then i don't put in a valid password now we get the password errors so now let's just go ahead and put in some random password i'm honestly just going to copy the email and paste it in there now we get to the confirm password so if i input a incorrect password or a password that doesn't could uh that isn't exactly the same as the password we put in here we get this error and now if i let's just go ahead and refresh once more if everything is okay if everything is okay let's just put in that you can see that nothing happens and we're gonna test for this scenario now in the udemy course we're gonna actually take this to the next level we're gonna be building and testing this relatively complex application and here this is where we're going to take our react testing libraries to the next level so this is a adoption adoption website where we adopt cats so over here we have the name of the cat and over here we have the contact information for the people that we can contact to adopt this cat and what's really nice about this let me zoom once more is we can favorite the catch that we like and of course we're going to test for this and then we can also filter for well favorite or not favorite and of course this is also something we're going to learn how to test for in react testing library we can also filter by gender so we can have multiple filters we can say male and favored in this case we have nothing male and not favored well in this case we have these cats so over here you can see you can do these really complex filters and what's really nice about this is if you if i refresh look at the cards and how they render they don't render right away so this is actually coming to us from a server so we're going to learn how to mock http requests in our application which is something that happens all the time inside of react apps so again if you want to take your uh your skills to the next level go ahead and enroll in the course i'm also going to add a future section which i don't have right now about how to test react router so that is going to be the course i hope you guys enjoy it and i'll see you in the next one before we start diving deep into react testing library we first need to understand what is testing and why do we care about it so that is what we are going to uncover in this lecture starting with what is testing well simply put testing is a method to check whether the actual product matches the expected requirements so we might have a product and we want this product to do something that is our expected requirements so in order to see that it actually meets that expectation we need to test it let's actually look at an example to illustrate what i'm saying here let's say we have a product and this product is a video game and inside of this video game we have a character and this character has a health bar now whenever this character gets hit what we expect this video game to do is decrease the health bar so we have a product which is a video game and once the character gets hit we expect that the health bar decreases now we need to make sure that this actually occurs and of course we're going to make sure that this occurs with testing and we'll talk about the different ways we can test the different types of testing in future lectures but for now that is pretty much what testing is now testing isn't isolated to software applications so for example a software application like google of course they test their app they continuously test it you know anytime you want to search something they want to test that you get the expected results but there are other companies that are not software related like casper that sells mattresses they rigorously test their mattresses they test the texture they test the firmness they test that you know it's meets the user's expectation it meets what they expect of their product and this is just a mattress and there are other car companies like porsche that also rigorously test their cars to make sure that they work the way that they intend them to work so for example if you ever seen those safety tests where a car rams into a wall with a dummy inside it those are tests to test that hey the car is meeting some sort of safety expectations some sort of safety requirements so they smash hundred thousand dollar cars in order to test this out so again it's not just isolated to software companies now now that we know exactly what a testing is let's actually talk about why we want to test and after going through this i do expect you to have an idea of exactly why we want to test but the main reason we want to test our product is we want to increase our confidence in our product we want to make sure that our product delivers what we expect it to deliver and what that means that we have high reliability so no matter how many times we reproduce the same thing it results in the same action results in the same requirement we want to increase the reliability and we want to decrease the defects so any defects that occurs and in software development this could be a bug so that is exactly why we want to test and i hope that makes it clear in this lecture we learned about what testing is and we also learned why testing is important but we didn't really learn how we can test our products how we can test our applications so that's what we're going to be doing in this section in this section we're going to uncover the different types of testing methodologies now when it comes to testing there's only two main methodologies that you can utilize and that is either manual testing or automated testing so let's actually look at what manual testing is first and then we'll look at what automated testing is so in order to understand this let's actually look at a real life example so let's say that we have this form right over here and you're asked to validate that the email that they input is actually a correct email so right here of course they can type in whatever email they want and then when they click submit if this is not a valid email we want to show an error some sort of error message saying that this is not a valid email please try again so what you would do what any developer would do is they would go to the code and then inside of the code they would do some things you know they would try to add that logic i already did this so they'll try to add this logic and then what they would want to do is test it out so at the very end you want to test out if their feature their new feature that they want to add actually works now how would they do that well they would open up this application in their local machine and they would type in an invalid email inside of this email right over here so they would say something like lathe and then maybe they would forget the at sign and they would just say lathe hotmail.com and then what they would do is click this button right over here and look at that we see the error message the email the email you input is invalid so what did we just do here well we just tested our application to make sure that it works the way that we expected but we did it manually we manually opened up an instance of our application we manually typed in an invalid email we manually clicked this button and lastly we manually validated that we got our error and this is manual testing and developers do manual testing all the time it's almost done simultaneously with actual development so that right there is manual testing when you actually physically do the thing so now let's talk about automated testing well automated testing is where you write a test in code describing the behavior that you want and the outcome that you expect so the behavior that i want is i want to go ahead and type in an invalid email and then the outcome that i expect is that i get this error so what i can what i can do is i can write a test for this an automated test in code and an example of this example of what exactly we just did with manual testing is this test right over here so i have this test that should show email error if email is invalid and right here you can see that we're typing in an invalid email as you can see this is an invalid email there's no add sign and what we're doing is we're expecting this error message to be in the document so this right here is an automated test that did exactly what we did when manually testing it so that is a difference between automated tests as well as manual tests now why would we ever want to do manual tests writing all this seems a lot more work than just simply doing this and then clicking the button and then validating that it's there well the reason why you want to do automated tests is as your application gets bigger and bigger and bigger it becomes very very impractical to manually test every single feature whereas with automated tests you can see here we have a test for every single feature and all we simply have to do is run our test suite and check if everything passes if everything passes we have increased confidence in our application we know our application is reliable and there's going to be definitely less and less bugs so just to point out an example of where manual tests can really fail us let's actually look at a scenario where you know i do some changes maybe i want to change this from email address to email i don't just email itself without email addresses so i go over here and uh i go and i say uh where's the email so i change this to email right over here so i change that to email everything seems all fine and dandy and then once i scroll up i see over here oh my goodness he has a bunch of if else statements i actually prefer to have if statements instead of if else statements i don't know why would someone would do this but they they did it they went ahead and did it and saved their app well now if they were to refresh they can check over here okay everything is working fine let me just quickly input an invalid email you know everything seems okay or let's actually put in a valid email maybe a password here but an invalid confirm password and i can see here okay the tests work exactly the way that we intend okay that is completely fine i'm going to go ahead and ship this inside of production well actually what you did right here is actually going to cause some problems so if we opened up our terminal you can see that our tests actually caught a potential issue that we'd actually didn't catch when manually testing our application so what we can actually do is now look at the tests themselves and we can go here we can scroll up and look at some of the failing tests so it seems that this test right here is failing should show email error if email is invalid why is that the case so now what i can actually do is input an invalid email submit this and i can see i get a different error you know the password you entered should not contain five characters or more so you can see that if i did manual testing i wouldn't have caught this error but with automated testing i did and then i can of course debug exactly why i did that and then i can realize oh okay so it's the else if are the things that guard for this so automated testing allow us to catch things that we would most definitely miss with manual testing if our application gets big enough now you can see here that we also have another automated failed test i'm not really sure what that is let's go over here and say address address so let's save that let's save that let's just get rid of this test over here and let's run it again let's see why that is and we want to see all of the tests all right everything is all fine now our application is fine and we are confident in it so hope that makes it clear exactly why we also want to automate our test now react testing library is a library that allows us to write these tests for our react application and therefore increasing the confidence of our react app in this section of the course what we're going to do is learn about t d d now this stands for test driven development and what it means is a process where we write our tests before we write the feature so let's actually look at an example for this so let's say in our application we have a button and what we want to do is when a user clicks on this button we want to change the color of this button to purple very very simple feature and of course we have to go into our code and code it out now if we were following test driven development we wouldn't go right ahead and code out the feature itself what we would do instead is write a test testing that feature so right over here this square box symbolizes the test that we are initially going to write we're not going to write the feature we're going to write the test first now because the feature doesn't exist well that test is going to fail and as you can see here we have a red failing test and then the next process is to go ahead and code out that feature and once we code out that feature and it's behaving the way that we want it to well that test should pass that same test that we wrote over here should be green meaning it has passed and that is test driven development we write the test first and then we write the feature and then the test should pass now this is also known as red green testing because initially your tests are going to be red meaning that they are failing and then you write your feature then they turn green meaning that they are passing now why in the world would we ever care about test driven development well there's actually a few reasons testing becomes a part of development a lot of the time testing feels like a chore especially if you leave it at the very end you write your feature then you're like oh my goodness now i have to go ahead and write a bunch of tests for this when you're doing test driven development you're very cognizant of the test and testing actually becomes a part of the development process which is really really important another one is that you write cleaner code it's actually a known fact that when you apply test driven development developers tend to write the smallest unit to make that test pass whereas if they don't have a test they tend to have more code more complexity more complexity and it just becomes a little bit unnecessary and lastly it reduces bugs when you follow test driven development you actually end up writing more tests and of course the more tests you have the less likely that you're going to have defects and bugs in your application and that right there is why a lot of people encourage test driven development welcome to the section of the course where we're gonna get our hands dirty and start utilizing react testing library now in order to utilize react testing library we need to have an application to test and what we're going to do is follow the test driven development methodology so what we're going to do is write our test and then write our feature and then make sure that the tests pass so at the end of the day what we're going to do in this section is test our application and also write our application so we're not just going to have a fully pledged application and we're just going to test it no we're going to write it and test it simultaneously now what's the application that we're going to be building well we're going to be building a very simple form application and you guys seen this before so over here we have this very simple sign up form where a user puts their email puts their password and confirms their password and this right here is the design and this is how it should look now the other images are going to show how it should behave so if you were to put an invalid email what we should have is this error over here that says the email you input is invalid and we get this error once we click submit on an invalid email now if we have a valid email but an invalid password we get this error and then if we just do not confirm our password correctly then we get this error right over here so this is what we are going to build and test with react testing library so you know what let's just get right into it in this video what we're going to do is create a react application and we're also going to inspect the boilerplate code so let's just get right into it so the first thing that we need to do to create a react application is we need to go and open up our terminal or our command prompt if we're on windows and move into whatever directory we want our application to live in and then once we're there what we would execute is npx create react app and then we're going to give our react application a name let's call it sign up form so that's all we have to do now this command is going to take some time to execute so i actually already did this beforehand but if you haven't which i'm assuming you haven't pause the video and wait till it's done executing and then you can resume watching now once you execute this command what you should have is a sign up form folder react app that is living inside of whatever directory you created it in in this case it's in my desktop so if you did something like cd sign up app you should be able to see it awesome now once that's done open up that folder inside of your favorite text editor i'm using vs code which is by far the most popular text editor in the planet right now so i went ahead and i opened it up and as you can see we have a pretty boilerplate react application i do expect you to be relatively familiar with what's going on here right here we have this app component and it's just rendering you know this react learn react anchor tag it has a paragraph over here and has an image right over here that shows the logo so very very simple component and it's being rendered inside of the index.js as you can see here now one thing that i want to inspect is this file right over here app.test.js so it appears as though that this is a test file that is testing the app.js component and that's exactly what is happening typically when we're utilizing react testing library this is the naming convention so the component that we're testing dot test dot js so let's actually go ahead and click into it and let's just look at what's happening here now we're not going to actually look into the test part a little bit later we'll dissect that in future videos but right now what i want to focus in on is this right over here so we're importing something called render and screen from at testing library dash react so it seems by default react is utilizing testing library so we don't have to do any installation any configuration ourselves by default it is actually already being used so if we went to our package.json and we looked at all of the dependencies you can see that well that's actually what's happening you can see that yes we have testing library we have um we have testing library dash react testing library dash user event we have testing library dash just dom so it's already installed and what's nice about it is we don't have to do any initial configuration now if we look at the scripts you can see of course we have the start script the build script but we also have a test script so we have a script that we can run to run all of our tests so let's actually go ahead and do that i'm going to open up my terminal and i'm going to do npm run test and just to see what happens and there we go we get this over here i'm going to say a to run old test you might not get this and you can see that it is going to detect this test file app.test.js and right now we have one passing test so what's happening here is when we run app. mpm run test is going to look for all of the files that have this structure the app.test.js and then it's going to go ahead and run them now inside of the app.test.js we have one test and it is passing and again we'll look at the test itself a little bit later but for now you can see that we do just have one test and well it's passing renders learn react link it's passing and as you can see this is that test awesome so one other thing that i want to note is that react testing library uses another library called jest under the hood so that just is a very popular testing library and react testing library is utilizing that to build this react testing framework so right over here if we were to go back to our package.json you can see that we also have this dependency right here just dong all right so i hope that makes sense and now that we have a good understanding of the file structure for react application let's actually move on and start utilizing react testing library in order to start using react testing library properly we first need to understand one of the main react testing library philosophies and to do this let's take a quick look at what we're trying to build and test so over here we're trying to build a form and obviously this form has quite a bit of functionality to it now of course when we want to build this form we have to go ahead and code it out so let's say that over here we have this person and he went ahead and coded out some logic and it ended up in this form it ended up resulting in this form with its functionality his error handling functionality now this is awesome and it's behaving exactly the way that we want however one thing that i want to note is that we can also have multiple people code out the exact same thing but with different logic so you can see here that it's different color representing different logic for example this person over here they could have used use state to handle all of the inputs whereas this person maybe they just got the e dot target.value and directly utilize that to handle the inputs as well as the error handling so the implementation might be different however across all of these people across all of these code bases the ultimate outcome and the ultimate design is exactly the same the software app behaves the exact same way that we intended regardless of the different implementation details and react testing library says that regardless of how these things have been implemented the test should always pass and the reason for this is we will never focus on the implementation details when testing our react application but rather we're going to test how the software should actually work so for example we're going to test that we should type into this we should be able to type into this input we should be able if we input something incorrectly and hit submit we should see this error how we get there react testing library doesn't care it just tests the outcome of the software product so that is a rule that we are going to follow we're always going to test how the software is meant to be used not how it's implemented and that is a very very important philosophy that you need to understand when utilizing react testing library and you know what any testing framework for that matter let's go ahead and write our very first test now remember what we want to do we want to test the behavior of the app that we built not the implementation details now if i get this form as a user what do i expect to happen well for one let's start with the very simplest thing i expect a user to be able to type into these inputs and once they type into the inputs the value is present in that input so let's actually write a test that tests whether a user can actually type into the email password and confirm password inputs so let's go ahead and do that and of course we're going to take a test driven development approach to do this so the first thing that we're going to do is write a test that tests that we can type into the input and then we are going to code out that feature until the test passes so let's go ahead and do it right now now in order to do this let's actually go into our app.test.js file and let's actually inspect this test over here we're going to look at the structure of this test so a test is written by using the test keyword and this is something that we go ahead and invoke so we have test and we go ahead and we invoke it and what this takes in is two parameters the first parameter is going to be a string and this is going to describe what this test is testing for example over here this string says hey this is going to render a react link this is testing that this component the app component renders a react link so over here we can write anything that we want to describe our test so i'm just going to say description over here for now and then as the second parameter we're gonna have a callback function so a callback function and inside of this callback function we're going to have all of our test logic now what is going to go inside of this callback function well typically these three steps will always occur in any callback function that we have so the first step as you can see here is we're calling a function called render and we are passing in the app component so this render thing is we're getting that from right over here from the ad testing library slash react library so we're getting it auto imported from here and then what we're doing is again we're passing the app component which we're getting from the app.js file so the app.js file is over here which is our app component all right so what is this doing well this is going to render that component into the virtual dom and it's only going to render that component in any children that it has anything else any parents are not going to be rendered so it's going to render that component in the virtual dom and once it's in the virtual dom we can start testing it so this is going to be basically rendering the component that we want to test so rendering the components we want to test we want to test awesome so that's the very first step and then the second step over here you can see what we're doing is we're finding a specific element inside of this component so right here we're doing screen which we're getting from ad testing library and we're saying dot get by text so screen has a bunch of methods that we can utilize to find elements and we'll talk about all of them in great detail a little bit later but over here we have screen dot get by text and then we have a regular expression so right here this is a regular expression and so it's going to find the element that has the text that matches this regular expression so if we were to go to the app.js file and we want to find the element that has the text learn react well over here it's right over here so we have this anchor tag right over here that has learn react so what this is going to do is get us that anchor tag so it's going to get us that anchor tag so over here step two is finding the elements finding the elements that we want to find so finding the elements and then the last step in this case is an assertion so this right here is the final thing that is going to assert what we want in our test so here what we're doing is we're expecting that this anchor tag is going to be inside of the document and so this is what what is either going to fail or pass so if this anchor tag is not in the document well this assertion is going to fail and thus this test will fail if it is in the document while this assertion is going to pass and thus it will pass the test will pass so over here we have an assertion and what's nice is we can have multiple assertions within one test block so this right here is known as a test block this over here is another test block and we can have multiple assertions within a test block and if just one of them fails the whole test fails so just to quickly take a look at this let's go ahead and open up our terminal and let's run those let's run these tests again so over here you can see now we have two passing tests you might be wondering why do we have two passings tests well we have now one test here and then we have another test here and even though we're doing absolutely nothing in here it is still passing well why is that the only way we can get a test to fail is if an error is thrown and so you know if an assertion is false or fails then an error is thrown but right now because we're not doing anything everything seems fine and so the test passes so let's actually just get rid of this test real quick i'm gonna get rid of it and you can see now we have one test pass and now what i want to do is i want to comment this out right over here so let's comment out let me zoom out a little bit so i'm going to comment out this anchor tag so let's say we commented out this anchor tag and now notice that this test should fail there we go and why is that well if we were to scroll up all the way up here it says that hey we're unable to find an element with the text learn react and then over here it says it's maybe whatever and what is what's really nice is that it also gives us an html tree of our component so we can actually kind of dig around and we can look and we can see well yeah it's right there is no learn react anchor tag so we can go just go ahead and uncomment this out and if you were to uncomment it out it should pass and there we go awesome so now that we know the structure of a test let's go ahead and um well let's go ahead and write our first test all right my good friends in this video what we're gonna do is go ahead and finally code out our very first test so what i went ahead and did is i went to the app.test.js file and i removed everything aside from these import statements right over here and now let's go to our app.js and then everything inside of the div element let's get rid of it let's also get rid of this class names so we just start with a very clean slate so what is it that we want to test well i know i said that we're going to test whether we can type into an input element but i think our very first test should be a little bit simpler so initially when a user sees this form what do they expect to be inside of these inputs well nothing so let's write a test that tests whether initially all of the input elements are empty so that is what we are going to write so in order to do this let's go to our test file and then what we're going to do is we're going to create a test block so we're going to say test and then we're going to give our test a name a description so that's gonna say inputs should be initially empty so this is what we're testing for and then we're gonna have our callback and then our callback is going to have our logic so what's the first thing that we need to do well we need to render the component that we are going to be testing inside of our virtual dom so we're going to call render and then in here we're going to pass in the component we have to pass in the component in the jsx form so we're going to say app like this all right awesome so that's the very very first step now what's the next step well the next step is to find these input elements to go ahead and query for them now how do we do that this is probably the tougher part so in order to learn how to do this let's actually look at the documentation and let's see what it says so i'll link this uh page in the description if you want to see it i'll have it attached to this video um but essentially what this is going to state is how we can query for specific elements inside of our virtual dom so if we scroll down over here you can see that there's actually multiple ways that we can query for single elements and multiple ways that we can query for multiple elements so we can use get by something or we could use query by something or we could use find by something and we'll talk about what these somethings are or we can if you want a query for multiple elements we can do get all by or query all by and then or find all by but right now what we want to do is focus in on just the single elements because that's exactly what we want to query for we want to query for if we go over here we want to query four and let's present this we want to query for this element and then we want to separately query for this one and we want to separately query for this one because they're all separate and we want to test for different things for all of them so let's go ahead and let's figure out how we can do this well what do we want to use do we want to use get buy query buy or find buy so let's go over here and let's look at this table so this table is going to describe the differences between get buy query buy and find buy so get by if it doesn't find any elements what it does is it throws an error and it causes the test to fail so that is what get by does so if it does find something what ends up happening is it returns the element and if it finds more than one match it throws an error and it causes the test to fail and get by cannot be used asynchronously so we cannot use async at a weight so if we're rendering a component asynchronously and we want to test for it well we cannot utilize get by so let's just quick take a quick a reminder of what it does so if it's zero elements does not find the match it throws an error if it finds one element it's going to return it if it finds multiple elements that uh uh meet this description it's gonna throw an error and we cannot utilize async away now over here let's move on to query buy so query buy is pretty much the same as get buy except there are differences when there's zero matches when there are zero matches it doesn't throw an error it just returns no so if we are trying to test for the lack of a ui element in our component then we want to use query by rather than get by and then the rest is exactly the same lastly let's talk about find buy find buy behaves the exact same way as get buy except we're able to utilize it with elements that render asynchronously and so it's going to behave over here exactly the same but when we need to utilize async await for an element we can utilize find buy except for get by and multiple elements work exactly the same way so over here get all by if we don't have any elements what it's going to do is throw an error if we have one match or multiple matches it's going to return an array then over here we cannot utilize async await query by if we don't have any elements it's just going to return an empty array and then over here it's going to behave the same way and we cannot utilize async away and then find all by is going to behave exactly the same uh with get all by but we can utilize async away awesome so i hinted that we have here get by and then we have three dots get by something so what is this something well let's actually scroll down over here and we can actually look at all of the different ways that we can get by or query by or find by so over here you can see we can either get by roll and anything that we can get by we can also query buy and find buy so we can also do find by roll query by roll but for example for this example they're just using get by so we can get by role we can get by label text we can get by placeholder text we can get by text we can get by display value we can get by alt text by uh by title and we can also get by test id but which one do we want to utilize well if we go over here you can see that we have some priorities and it says here that based on the guiding principles your test should resemble how a user interacts with your code as much as possible and so what you want to do is you want to use roles that reflect the experience of a visual mouse user as well as those that use assistive technologies like screen readers so if i were to go back over here to my my forum well i'm probably going to look at this form and i'm going to see this and i'm going to look at the role of this element and the role of this element right over here is a text box role and that is how i am going to perceive it so it's highly uh it's much better that our tests do the exact same and we get the element by the role rather than something like the test id which is not seen by the user and screen readers cannot see at all at all so again what we want to do is we want to make our test as similar as a user experience as possible so if we can we are going to utilize get by role if we cannot utilize get by role we're gonna utilize get by label text which is the second one and this is also a really good method and then over here we could also use get by placeholder text which is also a very good one get by text itself is pretty good and then if we cannot utilize any one of these we're going to move on to the semantic queries such as get by alt text and get by title and things like this like the alt text even those some users can't see it at least you know assistive technologies like screen readers can see it and then the last thing the last option if we cannot utilize anything else we're gonna use test id and test id is we assign a test id to a particular element and then we just get that element by test id but again a user can't see that nor can assistive reading technologies so this is our last resort now that we got that out of the way let's go ahead and query for this email input element so in order to do this what we're going to do is first create a variable and we're going to call this well email input element very very simple and then we're going to say that that is equal to screen and then we're going to do screen dot and then we can see all of the different query methods that we can utilize now we're going to utilize get by so we're going to say get by and as you can see now we see all of the get by query methods that we can utilize well which one do we want to use well semantically the best thing that we can use is get by role because this really matches the user's behavior and also is best for screen readers so we're going to say get by roll now the rule is going to represent the role of the element that we're trying to query by so let's go ahead and invoke this and then we need to specify the role the best way to do this is to just put quotes in here and then you could just go ahead and scroll through all of the different roles now off the top of your head you might not know exactly what role your element is what role your element has so the best thing to do is just to do a quick google search or if you don't do know what it is like i do i know that we're trying to query for the input element that has a role of text box so we're gonna say the textbox role so i'm going to go ahead and query for this now one thing that i want to note is i want to quickly run my test before i save this i want to run my test and initially it's going to pass because there's nothing that's throwing an error now if i were to save this and we can see here that it has failed and the reason why it failed is that it can't find any element that has the role text box and that's because if we go to our app.js there's absolutely nothing in here at the moment and this makes sense because remember remember if we go over here get by if it doesn't find any element it's going to throw an error and then and if an error is thrown inside of a test block that causes the test to fail okay awesome so that is finding the element now what we want to do is the assertion so we expect this input element initially to have a value that is completely empty so what we can do here is have an expect statement and then in here we can say that we expect that the email input element so that the email input element dot value and then here we can say dot 2 b and then just an empty set of strings so this is the assertion that we want and if you're wondering you know how i got to b how i got dot value this is all going to come with the to you once you write more and more tests so we're going to expect that the email input element.value is going to have a empty string so now we're going to go ahead and save this and now well we should still expect this test to fail because remember we're following a test driven development approach so now what we need to do is to write out the code to make this test pass and let's do that in the next video let's now go ahead and write out the code to make our tests pass so as you can see here very very sad test we are failing it is red let's make it green so in order to do this just for styling purposes we're going to utilize bootstrap so let's go over to getbootstrap.com and i'll have this attached to the video and what you can do is you can just go to get started and then over here just copy this link right here and once you're in there what we're going to do is we're gonna go to the public we're gonna go to index.html and we're just gonna throw that link in there that's all we have to do to set up bootstrap for styling purposes this isn't really anything test related okay so now that we got that out of the way let's start creating the elements that we need to make this test pass so the first thing that i'm going to do is i'm going to keep this div except i'm going to give it a class name of container and we're also going to give it a margin top so margin y of five so this gives it a margin top and bottom margin y all right so that's the very first thing and then what we're going to do is we're going to create a form so that's what we're going to do and then inside of this form we are going to have a div so over here we're going to have a div and we're going to give this div a class of m b three so we're gonna have some margin in the bottom and then inside of this div we are going to have a label so a label and this is gonna be for the email we're also gonna give this a class name that is equal to form label again just some bootstrap classes and over here we're going to call this label email address so email address awesome so well right now we still didn't do anything and the test should fail because we don't have that input element so as you can see it still fails so now over here right under the label let's go ahead and create that input element okay let's just zoom in once more i'm just worried that sometimes it gets a little bit small so let's add an input element and we're going to give this a type of email let's also give it an id of email and we're going to give it a name of email and lastly we're going to give it a class name and we're going to say that that class name is equal to form control all right and that's pretty much it this is the bare minimum amount of code that we need to get our test to pass because right now we have our input element that has the role of text box and that initially should be empty so let's go ahead and let's open up our terminal again and let's go over to our test and as you can see now our tests pass we made great progress however this test is not complete remember what this test is supposed to do it's supposed to test that all input elements should initially be empty right now we're only testing that the email input element is empty so we have to do the same thing for the password input element as well as the confirm password input element and the process of doing this is going to be exactly the same the only difficult part is querying for those elements now you might be thinking well okay well what i could do is something like a const password input element and i can say screen by and i can say get by role and i can then say text box well that's not going to work and it's not going to work for multiple reasons the first reason is that we're already querying for a text box and that should be the input email element now remember what happens when we have multiple matches for a specific query when we utilize get by it's going to throw an error so what we need to do is we need to find a more unique way to find this password element now even if even if we went ahead and commented this line out over here and then we went to our app.js and instead of changing this input element to be an email and we made it to be a password it is still going to fail let's actually take a look at it so we need to go here we need to change the password input element and you might be thinking well this should definitely work we do have an input type right here and we should be able to get that and then assert that it is initially nothing however when we scroll down here it is failing and why is it failing if you scroll all the way up you can see here that there is no element that has the role of text box which well that makes no sense we we just had it before all we did is we changed the type well that right there actually changed the role of the input and this is kind of a nuance and something that is tricky to kind of get over the main reason why i figured this out is i went ahead and i researched it and i found here in this github issue that in order to retrieve in order to retrieve a password a password has no implicit role so we're gonna have to use something else called get by label text so you can see here that every div element that contains an input has a label and then it also has an input and that label right over here is attached to this input with the for attribute and then the id attribute and that's exactly what we had right over here let's move this back to email we had this label that says html4 and then over here we have this id on the input that is email and so now we're linking this label to this input so what we can do is we can create another div element that has a path that has a password input type and a label and then we can get that input type by its label so let's go ahead and do that so in order to do that let's go over here and let's just go back to our previous versions and what we're going to do here is we're going to get by label text so we're going to get by label text so let's go ahead and do that and we're going to utilize a regular expression for this so we can either say we want the text to be password like this and therefore it's gonna have to match this exactly including the capitalization or we can just use a regular expression that says well the label should have the word password in it doesn't matter where it is doesn't matter if you have multiple words in there as long as we have password and it doesn't really matter if it's capitalized or not so we're going to use a regular expression so we're going to get the input element that is going to have a label of password and then we're also going to do the same assertion so remember we can have multiple assertions inside of the same text so we're going to say here expect and we're going to expect that the password input element we're going to expect its value so we're going to get the value attribute from the input element we're going to expect it dot 2b and this is outside of the expect we're gonna expect it to be empty initially let's go ahead and save that and let's go here open up our terminal oops oops oops oops and initially this test should fail now even though this expect statement passes this one fails causing the whole test block to fail all right let's go ahead and go to our app.js file and i am going to uh let's let's zoom out hopefully it's not too small for you guys so in here what we're gonna do is we're gonna just simply very uh copy this right here we're gonna paste that in there we're gonna change this to password we're gonna change the um the html4 to password we're gonna change this right here to password the type to password we're gonna change the id to password and we're gonna change the name to password so let's go ahead and save that and there we go now it is green so the last thing that we have to do is go to our app.test.js and test for the confirm password now what we can do is the exact same thing i'm going to go ahead and type it out so we're going to say const password input element and we're gonna say screen dot get by label text and this time we're gonna have a regular expression that is gonna say confirm password confirm password all right so we're gonna have that in there and we're gonna also expect that to be null so we're gonna say uh password or over here this should probably be confirm password confirm password input element so let's copy that let's paste that in there we're going to expect its value dot to be initially empty of course once we run this it's going to fail so let's go over here let's just check it out yes it failed and now let's go to our app.js and let's make it pass so i'm going to do is i'm going to very simply copy this paste that in there in here i'm going to say confirm password and then i'm going to i'm going to save this now what do you guys think is going to happen is this going to fail or pass i'm trying to like quickly not show you guys what happens what do you think will happen here will this fail or pass well if you said fail then you are correct it well it passed i'm actually a little surprised that that passed and the reason why that passed is let's make this confirm password and then let's go over here and kind of ruin the suspense there let's do confirm password and then confirm password so let's go ahead and save that and this should fail so let's go here and now why do you think that this failed well let's actually scroll all the way up right over here and it says so it says that hey we just found multiple elements that match this regular expression and the reason for this is because if you look at the label this label over here has password and then this label over here even though it has confirmed password it also has password and so it matches that regular expression and remember when we have multiple elements when we utilize get by it's going to throw an error so in order to fix this what we can do here is remove the regular expression and just simply say we want to find an element that has a label that has the string password and just the string password nothing else no confirm password no uh the capitalization does matter and that should work so if we were to go ahead and save this it passes all right so well congrats we uh wrote our very first test and it's actually a pretty sophisticated test we're actually doing quite a lot so that's awesome and now let's actually move on to more complicated tests in the next videos now that we got one test out of the way let's go ahead and write another so what test do we want to write well i want to test that we have the ability to type into these input elements so if i were to type something in it should be inside of the input element that i typed into so that is what i want to test so let's go ahead and test this so the first thing that we want to do of course is create a new test block because this is testing something completely different and what we're going to say here is we're going to give this test a name and this should say something like should be able to type an email type and email and then we're gonna have our callback function and in our callback function we're gonna render our app components so let's go ahead and do that and now what we want to do is we want to get the email input element so let's go ahead and copy this and we're going to paste it in there and actually right here we can do one better so what we can do is we can get by role the text box as well as get by label text so we can have both queries simultaneously in order to do this what we can do is pass in an object as the second param and then we can say name and then over here we can have our uh our regular expression so what this is doing is getting by the role text box and it's ensuring that the label text is email so now we're having these two simultaneous queries that ensures that we're getting the correct text box because we can have multiple text boxes within our component all right so that is the first element and now what we want to do is we want to type into this element now how do we do that well what we're doing here is trying to simulate a browser interaction inside of our test and we can actually do that by going into our package.json so let's go into our package.json and we can do that by utilizing this library that was already installed for us testing dash library and then slash user event and what this does is it simulates user events that could occur by a user in the browser and if we actually went to the documentation i'll have this attached to the video you can see all of the events that we can utilize we can utilize a click event and over here it has an example so over here we have this element right here and what we're doing is user event dot click and then we're going to click this element right over here as you can see we also have a double click we also have type well this is something that we're going to use type there's also keyboard options upload clear et cetera there's many many different things like hover and unhover now what we want to do is we want to utilize type so in order to do this what we need to do is import user event from uh ad testing library slash user events so let's go here we're gonna import that in so let's import it right here and then in here we're going to say user event dot whatever event we want type in this case and then we need to provide it with the element we want that event to occur in so we want this to occur in the email input element and then as the second parameter we're going to provide it with well what do we want to type in this case we want to type in an email so we can say selena gmail.com and the last thing that we need to do is the assertion so now what we need to do is expect and then we need to say expect that the email input element dot value and we expect it to be well we expect it to be this right over here now this is going to be one of the rare cases where the test will pass even before we have implemented the code because by default we should be able to type into an element and that should change the value of that input element now you might be thinking well if by default that's how it works then why in the world do we even care about this test well later on in the course not to spoil anything but i guess i will we're going to be adding two-way binding to our input element so we're going to be storing the input value inside of our state and then the value of the input is also going to be our state so we're going to have basic two-way binding so we're going to have here something like value is equal to well whatever that uh state is so we need to actually make sure that we're able to when we update our input element we also update that state because for example if it stays empty like this if it stays empty like this well in that case our test is going to fail and well that means that this test was actually useful in catching that error so that is just foreshadowing what we're going to do in the future and well this is the first test that we wrote with user events welcome to your very first do it on your own section so what i want you to do on your own so pause the video of course is to do similar tests to what we've done over here but also for the password and confirm password so i want to have two separate test blocks that test that we are able to type into the password field and well that should change the value of this input element and then another test block that tests that we should be able to type into the confirm password and this should change the value of this input element so go ahead and try that on your own you can use the other tests as references so i'll give you guys a quick five seconds to pause the video and try it on your own and then i'm gonna go ahead and do the explanation so five four three two one all right so let's go ahead and let's do this right now so the first thing is is we need to have another test block and we're going to say that this test block is well we should be able to type a password should be able to type a password and then we're going to have our callback and then in here we're going to have a render we're going to render our app component and then what we're going to do is well we want to get that password element that password input element so we're going to say const password input element and what we're going to do is we're going to do screen dot get by we're going to get by label text and we're gonna say password because we can't do a regular expression for this because we have multiple elements that have a label text of password within the text itself so we're just gonna do the regular string for this so now once we get it well i want to type so i'm going to say user event dot type and then i'm going to say password input element and i'm going to type in my password of password exclamation mark the last thing i want to do is the assertion so i'm going to say expect and i'm going to expect that the password input element its value to be well password with an exclamation point and again this is one of the rare cases where the test will pass because of course we by default we're able to type into the password so as you can see here it passes all right now let's do the exact same thing for the confirm password so let's go here and research we should be able to con or type we should be able to type a confirm password we're going to go here and we are going to well we need to first get that element i'm going to go ahead and copy and paste it this time so let's go ahead here let's copy and paste that just so we can speed this up a little bit and then what we're going to do is a user event dot we're going to do a user event dot type and we're going to do confirm password input element we're going to type in password exclamation mark and then what we're going to do is expect that the confirm password input element dot value dot to be well password exclamation mark so now if we were to save this we should have another passing test and we don't actually so why is that failing well over here it's saying that it's not able to find the the label text of confirm password okay i wonder why that is okay and i know exactly why that is and that's because we're not rendering the component inside of our test so let's go here and let's render the app component so now we should have a passing test now is the time to start working on some more complicated tests specifically we're going to start testing the error handling capability of our form so for example if someone put in an invalid email and clicked on the submit button we should see this message right over here saying that the email you input is invalid so you know what let's just get right into it now this is going to be a separate test so we're going to say here a new test block and for the uh the title of the text exactly what this or description of the test we're going to say that this should show error or email error message on invalid email all right so in here the first thing of course that we need to do is render our component that we want to test which in this case is the app component the next thing is well we need to type into this input element so that's the next thing that we need to do so of course to do that what we need is to get the input element so let's go over here and let's find that input element right here awesome let's find that and we're going to go ahead and we're going to um put that in there and then we're going to do user event dot type and then we're going to say input email element and then what we're going to say is you want to type an invalid email so we're going to say selima selena but then we're going to forget about the at sign or we're just going to say gmail.com that's that's pretty invalid to me so you can say user userevent.type and then the element itself and then an invalid email you can put whatever email you want in here and then what what do we want to do what's the next step to get this error well we want to do is we want to click on this button right over here now this button doesn't exist at the moment but it will and it's going to be the only button inside of this component so what we can do here is we can get this button by roll so we can say submit button and then or we can call it element as well might as well submit button element or we can go screen dot get by roll and while this has the role of button and this should get the button uh inside of the only the only button inside of our form now if you want to be more specific of course we can go here and add the name and we can say that this is going to be submit and let's actually do that all right that's awesome so now what we want to do is we want to click on this button so over here we're going to say user event dot click and we're going to click on the submit button elements all right so now what we want to do is assert that this error is present in the document so what we can do here is we can get that error so you can say email error element and we can get it by text because it's going to be just a normal p tag so we can say here screen dot get by text and then over here we can have a template literal and over here we can say the email you input is invalid okay so the email you input is in valid so now once we get it we want to assert that well this is present inside of the document so what we can very simply do is expect email error element so email error element to be so dot to be in the document and this right here is a matcher that tests well is this present inside of the document and of course you can look at all of the different matches that we have but you what we can also do is we can go to this just documentation and it shows you all of the dom based matches so over here maybe we have a button that's disabled so we can test if it's disabled by doing to be disabled over here to be enabled to be empty to have class to to be visible to be checked so there's a bunch of uh you know dom based matches that we can utilize i'm going to be utilizing again to be in the document because well it's not going to be in the document if uh well the error is not there okay awesome so we're going gonna say expect this to be in the document to be to be in the document and that's pretty much the error one thing that we could also do is test that initially this error isn't present and only once we input an invalid email and then click submit well that's when it's present so we can actually have two different assertions at different locations in the code so in order to do this what we can do is we can copy this over here and we can put it right at the very top and we can just do an expect right at the very top so we can say expect and we expect that this element right over here and over here what we can do is say to not to be in the document to be in the document so by uh by having this knot in the middle what it's doing is it's just flipping everything now one thing that's going to happen is even if we coded this out and everything is working fine as expected this test will always fail and the reason why is because we're using get by text and remember when we don't have an element which we are expecting initially what ends up happening is this throws an error so what we need to do is we need to change this to query by and then we assert that it is not initially in the document and then of course we're going to do some of the user interactions we're going to type and then submit and then we expect it to be in a document and just for organization's sake let's actually move all of these variables up here okay let's also move this one and uh and that's pretty much it so that's that's pretty that's a lot cleaner in my opinion we have all our things here we expect it initially to not be in the document and then we have these two user events and then we expect it to be in the document so i think this is a really really good test let me fix that oh my goodness what's going on with these extra letters all right so let's save that and of course this is going to fail in so many different ways but let's actually go ahead and code out a solution in the next section so we wrote the test and now let's write the implementation to make the test pass so the first thing that i want to do is right at the bottom i want to add that button so inside of the form but after this div this last diff over here let's add a button and then in here we're going to give this button type submit so type is equal to submit and then in here we're going to say submit all right awesome so that is the button so we added the button and now in our test we should be able to successfully query for this button that has the role of button of course and it has the text of submit but now what we want to do is we want to display any errors that might occur so in order to do this what we need to do is somehow get the value that we put inside of our input inside of some state in our react application now the best way to manage state in a component level is to use use state so what i'm going to do is i'm going to import use state so i'm going to import use date from react so let's go ahead and do that and now we got use state and so in here what we're going to do is we're going to say const and we're going to say sign up input and then over here we're going to say set sign up input and this is going to be equal to use state and initially it's just going to be an object so it's going to be an object where the email is an empty string and then we're also going to have the password be an empty string and then over here we're gonna have our confirm password to also be an empty string now again the reason why we're doing this is that we want to do two-way binding so whatever this state is over here is going to be the value of this input and anytime we update and change the input we're going to update the state so let's just do the one way binding where the input over here is going to be whatever this is so we're going to say here value and then we're going to say value is equal to and we're going to say values equal to sign up input dot email now let's say that we actually did this and we forgot to do the two-way binding with the on change let's actually go ahead and open up our terminal so let's open up our terminal and let's see what happens so let's go here let's go here so right now we have that one failing test that makes sense that's the one that we just wrote but if i went ahead and saved this and we forgot about this and we thought okay everything is fine well our tests are going to tell us that everything is not fine so we should have an additional failing test if this there we go so you have an additional failing test and that's going to be the test of um where is it where is it so yeah so well this one is the one that we just wrote well this one right here so it should be able to type an email well right now we can't type an email because the email is always going to be an empty strength so we're not going to be able to change the value so in order to make this test pass we need to have an onchange handler and we're going to give this a function called handle change so we're going to give this a function called handle change and then in here what we're going to do is we're going to do a const handle change and this is just basic react to a binding we're gonna get the event and then what we're gonna do is we're going to do set uh the sign up input so we're gonna set the signup input and we're gonna make that equal to an object and what we're going to do is we're going to destructure out everything inside of we're going to or we're going to spread everything inside of the sign up input except we want to change the email in this case to whatever e.target.value is now because what we want to do is you want to utilize this a handle change throughout both the uh the email and the password and the confirm password what we can do here is utilize the name so the name here says email which matches this right over here so what we can do is we can say that we want to utilize the property e.target.name then this is going to resolve to the email when we change the email and we want this to be e.target.value and we don't even have to test if this works what we can do is just simply rely on our tests so if our tests pass then everything should be okay well i mean with that one test will fail but we should only have one test failing rather than two so let's wait it's taking extra long these days or i'm not scroll down but you can see here yes okay awesome so now we are able to type into it and now we have this two-way binding and so what we can do very simply now is actually copy this and paste it in here but change this to password and over here we can do the exact same thing and we can change this to confirm password now if there's now this will actually result in an error because as you can see the name here is not a confirmed password so we should get an additional error here so what we can do to fix this is just very simply change the name to confirm password like so all right awesome but this is something that i caught right away however it could be something that you don't catch that the that the test did catch all right so now that we have that now we have the two-way binding what we want to do is we want to validate the email when we click this button so when we submit this form we want to validate the email so right over here let's add another handler and we're gonna say handler and let's actually wait give it a little bit of classes here so let's say btn btn primary and then we're also gonna give it an on click so we're gonna give it an on click and this is gonna be handle click handle click all right and then over here this is where we're going to have our const handle click and here is where we're going to validate all of our um all of our inputs so the first thing that we would want to do is get the target and prevent the default behavior so let's just do e dot prevent default we're gonna go ahead and invoke that and then what we want to do is right now let's go ahead and get the email and validate that it's actually a real email so what we can say is we can use some sort of regular expression to validate the email so let's actually go on the internet and say how to validate an email an email in js let's let's let's see how we can do that that's pretty it's a pretty tough thing to do maybe if we can find a stack overflow for this it'll be a lot easier stack over flow so let's go here best way to validate an email let me zoom in here for you guys so this person is saying uh let's use this crazy regular expression to validate an email honestly we could use this and this is one implementation detail that we could utilize but i don't think this is a very good approach and the reason why i don't think this is a good approach is because there are libraries out there that do these things and they're very very popular and if we just do this we're kind of reinventing the wheel so instead let's actually go to google and search for email or maybe validator so validator and then javascript so if we search for that then what we're going to get is a library called i actually can't find it here but there's a library called validator that can actually do these stuff for us so maybe if i did validator mpm i'll find it there we go so you can see here that there's a extremely popular library let me zoom in here for you guys that gets almost 6.4 million um downloads every every day and it does exactly what we want so we want uh validator dot is email we pass it the email and the either returns true or false now at the end of the day it doesn't matter if i use a regular expression or a library the implementation doesn't matter what what matters is how how the user interface and how the interactions um occur in in real life and so that is what matters so we don't care about the implementation details so let's go ahead and install this library so validator we're going to open up a new terminal window and we're going to do npm install and we're going to do validator and let's go here and let's just wait so while that downloads what we can do is we can import validator so we can say import valley detour from and we can just say va lead detour i might need to restart my computer after this because it's acting extremely slow all right let's just wait i think it's because i have docker running to be quite frank maybe i should probably get rid of the hucker okay so let's just wait wait wait and there we go so now we got that and so here what we can do is have a check so we can say if and then here we can say if the uh we can do validator dot is email and then we can pass in the sign up input dot email and what we want to do is we want to check if this is not an email then what we want to do is we want to throw an error so okay so well what's the error so we can actually create another piece of state here and we can say const and we can say error and then here we can say set error and then over here we can say use state and initially that error is going to be an empty string so here what we can do is we can return set error and we can say well what the error message that we want to say so what was the error message it was this right over uh this right over here so the email you input is invalid so you can say here the email you input is invalid so that is what we want to set and so lastly right at the very bottom what we can do is we can have a p tag that shows that error only if we have an error so we can say error and then and then we can have our p tag let's have our p tag in here and then here we're just going to display the error so if the error is not an empty string and there's actually an error well we're going to display this a p tag with that error however if it is an empty string then that resolves to falsely and we don't see this p tag so this should work so the last thing that i want to do is just maybe give this a little bit of styling so it's nice and red so let's say class name and we're going to say text danger so without even running this what i can do is open up my terminal see the tests and hopefully everything should pass and no it doesn't so i wonder why that is so over here it uh expected but it received null i wonder why that didn't really work the way that i wanted it to so there must be some sort of bug inside of our app so the email you input is invalid that is this right over here the email you input is invalid let's actually go ahead and try to run this manually that's another form of testing so let's just say npm run start just to run it manually see if it works okay so what are we doing here so we have this okay so let's use a different port because i'm already running something on port 3000 and let's see what port it read our access to let's give it some time okay how long is this going to take port 3001 there we go all right so there we go and let me just zoom in here for you guys so let me type in something invalid and if i click this well i actually do see it so i'm very curious as to why this test is failing oh okay i actually know exactly why this test is failing all right so all right so let's go over back to our test so what we're doing here is we're querying it initially so that's the very first thing that we're doing we're running this query initially and initially this is going to be null because it it doesn't exist inside of our um it doesn't exist inside of our inside of our virtual dom so it doesn't exist so it's going to be null and so what we're doing is initially asserting that it's not there and it's passing but then what we're doing is we're using that exam exact variable that is initially null and then we're asserting that it's going to be in the document so over here this is going to give us null and we're asserting that it's going to be in the document so what we actually need to do is make this uh call again so what we can say here is const we're going to get this element and we're going to call it maybe again something like this email error element again and then what we're going to do is we're gonna assert that that's in the document and that should work so i hope that makes sense so let's wait a little bit here and now we should have all of our tests passing and we do so again just a quick summary as to why that happened initially this is this was null returning null we were expecting it not to be in the document that passes but then we were using that exact same variable for this assertion we had to go ahead and make that query call again to make this work all right so that makes our test pass assignment time so you're gonna write two tests that are really similar to the one that we wrote right over here so what are these tests well now these tests are gonna handle the errors for the password as well as the confirm password so only if we input a correct email and then we input an incorrect password so a password that is less than five characters do we want to show this error right over here so again if we did this so if we have latex hotmail.com and so this is a proper email and then over here we have an improper password then we want to show this error however if the email is improper and then we also put an improper password then we want to show the email error and not this so you only show this uh error if this field over here is okay and it passes the check so what i want you to do is to write a test that simulates this so we put in a proper email but we put in a password that is less than five characters and then we see this error right over here now the next test is going to test if the passwords don't match so if we put in a proper password a password that's greater than five characters and we also put in a proper email but we put in a password that is completely empty or it doesn't match we want to show this error right over here so what i want you to do is i want you to write two tests for these conditions so go ahead and do that and we'll have a solution in the next video all right hopefully you guys gave that a go so now what we're gonna do is we're gonna create a brand new test block and then here we're going to show the password error if the password so if password is less than five characters so that's gonna be the uh description of the test and so in here what we want to do is we want to type into the email and put in a valid email so let's do that first and honestly we're just going to go ahead and copy some of the stuff that we have here so we're going to go ahead and copy the render so let's copy that we're going to get the input element for the email let's copy that and now what we want to do is we want to do a user event and we want to put a valid email so we're going to type in a valid email address we're going to say something like selena we've been doing selena so let's do selena but this time at gmail.com so that's a proper email now what we want to do is to basically do the exact same thing that we did over here so we want to find this element right over here so we want to find this element and let's do it at the very top and this is going to be uh the the message the password message the password error message so that's going to be uh the password you entered should contain five or more characters and then over here we can say that this is going to be the password error element and so the first thing that we want to do is we want to assert that that is not there already so right after we type into the email let's just do an expect here we're going to expect that the password error element we're gonna have to do a query buy and we did we're gonna say expect that to not to be in the document go ahead and invoke that all right so that's our very first assertion and now what we want to do is uh well we want to type into the password element so let's go over here and actually we can probably copy it from up here we can get this one the label text so let's go over here and let's just put that input element in and now what we want to do is we want to type an invalid password so let's type a password uh password error element and we're gonna type in an invalid password maybe something like one two three so that's only three characters and then what we want to do is we want to click on the button let's go here and copy that and paste that in there we want to work with the input element not the error element so now what we want to do is want to click on the button so let's find the button let's copy that and you can see here that there's a lot of uh duplicate code here our tests are really getting long and messy don't worry we're gonna do a lot of cleanup later so i'm gonna show you the proper ways to you know prevent all this duplication and all this um extra long code so now what we're doing here is so once we input this now what we want to do is we want to click on the submit button so we're going to say user event dot click and then we're going to say submit button element so we're going to click on that and then the last thing is we want to query for this element again so this error element and so we can just call this again and then what we can do is well we can just say very simply expect the password input element again and this time we expect it to be in the document and that's pretty much the test i know it's a very long test and again we're duplicating a lot of these things but we'll fix it later so let's go ahead and just look at our wonderful test fail i'm not running the test because i restarted my computer so let's fix that so our test should fail and in the meanwhile let's actually go ahead and fix this so we can actually fix this very very easily all we have to do is add an if else statement over here so what we can say here is if else and then let's just first look at our test so let's do a to run all of them and then over here we can say if uh yeah one of our tests passes so we can say if the sign up input dot password dot length so if that's less than five characters then we want to throw that error so now what we can say here and when i say throw an error we're not really throwing an error we're just gonna set the uh set the error to be the error that we provided uh over here so the password you entered is should be five characters or more so let's go here now we're gonna say the password you entered should contain five characters or more and this should cause it to pass so let's go here let us wait wait wait and i hope that passes and it does awesome all right that is terrific and so now let's actually just uh do the very last test so the very last test is going to be uh the uh confirm password so what i'm going to do is i'm going to just copy all this because we're going to do a lot of duplication so let's just copy this whole test block that we wrote let's paste that in there so let's paste that in there and again it's looking really messy i really don't like it but let's just say here should show confirm password error if passwords if if passwords don't match so that's the error and so now what we want to do is well we want to get the email input element we want to get the password input element and then we don't want to get the password error element we want to get a different one so over here let's change this to uh what was the error message so the passwords the passwords don't match so the passwords don't match try again so try again so that's and we can make this just lowercase because we're using regular expressions here and we can call this uh password confirm or confirm password let's just call it confirm password confirm password so confirm password uh error and so initially what should happen is we should uh well let's go here this should not be on the screen or not be in the document let's add another type over here to type in the password let's type in the password uh okay so where is that so over here let's type in a valid password like one two three four five so that is five characters and so initially we expect it to not be on the screen and then let's get rid of this because we did that so in here what we want to do is we want to actually get the confirm password input element so let's find that where is that confirm password there nope that's not it confirm password confirm password where is that there we go this works let's go scroll all the way to the bottom let's actually just put that right over here with all of its other friends and now we can just put in an invalid password or a password that doesn't match so here what we can say is confirm password input element and we can say one two three four five six for this now you can see that they don't match then what we can do is we can click the submit button and then we're going to query for this again so we're going to go ahead and query for the confirm password element again so yeah confirm password element again and we're going to use this template or this regular expression and what we're going to assert is that this now is in the document all right that's pretty much it super super long test let's save it and let's open up our terminal and we got one test failing now to fix this test let's go here now all we need is another uh else if statement so you can say else if and we can say sign up dot password is not equal to sign up dot confirm password and then we're going to return set error and then let's do well what's the message let's go back here i forgot already this message all right so the password uh the passwords don't match try again so now if i were to save this all the tests should pass there we go awesome all right my good friends well we're almost done this application we really just have one more test but before we do that i want to note that we only tested our application through these automated tests and to be quite frank we shouldn't do that we should use a combination of automated tests as well as manual tests so let's go ahead and open up our react application so yours should be on localhost 3000 mine will be on locos 3000 and well nope i forgot that i restarted my computer let's go ahead and run it and it's going to be on localhost 3000 and let's actually just do a quick uh manual test so if i went ahead and i uh clicked this it inputted and didn't even input an email then i should get this message awesome let's put in an invalid email i should still get this message now if i put in a valid email but i don't put in any passwords i should get the password message and okay and well maybe with this automated test i noticed that i don't have a period so maybe i can add that period in so let's go here we could have also caught that in the um in the automated test sorry i meant manual test before so you can add that period in you can also have that in okay cool so now what we can do is we can input a valid password so let's say one two three four five and now this doesn't match and over here one two three four five well we still see this error because we didn't clear any of the errors so now let's just quickly do a latha hotmail.com and then over here let's just put in uh let's just put in one two three four five one two three four five and if we click this then we are completely fine so the very last thing that i want to test is if we input everything valid then we shouldn't see any errors so let's just quickly go ahead and test that in the next video the last thing i want to add is a test that checks that no error message is present if we input everything correctly so let's go over here to our app.test.js and this is a test that should pass right from the get-go so let's go here and let's actually just copy let's copy all of this we're going to copy all of this and we're going to paste it in here all right and then we're going to change this so we're going to say that should show no error message if everything or if every input is valid okay cool so now what we have here is we have the email input element we have the password input element we have the confirm password input element let's go ahead and get rid of this we have our button and then now let's type in something that's valid so let's go here and we're gonna say uh well we're gonna type into the confirm confirm password input element the same password that we have here and then what we're going to do is going to get rid of this assertion and what we're gonna do here is of course get rid of this as well so over here we have the type email type password type confirm and then we're gonna click and then lastly over here what we're gonna do is we're gonna assert that all of these errors are not present inside of the document so let's also get the email error so let's go here and where is that so the password error let's copy that and let's paste that over here let's also find that email error so email error this one let's copy that and let's paste it right over here let me get rid of the again and what we can very simply do at this point is just assert that all of these are not present in the document so we can have three assertions and then we can assert this and we can insert this this is known as asserting the happy path so before we we were asserting not the happy path but the happy path if everything goes fine this is what we expect we expect just no error to occur later on you can add some logic to actually sign up the user maybe redirect them and you can test that but for now we just don't want to show any error and that's really all we want to do okay so that's pretty much it and this actually should pass uh regardless we don't have to do any changes so this should just be green right away so let's uh wait and it actually doesn't so that means that there's something wrong with our test and the thing okay so what's wrong with our test is we actually expect all of these errors not to be in the document and i said to be in the document so let's put the knot in there so not not and then lastly let's put a knot here save that and now it should pass all right come on please please pass there we go it passed and that pretty much concludes all of the tests for this application congratulations you guys really worked hard with this and you built the application as well as tested it and you followed a test driven development approach now there's one thing that kind of sucks about this uh this test file is that each test is well some of these ladder tests are really big like very very big as you can see and we have a lot of code duplication so this is obviously not great and the same principles apply to tests that they do to normal files we should always try to keep our application as dry as possible and this includes the test so we should not repeat our code and uh so in the next section we're actually gonna start looking at how we can refactor the test just so we can make it a lot more organized all right so we wrote out all of the tests but as you can see it's really long and you know the tests are not really dry so what can we do to fix this well let's actually look at each individual test so this test right over here the first thing that we're doing is we're rendering the app now i'm actually going to notice a little bit of a pattern if i look at every other test so you can see here also we're rendering the app here we're rendering the app so actually what's happening in every single test we are rendering the app so that is 100 guaranteed so we're rendering the app component so what can we do so that we actually don't have to explicitly say we want to render the app inside of the test block well to do this what we can use are hooks so we can use something known as a before each hook so way before each hook and what this is is a function that is going to be invoked before each test so over here we have the function and then in here we can have a callback and inside of the callback we can have the logic that we want to call before each test so for example what we can do here is console.logged console.log called before so we're going to do a console.log called before and what we should see is right as you can see here before each test we're console.logging this so we're running this function so we're running the callback function so what we can actually do inside of this before each hook is call that render method and pass in the app component and so now we can actually remove this render we can remove this render from each test all right so we can remove this render from each test and let's do that and you can see here that that already simplified our code a bit so let's find the last render let's go ahead and get rid of that and i think this one's the last one let's get rid of that and now if you were to save it and if all of our tests pass we know that everything is okay so let's just wait and everything passes awesome so you can see here that you can utilize these hooks to really simplify your code and you can plug in repetitive things so that you don't have to worry about adding them into each test so over here we have the before each hook now let's talk about some of the other hooks and we won't we won't actually utilize them but i want to talk about them just so you can learn about them so what i'm going to do is i'm also going to console.log before each so i'm going to say this will right here let's this will run before each test now there's other other hooks that we can utilize and these are just hooks you can also utilize after each so after each you can probably imagine what it will do so we can console.log and we can say here this will run after each test so if you ever want to do some sort of cleanup after each test well you can put that inside of the after each so let's actually console.log that just to see how that looks all right so we can go here and let's go all the way to the top so you can see our very first test so this will run before each test and then we're going to run this after each test we're going to do that for every single test that we have as you can see all right now there's two more hooks that i want to talk about i want to talk about before all so this what is what's going to happen with this is it's going to run only once before all of the tests so let's go here and we're going to say that this will run once before all of the tests so if there's anything that i have to do just one time before all of the tests i can use the before all hook so let's go here let's just wait a little bit or maybe just scroll down and so you can see if i were to scroll up if i were to find it where let's just let's just save this again all right there we go so let's scroll all the way up and if you were to do that where is it so before all yeah so this will run once before all of the tests and this is going to run before any before each hook so you can see here that this is at the very top and then we have the before each hooks and as you can imagine we also have after all so we can say after all and then we can say this will run once after all of the tests so over here you can say after all of the tests let's just open that up and there we go so at the very end this is going to run after all of the tests so these are some of the different jest hooks that we can utilize more often than not you're probably going to use the before each hook and the after each hook for clean up but sometimes you do want to do things once before you run your test suite and then after you run your test suite so let's just get rid of this and we're just going to get rid of this log and right now well we simplified our test a little bit but it's still extremely messy so let's think of another way that we can actually simplify it so we simplified our code a little bit our tests are a little bit nicer now we don't have to add this render app on each test however as you can see there's still a lot of code and it's not really dry now one thing that's really bothering me is that throughout each test we perform the action of finding the input elements and then typing into the input elements fairly regularly so for example this test over here we're finding the input elements and then we're typing into the input elements over here we're also finding the input elements and then we're typing into the input elements so where this this logic right over here is repeated throughout multiple tests now what do we do when we have logic that we want to utilize throughout our code base well we put that logic inside of a function and then we call that function everywhere well we can do the exact same thing in a test suite so let's actually go ahead and do that so let's create a helper function that is going to find the elements for us and type into them so let's go ahead and do that so over here let's just create a function normal javascript function and we're going to call this type into form so this is a function that types into the form so normal arrow function and what i'm going to do is i'm going to pass in an object and inside of this object we're going to pass in the email the password so the password and the confirm password confirm password and so if we actually provided an email or a password or a confirmed password what we want to do is we want to find that element and then type that email or password or confirm password into it so let's just for example let's just start with the email so if the email so if we actually provide an email and we actually put input something so it doesn't really have to be an email just has to be any string that's that's not undefined or an empty string then what we want to do is we want to type in that email inside of the email input element so at the very top at the very top let's actually copy this and let's just get the email input element and if we have an email if you provided it with an email what we're very simply going to do is well user event dot type and we're gonna say email input element and then we're gonna say whatever email that we provide there we go that is the very first thing so now let's move on to the other things let's add another if statement so now if you provided us with a password well let's go ahead at the very top let's find the password input element which is this one let's go here at the very top let's paste that in and we're going to say user event dot type and then what we can say here is well we can invoke it we can use the password input element and then what we can do is well we can type in the password awesome so the last thing that we want is to confirm password so let's say confirm password if you provided us with a confirmed password let's go here now let's copy that and so now what we can do is very simply add that at the very top and now we can just do user event dot type and over here we can say confirm password and then we can say password all right awesome very very simple we don't have to do much else and actually this should be confirmed password so it should be confirmed password here and then here should be confirmed password and that's pretty much it so now what we can do is we can actually call this function whenever we need it so let's look at this very first test so in this very first test we're not really doing much we're just testing that initially they're empty so we're not doing any typing so we'll just leave that as is here however well what we're doing is we're doing some typing we're typing this and we're checking if if the email input element its value is uh the same as the thing that we typed so here we can actually utilize it so instead of actually doing this and let's just comment this out for now we can actually just very simply invoke we can invoke type into form and then we can just pass in the email the email that we want to type so we can just pass in this email so look at that look how much simpler that is so instead of having these two lines of code we just have this could be even a one-liner if you wanted to we can just have it be like this so instead of having this over here we have this one liner now the only issue with this right now is we don't have access to the email input element and the reason for that is even though it's in the function itself you can see that this email input element is scoped within this function and it's not scoped within this test block so what we can actually do to fix that is just return the elements so we can just return the email input element we can return the password input element and then we can also return the confirm password input element and so here now what we can do is we can just get the confirm password input or not the confirm password we can just get the email input element from this function and then we can assert this so you can see four or four simpler and less lines of code so let's actually let's actually save that and let's see if that affects our tests in any way and it doesn't so you can see that everything still passes but it's a lot simpler now so let's just do the same thing over here so now what we want to do is we want to get rid of this or let's just comment it out for now and now what we want to do is we want to call this function we want to get the password input element and we want to say the password and over here we can say password now let's get rid of this code save that should work let's just double check there we go a pass same ordeal over here so let's do another refactor so let's get rid of all of this let's just copy this here we're going to say we want the confirm input element and here we can just say that and that that should be fine all right so now let's move on to where it's really going to help us out so over here uh what is this saying so should show email error message on invalid email so here you can see that we're getting we're trying to fetch the email input element we don't have to do that anymore so let's get rid of that and then here we're not gonna type in this in anymore so let's also get rid of that and or let's just comment it out because i want to keep the email the same so here what we can very simply do is call type into form and actually we don't even need to get the uh the email input element because we're not using it anywhere else so we we just needed to use it in order to type into it but now what we can do is just invoke this and then pass in an email so we can pass in an email that is invalid like this so now what we can do is we can get rid of this and you can see that's already a lot simpler awesome okay so if you look at our tests oh now it's failing okay so why is that okay so what test is failing so should type in should type to should be able to type to confirm password so that was actually one of the tests up here that i uh didn't even bother testing or looking at so let's go over here to should be able to type into confirm password uh so the reason for that is this should be confirmed password not password so confirm password and that should fix this test and we also know that this test is passing so now let's do the exact same thing over here so we don't even need to bother with getting the input element we don't even need to bother with getting the password input elements because we only we only needed to bother with them because we because we um what am i trying to say here because we were trying to type into them as you can see over here so now what we can very simply say is type into form and we can just put a valid email so here you can just put selena at gmail.com and then here we can just put a invalid password so right here we can put an invalid password so we can say password and we can say one two three here and that should be fine as well there we go so if i were to save this and that passes all right so that is the show error so now let's go work with the show confirm error so let's get rid of the password and email and let's also get rid of this we don't need this as well we don't need the input elements at all and now what we want to do is we want to type into type into the form so we can just very simply say here type into form and instead of having two lines for this we can just have one line so we can say email is going to be this valid email and then over here what we can say is password is going to be this valid password what's the one two three four five now we can get rid of this and over here we can leave that as is here we can add the other type into form however this time of course what we want to do is put in a invalid confirm password so we can say here confirm password we can say that is one two three four five six so now we can get rid of this and i think the rest is a okay so let's go ahead and save that and that should still pass and it does so now the last thing is well let's test the happy case so the last thing that we need to do let's get rid of all of this so let's get rid of all of this and instead of having three lines for typing what we're gonna just simply say is type into form and we're gonna put in a valid email let's copy that email we're gonna put in a valid password so one two three four five we're gonna also put in a valid confirm password one two three four five and we're gonna get rid of all this code and now we have the user event the rest is a okay so now we can go ahead and save that and there we go awesome so you can see that now our our code is a lot simpler a lot lot simpler now there's still a lot of duplication and we'll talk about that a little bit later actually it's going to be an assignment for you guys to do however you can see that this is this is the way to go to reduce the um duplication within our test suite all right my good friends it is challenge time in this challenge what you're gonna do is create a helper function that is going to find the submit button and click on the submit button so if you actually look throughout the test a lot of the time we're trying to find the submit button and then we're clicking on the submit button over here you're finding the submit button we're clicking on the submit button so you know this is a lot of code duplication that we can reduce with a function so what i want you to do is create a helper function that is going to reduce this to do this action and then i want you to call it in those tests blocks instead of doing these stuff manually so go ahead and try that out and as always in the next video i'm gonna go ahead and do it okay hopefully you guys gave that a go so the first thing that we're going to do is we're going to go all the way to the very top and we're going to create a new function we're going to say click on submit button that's going to be the function and this one's going to be really easy so the first thing we need to do is find the submit button so let's go to one of our tests where we do that so we're going to go ahead and copy that paste that in there and then let's do a user event dot click and then submit button and we don't have to return anything because we never really do anything with the submit button other than click on it now if we did do something with it so if we asserted that it was in the document or something then we could return it if we want to so over here let's start utilizing in our test now before we do that let's actually just look at how many lines we have so we have 167 lines so let's see how much this reduces it so let's go here so over here let's get rid of this block of code and here let's just replace this with click on button very simple that's it that's all we need and we can get rid of these two over here and there we go so over here we can replace that with just click on button and we can get rid of this line of code and then let's uh let's look let's look here you can replace this here you can get rid of this line of code and uh last thing that we need to do is this one you can replace this and we can get rid of this line of code i think that's it let's see and it is it awesome so let's go ahead and just save that and then take a quick look so you can see that that actually saved us well like 20 or i don't know i actually was 67 before now it's 50 uh 152. so if my math is correct that's 15 lines of code that that one little function saves us so you can imagine how much lines of code that this saved us over here uh i guess i also didn't really factor in the creation of the function so maybe really only saved us 10 lines of code all right so that's great and you can see that this is actually not not only does it reduce duplication it also makes our tests a lot more readable so now if i you know i were to look at this test the super super long test uh i could just very simply say okay well we're typing into the form that makes sense we're typing in the email the password and then you know we're asserting that it's not in the document and then we type into the form again we click on the button and then we assert that this is um in the document so you can see it's a lot more readable than what we had before now we can also do one last thing to make it better well there's actually a few more things but in terms of reducing the lines of code we can do one more thing and we'll talk about that in the next video there is one thing that we can actually do to significantly simplify our tests and let's actually look at this test specifically to illustrate this point now in this test let's look at the this block right over here so these four lines so what are we doing here well we're first finding the elements so we're finding this error element and we're assigning it to this variable and then what we're doing is we're getting this variable we're putting it inside of the assertion and then we're doing to be in the document so won't it be better to just skip this step altogether why do we care about this step why not just get this right over here and just plug it in there so we can plug it in there and just completely get rid of this so there's really no point of assigning it into a variable if we're only going to be using it once so now what we can do if we were to save this you can see that our code is a lot simpler and over here we can actually do the exact same thing on this exact same test so now what we can do is copy this and we can just plug that in there and now we can get rid of this and just to prove to you that everything still works let's go to our terminal and uh let's go here and you can see that everything passed so now let's actually do that uh with all the other tests and just look at that beautiful test like look how simple it is so now we're expecting that whatever this element is it's not going to be in the document then we're going to type the email we're going to click the button that we're going to expect that it is in the document just look that's an amazing test sorry sorry we kind of went on tangent so uh let's let's go here so this is an excellent example of this so let's just get the screen and we can just very much put that in there we can get this we can put that in there and now we can just simply get this and we can put that in there oops uh what am i missing here yeah so we can get this we should be able to put this in in there what am i missing oh yeah i'm adding a semicolon all right so now what we can do is completely get rid of that and just for uh test sake let's let's look at our tests everything still passes awesome all right can we do the same thing over here uh not really so that will be fine this is fine this is fine this we already did here uh the input error elements we can actually just copy this or cut this out get rid of this completely and then just put this right in here and we can do the exact same thing right here so we can get rid of this variable and so now we can get rid of that and we can paste that in awesome so now let's look at this test let's cut this out let's put that in there and get rid of this now uh and now over here we can just get rid of this cut the whole thing out paste this in here and there we go awesome so now we can do the exact same thing over here i think this is the last test so this is actually an excellent example of how useful this can be uh so look how many how much code we have here this unnecessary code so again let's just get this let's paste that in there let's also get this and we're gonna paste this in here and now we're gonna get this and paste this in here so let's paste that in there and now we can get rid of this awesome and now you can see we were at 152 now it dropped to oh my goodness maybe another like 18 or something i'm not really sure with my math but you can see that everything is passing and our test suite is looking beautiful there is one last thing that i want to talk about and that is the describe block so right now if we were to look at every single test here they all have one common thing that they're doing they're testing the functionality of the app component so what we can do is we can group a similar test together inside of a describe block so let's actually go ahead and do that so right above all of the tests what we can do is we can have a describe block and this is going to be exactly the same as the test block so we're going to have a callback function right over here and inside of this callback we can group all similar tests so what we can say here is as the first parameter we can describe the describe block so we can say that here we're just testing the app component then we can get all of these tests and just put them inside of the describe block awesome and if we wanted we can have multiple describe blocks and we can put our tests accordingly into whatever describe block that we want another thing that we can actually do is we can nest describe blocks so right here we have all the tests that are testing the app component but if we go right over here these tests are specifically testing the error handling of our app component so what we can do if we want is add a describe block over here and we can say error handling so this is what we're testing so error handling and this is in the app describe block and we can have another arrow function and we can just very simply take all of these tests that are handling the errors so the last test is this one you can cut it out let's let's come on did it go too much no i didn't awesome and i can actually put that inside of this describe block so that is another way that we can organize similar tests together and if you were to run this let's go here delete this go here you can see that well everything runs a okay awesome that is cool now one thing that i want to talk about is describe blocks they actually serve more functionality than grouping things together if for example we wanted to run something before each set of tests so for example maybe i wanted to run something before each three out of the ten tests in my test suite so right here i have i don't know three tests maybe i wanted to run a test before each of the tests that handle the error handling well what i can do is inside of the describe block i can add a before each or before all or after each or after all and it's only going to effect it's only going to be ran uh for the tests inside of the describe block so right here how many tests do we have one two um one two three four four tests so let's just go ahead and console.log console.log hello and we should only see it four times we shouldn't see it uh however many tests we have so we have another another uh four test here so we should not see it eight times we should only see it four times so if we were to open up our terminal and look at the tests uh we can go scroll up up up if we can find it where is it do i do i just not see it where is it oh here we go so we got hello hello and we should see hello hello four times and if you scroll up we'll never find it so we only see that four times so if you want to run something before uh before each uh test but we only want it for a specific set of tests we put them inside of a described block now this right over here so this before each well this is going to run for every test and the reason for that is because well it's at the very top level and actually it's best practice to move it inside of this describe block right over here so now what we can do is well everything is still going to work because this is going to be ran before each test that is inside of this describe block and yes these tests that are nested are also inside of that describe block all right awesome so let's just quickly uh take a quick look at this all the tests still pass
Info
Channel: Laith Academy
Views: 40,158
Rating: undefined out of 5
Keywords:
Id: 04BBgg8zgWo
Channel Id: undefined
Length: 146min 48sec (8808 seconds)
Published: Tue Dec 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.