React Testing Library Crash Course - 2021

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
everybody welcome back to the channel and welcome to a brand new crash course in this crash course we are going to learn all about react testing library and essentially this is a library that will allow us to test to write test scripts for our react applications now in this crash course we are going to be building and testing this very very simple application so the reason why i'm doing a very simple application is because well i want to introduce react testing library but this application over here which is a simple counter application is actually kind of deceptive in the amount of tests that we actually have to write so it's kind of a good introduction to react testing library so what is this counter app doing well you can imagine over here we have the counter and we can basically add to the counter or subtract to the counter so what we can do is we can basically add so over here we're adding one so now you can see that this is changing we can also subtract one and you can see here that this is also changing now we can also basically change by how basically these steps how much do we want to increase or how much do we want to decrease so we can change this to something like seven and then we can do seven and then we can also subtract by seven and let's go ahead and change this to like let's say 20. now if we go above 100 you can see that the color changes to green and if we go at negative 100 or under you can see that the color changes to red so this is a very very simple application we're not really going to focus on actually writing the application but we're mostly going to focus on actually going ahead and testing it now why in the world do we even care about writing a bunch of tests for this application we basically kind of in a sense just tested it right now and it seems to be working perfectly fine actually what we did right now is something known as manual testing where we actually go ahead and play around with the software and test if it works okay because right now let's say i expect this to be 79 well it works perfectly fine if i change this number to let's say 1 i expect this to be 120. it works perfectly fine i just implemented a bunch of manual testing with react testing library we are implementing a bunch of automated testing and essentially automated testing are is a way of testing where we write scripts basically saying that hey this feature in this in this component should work a certain way why do i care about that well let's actually look at a diagram to kind of explain why we want to take this approach of the automated testing over the manual testing approach in the long term so again we have two different approaches we have a manual testing this is where we actually test out our software manually so i'm testing right here this should be 121 there we go 121 and then there's automated testing automated testing is when you actually write code test scripts that basically test your software through these test scripts and essentially it basically is it uh it triggers some sort of action and it expects some sort of outcome so this is what we are going to be focusing on with react testing library now why in the world we would we want to basically focus on this over this this seems like a lot a lot of work and actually uh writing the tests for this is going to take maybe three times the amount of work than actually writing the functionality for this so it seems like this is a lot a lot of work that we could have just done by just quickly manually testing well here's the reason why we want to manually test or want to sorry uh test autumn uh in an automated fashion over manual testing so let's say that we have an application so so right now we're working with a very very simple application very very simple but in a real production application our uh our software is going to be very very complex and it's going to have multiple parts to it so let's say that this is a react application and it contains multiple components over here there's multiple components and within each component we have multiple features so over here we got multiple features within each component so let's say what we want to do is for this component over here we want to add an additional feature so right now we have future a b c and r and we want to add an additional feature essentially we're going to modify the code base in some sort of way so we could add an additional feature or remove an additional feature or update additional feature we're just modifying the code base for this particular component right over here now let's say we want to add an additional feature so we change the code base in some way uh let's go ahead and let's add another feature in so let's say we want to add feature z so we add feature z now what we can do with this pretty big application is if we go about the uh the way of automated testing what we can do is we can basically or sorry manual testing what we can do is basically check if this component is working fine okay that's great this component is working fine that's terrific so we can basically say okay we're done this feature now here is kind of an issue that arises let's say that we implement feature z and feature z is broken well when you're actually going ahead and actually writing it you probably can catch that feature z is broken and eventually you can fix it so there we go you can fix it manual testing rules so now let's say that you add feature z and it unintentionally breaks feature a so you add something into your code base that actually affects the functionality of feature a now it's highly likely that you might not catch this now let's say you're focusing on this component and you see that something is breaking within this component and you go ahead and you look around you see what's going on you figure out that okay future a is breaking and you go ahead and fix it and that is fine so here's one thing with automated testing you'll will be able to catch the error right away whereas with a manual testing you might actually not catch this error but let's say you're focusing on this component so it's easy for you to catch this error so let's say another scenario right now let's say you add feature e feature z and it unintentionally breaks feature i in a completely separate component now here it is very very likely that you don't catch this error because right now you're focusing on solely on this component and this component working properly you're not looking around at all of the other components so what you can say is oh this is terrific this is fine this works perfectly okay so i'm going to go ahead and push this into production this is great but then this component over here has features that is failing because of the code that you added now that is the problem with manual testing when we have a large scale application it is almost impossible to go ahead and check every single component and see if it is working properly now with automated tests what we can do is for each feature we can write a specific test we can say that hey i expect this feature to work in this way i expect this feature to work in this way now if i go ahead and write this test and it ends up failing feature i then what i can do is basically run all my test suites and then my tests will tell me hey this feature over here is failing so right away i can i can go to this feature and then i can start to figure out why this feature is failing and that right there is why we want to use automated tests over manual tests so over here i kind of have a list of things that kind of trump manual testing as i said manual testing is error prone remember error prone in that hey we can write this test and completely forget about some of the errors that occur in other components also manual tests are very very time consuming yes in the beginning automated testing might be more time consuming because you're writing the tests but in the long run when you are writing new features if we had to do manual testing for every single component especially as our application is getting larger this can get very very tiresome so this is why again automated tests can just go ahead and tell us directly that this feature right here is failing and so in the long run it is very very uh less time consuming if you will over here also automated tests tell us exactly what went wrong whereas with manual tests we might have to do a little bit of digging around to figure out hey this feature is going wrong manual tests tell us exactly that feature i is breaking and exactly what is happening that is breaking and we're going to we're going to actually see that with our application and then over here automated testing actually can serve as documentation which is really good for new developers actually a lot of the times these senior developers tell these junior developers hey just look at the test they kind of serve as documentation because they're written so well and basically you can see how the software is supposed to work so that is another advantage of automated testing and that is exactly why we are going to be using react testing library to test this application so that is kind of the introduction let's go ahead and create this over here and go about testing it to test out our react application we are going to follow a methodology known as test driven development and essentially in test driven development what we do is before actually implementing a new feature we write tests testing whether that feature works or not now initially of course we haven't implemented the features so those tests should fail over here symbolized as red and then after we write the test what we do is we actually write the bare minimum amount of code needed for our tests to pass and then we basically test our test suite again and there we go now we have a running test so with test driven development if we want to add an additional feature we first write the test testing the functionality of that feature and then we code it out so that test passes and then once that test passes we are done and we can move on to another project or another feature so this is test driven development again we write our tests before actually developing our application now why would we want to do this well there's actually a few good reasons why we would want to do this one good reason is that if we went ahead and just coded out our application we can just write tests that make it just pass based on the application that we coded out whereas maybe beforehand we actually had a bunch of different functionalities that we actually wanted to implement so if we wrote our test first we can have a clear idea of what exactly we want and then we can write out the code that is needed to make those tests pass another reason is test driven development well forces us to write tests if we went ahead and just you know created the component and then uh uh decided to test it out later it's very easy to kind of neglect testing what could happen is maybe you could create a component you could be like okay let me add on to this component before i test and all of a sudden now it's a very very big component that requires very very extensive testing and you can also you know maybe you can kind of forget about it and actually work in a different feature and now you don't have any tests for this component over here so this is why we are going to take the test driven development approach and this is very very common among large large tests large tech companies they uh they heavily use this approach over here of testing their software applications and so this is what we are going to do to develop this simple application so to test out a react application we first have to create a react app and if you're taking this crash course about react testing i'm assuming you have a good to fundamental knowledge of react itself so i'm just going to quickly explain how to create your react app but this is something i kind of expect you to already know so in your terminal just go to whatever directory that you want to place your react app in and do npx create react app and then you can do space and call whatever you want to call your react app so we can say react testing and so this is the command that will allow us to create our react application now i'm not going to run this because well this command takes forever and i already did create a fresh react app but if you haven't then go ahead and run this also you need to have node installed if you want to use the mpx command so if this fails for you it's probably because you don't have node installed so go ahead and install it and then you should be able to do npx so there we go we can create our react app and once you have your react app uh um once you have your react app what you can do is you can go ahead and open that react app in your favorite text editor i am using this text editor vs code which is very very popular and commonly used among almost every single programmer and so this is the react or editor that i'm using to open up my react application and you can go ahead and actually run your application by doing npm start so you can go to your terminal let me quickly zoom in some more let's zoom in actually a little bit more right now just so everybody can see things clearly you can go into either your uh your your basically mac terminal or the built in vs code terminal and you can do a npm start and that way you can actually run your react application so now because i stopped it it should theoretically not be running anymore so if i enter i guess it is still running uh but yeah it's running on localhost port 3000 so that right there is how we can create our react application now let's get react testing library inside of our fresh react application so ultimately what we want to do is we want to uh i have two instances of react running one on localhost 3001 and one on localhost 3000. essentially ultimately we want to make this react application exactly the same as this over here with the bunch of tests now the first thing that we have to do is because we're following a test driven approach we have to somehow get react testing library into our react app so over here you can see the command npm install dash dash save dev and then add a testing library dash react however we actually don't need to do that because we created our app with create react app so if you created your react app with create react app essentially you get support for react testing library right from the get go so there's actually absolutely no installation that you have to do and to kind of prove this to you in the new fresh react application what we would what we can do is we can actually go to the package.json and over here we can see that we have at testing libraries and this is basically the react testing library right over here and these are kind of the dependencies that we installed and actually if we go to our source directory we can see that we have an app.test.js and we can see here that well react has actually written our first test and don't worry about this we will get to all of the syntax in great great detail but we can actually go ahead and run this test when if we can open up a brand new terminal and we can do something like npm run test now why do we do npm run test again if we go to our package.json we can see that we have a test script and this is essentially going to test all of the uh all of the tests inside of our application it's going to run all of the tests inside of our application now how is it going to know well which uh where our tests are located inside of our application well inside of our source directory any file that is appended dot test dot js is going to be treated as a test file and is going to be executed so right now it is going to execute app.test.js but if we were to create another test another file called um you know lathe.test.js it will also execute that and it doesn't have to be in the root directory it just has to be somewhere inside of the source directory so let's go ahead and let's run this test and we should in a second see that our first test is passing and essentially what this test is doing is it's saying that hey learn react should be located somewhere inside of well the app right over here so let's actually go ahead and let's manipulate this let's do app.js and let's just say instead of learn react we'll say learn view and then if we now run this exact same test we can actually see that the test is failing so this is our first initial test we're actually going to delete this and kind of do this from scratch but this is how we can set up our react app and we can actually run our test and it's great that react testing library comes right off the gate if you do create react app so this is basically what we have right now let's actually do a little bit of cleanup so we can have something somewhat similar to what we have over here so the first thing that i want to do is i want to just completely get rid of this test right over here because we don't need this anymore so we can actually remove this and now if we go ahead and you can see here it looks for changes and now it's saying hey there's no test that that exists because there is no files with the dot test extension and let's just do a little bit more clean up let's just get rid of this svg this logo.svg let's remove that let's go to the app.js let's remove the import for the lo the svg we'll leave the css because we're going to use that a little bit later and then we can just completely get rid of all of the elements within this and now what we have is pretty much a bare bone html or react application literally nothing which is kind of similar to what we have here all we have additionally is this component so that is a good setup let's actually go on to the next section where we are going to be creating our first test and implementing our app so let's go about and write out our very first test now the very first feature that we are testing is a very very simple one essentially we want to basically have a header over here saying my counter and we want to test that that header exists and it has the correct content so essentially that is the very first thing that we want to do we essentially basically want this header to display right over here and we want to test if it exists and it contains the correct content now for this very very first feature we are not going to follow a test driven development approach we're actually going to create it and then we are going to test it and the reason for this is because this is our very first test i want to quickly introduce all of the terminology and all of the imports and all the things of that nature first and then after we have a good grasp of that for every other future we are going to follow a test driven development approach so let's actually go ahead and do this right about now so the first thing that we want to do is we want to go to our source directory and create our component so in here i'm going to create a new folder called counter and then in here i'm going to create a counter oops a file called counter dot oops again counter dot jsx now you can either use js or jsx it doesn't matter and then what we can do is we want to create make this basically some sort of functional component so we can go ahead and copy our app component and we can paste it in there and we can get rid of the app css and instead do an import react from react so we can import react from react let's make sure i spell react correctly and then what we can do is we can change this to counter we can also change this over here to counter we can get rid of this class name so we can get rid of this class name and then over here let's just create an h1 and then over here we have my counter and now let's render this on our app.js so let's go ahead and let's import counter from dot slash counter and then counter.jsx so let's go ahead and let's render our counter component and there we go we can see our counter now this is a little bit big so let's actually change this to an h2 let's save that okay there we go it looks close enough actually let's change it to an h3 just uh just to make the styles work a little bit better okay there we go so we created this and essentially we just manually tested this we saw that it works let's actually go about and create an automated test for this now for things like this it might not even be needed to write tests but let's do this just for some just so we can actually introduce tests and how we can go ahead and write them so to write tests if you want to test a specific component what we can do is we go to that folder where the component is housed and we create another folder known as underscore underscore test underscore underscore and then in here we create the test basically the test file is going to test this specific component so this is going to be counter.test.js now if we go ahead and create it you can see that now our test suite is basically running that basically all of the tests in this file now this file doesn't contain any tests and that's why we have a fail it says that your test suite must contain at least one test and well over here it doesn't so let's go about and let's essentially do everything that we need let's do all the boilerplates to write our very first test so the first thing that we need to import is well react from react and the reason for this is because we are testing a react component and while we need react to be able to test a react component so over here we are going to get react from react and then we want to basically get the component that we want to test so over here this is going to be the counter component and so this is going to be in the dot dot slash counter directory right over here so this is the component that we want to test now the next thing is essentially we want to be able to render the component in some sort of virtual dom so essentially every single time our react suites are are ran that component is rendered on some sort of virtual dom and essentially then any kind of then all for the tests will be executed based on that virtual dom now to be able to uh render our tests in a virtual dom we basically need a method known as render from at testing library dash react now again if you created your app with create react app you can go to your package.json and you can see that well we have this already so there we go so now the last thing that we have to import is something that is very known to just known as the expect keyword and we'll actually see what this does in a moment but just just take my word for it we need to import this so over here we can do something like at testing library dash extend expect so this will allow us to use the expect keyword and we'll see exactly what this does in a moment so let's go ahead and let's write out our first test now if we want to write out our test we have to specify the test keyword and this is a function that is going to be executed now in here we can basically pass two parameters so the first parameter is a string symbolizing essentially or or rather describing what the test is doing so our first test is basically testing if well this exists so essentially we're going to say header renders correctly with correct or header renders with correct text that's going to be describing our text and then the second parameter is going to be basically a function that is going to have all the logic for our test so this is where we're going to have most of our logic or actually all of our logic so let's go about and let's do this so the first thing that we have to do is we actually have to render this component right over here our counter component and we can basically get that using the render method over here so let's go ahead and let's say const component is equal to render and we want to render our counter component so there we go we went ahead and we rendered it and now what we want to do is now that this component is rendered in our virtual dom we basically want to check if this element over here contains basically the text of my counter now there's multiple different ways that we can get a specific element and to actually see them you can do something like component dot get by and you can see all of the different ways that we can get a specific element you can see here we can get by alt text we can get by text we can get by role we can get by title we can get by element there's multiple different ways but the absolute best approach is to actually go to the component and give the component that we want to test a specific id known as a data test id so we can give this a data test id and we can call this data test id let's say header and now we can save this and then over here we can say i want to essentially get the component by test id and well what is that test id well that id is the header so now what we can do is we can do something like const header element is equal to component dot get by test id and what test id bull do we want to get we want to get the header so now what we can do is we can assert some sort of test and we do this with the expect keyword and again expect this is why we did this import over here so we can use the expect so now what we can say is that hey i expect that the header element dot text content so basically this element over here it's text content and i expect that to be so to be and this is outside of the expect i expect it to be my counter so we can paste that in there so i expect it to be my counter and if i go ahead and run this you can see that it successfully passes now if i change this to say let's say i make some sort of mistake and i say instead of my i misspelled counter we can save this and now scooter and you can see here that it's failing and it actually tells us exactly what is failing it's saying hey i expected counter but instead i got cooter and you can see here that uh uh we're missing an n so it's specifically telling us that we're missing an n so we can go ahead and we can update that because we ran our tests successfully and there we go we have ran our very first successful test now let's just do a little bit of cleaning up so over here you can see what we're doing is we're doing component is equal to uh this over here and then we're not using component itself but we're using a method inside of component known as get by test id so instead of doing component dot get by test id what we can simply do is just destructure out get by test id so we can just destructure out get by test id and we can just get rid of this component over here and then we can go ahead and save this and it should execute just fine all right so that is our very first test i hope that kind of explains all of the imports in the next sections we are going to actually go ahead and code out this entire application following a test driven development approach all right so now let's do a little bit more testing for this section all we're going to do is just essentially create all of the elements that's what we want to do and we want to make sure that they render correctly with the correct values so we are going to follow a test driven approach for this so let's go ahead and let's write a test for this over here so essentially we are going to expect this value right over here and initially we're going to also expect this value to be zero so this is our counter let's write our very first test for this so let's go ahead and we're going to say test and we can basically say counter initially starts at zero so initially starts with text of zero so this is our first test this is going to be our second test rather this is the description of that test and essentially over here we're going to go ahead and write out this test in the test driven development approach so the first thing that we want to do is we want to do const and we want to essentially get by test id and we want to render our component so for each test it is going to re-render the component and so we're going to render this component and then we essentially want to get the element that contains that counter now again over here we haven't created it but let's say we create when we create it we're going to give it a test id of counter so we can say something like const counter element is equal to get by test id of counter and then what we can do is something very similar we expect the counter element dot text content to b to b and we expect that to be zero initially so there we go now we can pass or we can run this test and this test should pass but this one should fail and over here you can see here that this fails and the reason why it fails it says hey i don't have an element called counter this makes sense because well we haven't created this yet we are again following a test driven approach so let's go ahead and now let's create basically the tests for this over here so for these kind of buttons right over here so essentially let's begin with the input so we want to basically say that the input exists and its initial value is one you can see here that initially it starts off at one so let's write a test for this so we're going to say test dot input contains initial value of one so that's that's basically what that is and just to kind of prove that to you if i refresh this page you can see it initially starts off as one this isn't a placeholder this is an actual text or actual value so we can say something like this we can let's let's go ahead and let's do const get element by id again we want to render our dom so we or we want to render our component our counter component and then let's go ahead and let's get the input element again we haven't created this yet but let's assume that we give it a a test id of just simply input so we can say input element is equal to get by test id of uh input and then over here we're gonna have an expect and over here what we're gonna do is something a little bit different now you can fall into the trap and say okay input dot element dot text content to be one so you can actually fall into this trap but however you have to understand that e e input doesn't contain text content it actually contains values so instead of text content what we do is input element dot value so just dot value to be one again let's go ahead and let's save this again both of them should fail so now let's just do um let's just do these buttons right over here so let's uh or of course we want to write the tests for these so let's say um add button renders with with correct uh uh text or or we can say it it renders with plus sign so let's go ahead and let's do that and then over here let's actually just copy and paste this over here because it seems like we're doing this for every single test now if if there are certain things that are similar with every single test there's actually approach that we can do uh that basically kind of minimizes the repetitive code we'll talk about that a little bit later but for now we'll just do it this way so we can say add btn and we can say get by test id and let's say we have an element with a test id of add btn and let's actually change this to add button and let's change this to add dash btn and then over here we're just going to assert that we expect that the add btn.textcontent to be a plus and now we can do the exact same thing for our subtract so let's just copy this and then over here we can just say subtract and this is minus and then over here we can say sub tract so this is going to be add subtract now of course over here we have to change this to subtract and over here we're going to expect that the subtract btn dot text content to be a minus so there we go we have basically created all of the tests and now you can see that four tests were failing and then one test is passing and this is actually this kind of methodology is known as red green testing and essentially that's because hey we're getting a bunch of red tests and then we want to uh write out our functionality so that you know they can go from red to green so let's go ahead and let's write out our functionality to make these tests pass the first thing that we want to do is let's go ahead and let's make this test pass over here so in here we can basically create an h2 and this is going to have an initial value of zero so let's do a class name and then let's do something like uh or actually not a class name let's do data test id and remember this data test id is going to be of counter now this is this value over here is always going to change so it's actually better that we put this in a state right away so let's go over here and let's import uh use state so use state we're just gonna say const uh counter value and then over here we're gonna say set counter value this is basic react i do expect you to know this counter value and then over here we can do use state and initially we can set that as zero so over here what we can do is we can basically have that over here the counter value which is initially zero so if we save this theoretically now we should have two passing tests and that's exactly what we have all right so that is that first one let's actually make the rest of the tests pass so now let's create a button uh let's create a subtract button first so over here this is a subtract button with a minus let's give this a data test id of uh subtract vtn let's make sure that the naming is absolutely correct or add subtract okay see that's not not good let's change this to subtract btn and let's copy that and then let's paste that in there so subtract btn and then uh well that's pretty much it so now we can actually save this and we should expect our another test to pass okay cool so now we can do the exact same thing but with add this time so we can add add dtn cool so now we should have another test passing and now we let's go ahead and let's create a input and this is going to be of type number and then let's also give this a data test id of well i think it we called it input all right so we're going to give this a data test id of input now let's just make sure that that's exactly what we called it input now it's failing and the reason why it's failing is well we expected this to be one but initially it's nothing and if you actually go back over here we can see that it's completely nothing so now what we have to do is we have to basically pass in some sort of value now this value can always change so it's actually again a better practice to use some sort of a hook a used state hook so we can say that the input value so the input value and we can basically set the input value set the input value and that can be equal to use state and initially it's going to be equal to 1. and so now we can go ahead and we can basically pass that in there and now we should have all of our tests passing that was from some previous error that we had but there we go now all of our tests are passing so there we go we have it now one thing that i do want to change is well i want to make the text content of this to be right in the middle so simply to do that all we have to do is we can just add a counter dot css file and then we can say something like text center and we can do text align center we can import that css file into this component let's do a counter dot css and let's say here we're going to give this a class is getting a little busy let's actually make this multiple lines and then we'll just say class name of text center it's kind of like a bootstrap class so now if you save this this shouldn't reflect any of our testing but just for styling purposes that's how we have it okay so that is pretty much it so now in the next section let's actually make this functional because right now we can't really do anything nothing is happening we can't even change the value because it's actually fixated at one so there's actually multiple things that we have to do to make this completely functional and we're going to get to that in the next section so far this is what we have created and right now it is completely in functional we can't add we can't subtract we also can't even change the input value but basically all that we did thus far is create the ui elements and essentially tested that the initial renders are correct like you know this initially rendered with zero this initially rendered with a value of one but now let's actually go ahead and let's go and write the tests for the functionality of this right over here so for instance you know when we click this we should expect this to go up if we change the value to six we do expect it to go up or go up by six we also would expect it to go down by six and things of that nature so let's actually go about testing this now there's multiple things that we would have to do and so let's actually break them down into multiple little tests the first thing that we absolutely need is well we need to be able to change this value right over here so let's actually go ahead and let's just write a test saying that hey e person is able to change this value to well whatever the value is so if i were to change this to say um nine well i'm able to change it to nine and then that value over here for this element is nine so let's write e test for that right now so let's go ahead and let's do this so let's go to our test and then we can say well we want to write a test we want to say changing value of input works correctly so that's going to be just describing our test so over here let's go ahead and let's actually just copy this so we're gonna basically again render our uh component our counter component and let's basically get our let's get our input element now we actually already created this uh over here so remember we created it and we gave it a data test id of input so let's actually go ahead and get it so let's do const input element is equal to uh this is going to be a get by test id of input element or just of input on its own so input so now what we want to do is we want to well trigger some sort of event so now we don't just want to see um you know whether this component exists or whether this component initially has a value now we actually want to well implement some sort of event some sort of change and what is this event well we want to be able to essentially change this value from one to let's say five or six or whatever now how do we kind of do this in a testing environment well we can do this by going over here and getting a new uh method known as a fire event and well this right here initially well really all it does is it fires a specific event so let's actually go ahead and use it and it'll be really clear how this works so we can do fire event and then we can basically append what event that we want to fire so over here we have like different types of events we have a click event a copy event whatever a drag event so there's multiple different types of events we're not going to focus on all of them actually we're only going to focus on two but there's multiple different events that you can use now the event that we are going to use is the change event so essentially what we want to do is we want to change this value from 1 to something else so that is the event that we are going to use the change event so let's go ahead and we're going to call this and then we're going to basically specify essentially uh um the the uh input element that we want to change so what is this input element well this is the this input element right over here so essentially we want to change this input element so we can basically paste it and then what do we want to change about it well we want to change its value now remember if we ever wanted to extract a value of an input element it would look something like this e e dot target dot value so e.target.value so essentially what we want to do is we want to change the target and then we want to change that value to let's say five so we want to change that value to five and so once we fire this event what we basically can do now is we can basically expect that the input element dot value dot value uh to be well five so now if we actually go ahead and execute this well it's going to fail because right now we actually can't change the value to 5 and that's why it's failing another thing that we can actually do is we can have multiple expect statements so we can basically have an expect statement right over here and we can basically say that initially we expect it to be one and then over here we expect it after we fire our event we expect it to be five now this is all still going to fail because well we can't really change our uh our functionality at this moment because we can't change our input it's basically stuck at one so there we go we have created this very first test so let's actually go ahead and we'll in a test driven approach let's actually fix it and let's make this functional so this is very very easy to make this functional all we really have to do is say on change on change let's call a function and this function is going to basically take the e right over here and we're essentially going to set the input value to whatever e dot target dot value is so let's go ahead and save this and now you can see that our test passed okay cool so now let's work on another piece of functionality so now we can actually do this and it changes appropriately so now let's work at another piece of functionality now let's say that when i click the plus button it should reflect on the counter over here so let's go ahead and let's write a test for this so so let's go here and let's say clicking on uh plus button button adds one two counter so adds one to counter then over here let's have our function similarly let's take this over here let's paste that in there and then what are we doing well this time we need the uh the the button element so we can say button btn element is equal to get by test id so we can get by test id and this is uh i forgot what this was called i believe it's called add btn let's double check yes add btn okay cool so now we can get it and now we want to fire an event now what event is this going to be well it's going to be a dot click event and essentially all we really have to pass here is what element that we want to click well we want to click the button all right so once we click this what do we expect well we expect that the counter element is now now has a text value of one because initially it starts off as zero when i click this button it should be one let's actually go to the actual version right over here let's change this to one which is what it was initially and when i click this now this should be one so let's go ahead and let's write a test for this now before we do this we actually have to get the counter element so we can say const counter element is equal get by test id of um what is this called again counter i believe and now what we can say is we can say that hey i expect i expect that the counter element dot text content to be one so i expect it to be one so we can also have over here that i initially expect it to be zero and then after i click this button i expect it to be one again if i run this test it is going to completely fail because well that functionality isn't it isn't doing anything right now you can see why it fails right now it's saying hey you expected one but we received zero so let's actually go ahead and let's write the exact same test but for the minus and this is basically going to be pretty much a copy and paste so click on the subtract btn subtracts one from the counter and so let's just change this to subtract and we want to get well i guess we can maybe a better name for this would be add button element and so let's actually change this over here add button element and there we go and over here this should be subtract button element and then we can actually go ahead and we can paste this and over here we expect it to be negative one so let's actually save that and now if we run this we can see that now we have two tests that are failing so yeah two tests are failing and the reason why this one is failing is because well we expected negative one and we got zero so now let's go ahead and let's actually create the logic that makes this thing pass so let's go about doing that so this is going to be relatively easy as well so let's let's begin with the add button actually which is over here so over here we're gonna say okay we need an event listener some on click we're gonna call a function called add to counter okay so that is the function that we are going to call so now what we can do is essentially let's just add this function so const add to counter this is a arrow function and essentially this is basically going to add this is going to add um whatever whatever the so so the new counter value is going to be whatever the current counter value is plus the input value remember the input value could be 1 or it could be 100 or it could be whatever so now let's say that hey set imp or set counter value to be counter value plus input value and so now we should see our ad our ad actually work so let's let's go ahead and do this so we should see the one test pass and over here you can see that it indeed does pass so let's actually do another one so now let's do over here let's do subtract from counter and this is going to be minus and so now let's actually go ahead and let's on click with this over here so on click on click we can basically call this function and now if we go ahead and run this our test all should be passing all right this is terrific now there's another test that we need to implement what if we went ahead and we changed the value from uh from one to something else like let's say we changed the value to seven and then we added it now you can see here that it is actually failing so let's actually go ahead and write this test and we're gonna see that this actually fails and we're gonna see why it fails and how we can fix it and this is actually a really good way to see how why testing is is really important so let's just copy this exact same test let's actually copy the add test and this is going to be let's let's make this a little bit bigger there we go and so we're going to basically have a similar test so we're going to say change input value and click on add button um or you know what let's just rewrite the whole thing so changing input value then clicking on add button works correctly let's say so this works correctly so what do we want to do here well we have our add button we have our counter we also need the input element in this point so we have the input element and then we can get by test id of that specific element now what we want to do initially is let's get rid of this other expect so now we want to fire another event so this is going to be a change event and essentially we want to change the input element we want to change its target and we want to change its value to let's say five now once i change it to five i then click on the button and then i expect it to be five so let's actually go ahead and save this and then you can see that this will strangely fails now you can see here that well okay we expected five but we got zero five five and if we actually go ahead and do this well that's exactly what we get we have zero five five so this is wow what is going on here this is really really strange and the reason why this is happening is because over here what's happening is e.target e.target.value is actually going to be the string of five so really what's happening is string concatenation so we're basically adding zero the number to five the string so what it gives us instead is o five 0505 the uh the string now the reason why this didn't happen in the initial get-go was because one was actually the number one and we can actually see that over here this was actually the number one if i change this to the string five we can see it would have been one so it was initially the number one and this is actually why typescript is is so powerful this is kind of a form of static testing right over here uh but uh but we'll talk about that maybe in a different crash course now to fix this all we really have to do is basically say that hey you know this we want to parse it as an integer we don't want to parse it as a string so we can say parse int and we can do that similarly um you can do that similarly with the oh i think that i think that's it actually so that's it so we can just parse it as an integer and now if i change this to five you can see it should be five and how all of our tests are passing okay cool so let's actually do uh essentially the exact same test but for subtraction so we have to do this for subtraction as well for every single test and the reason why i'm i'm doing these kind of like repetitive tests is because well this is really how in a real production application we are going to be testing our app so let's do subtract so this there's multiple different features over here subtract and then and then over here we want to change this to 5 still but this time we expect it to be negative 5 and we want to click on the subtract button this time so if we save this we should have this test pass there we go okay now one other thing that we want to test is we want to be able to test okay well we can click on it once and it changes so let's actually go back over here so let's say we change this to five and we click on it once and it changes we also want to make sure that if we you know click on it again you know it changes again so we can maybe want to click on it multiple times and then it can change and sometimes maybe another thing that we would want to test is hey if we clicked on this a few times and then we clicked on this a few times that's something that we want to test now we can test that with multiple fire events now i'm not sure if i actually want to go about doing that let's actually do it for one but there's actually multiple different variations of these tests that we that we can write so let's go ahead and let's just test that um you know adding and then subtracting leads to the correct counter number okay so let's quickly do this test right over here and over here let's just quickly copy and paste these right here just so we can get our elements and let's also get the add element so the add button element right here our add button element so over here we're gonna probably want to fire a few events so the first event let's say that we want to fire is the change event on the input element and essentially we want to basically change oh oops this shouldn't be uh this should be an object we want to basically change it's i'm missing some parentheses let's see okay this should be an object and we want to basically change its target value to 5 or you know what to 10 this time and so now let's say that we want to let's say we want to click on the add button three times and then we want to click or let's say the add button four times and then two times on the subtract button we should theoretically get 20 in this case because we clicked on this four times so we should have uh 40 and then we basically uh um click on the subtract button twice so we should get 20. so now we can actually do a bunch of different expects so we can do something like fire and then we want to do a click so we want to do a fire and then dot click and then we can do something like well we want to click the add button so the add button we can also put this in a loop but for for simplicity's sake i'm just going to have four add buttons and then a few subtract buttons as well so let's let's do that so now a few clicks of the subtract buttons and then we can say that hey i expect the that the counter element dot text content to be 20. so we can actually go ahead and execute this and this passes now what we can do is we can actually append a bunch of other other expects so let's say that you know what now what we want to do is after we do after we do this let's say we want to change this back to five and then we want to execute uh maybe this over here again so maybe let's say we want to add uh add it once and then subtract it a few more times so over here it should be 20 20 plus 5 is 25 and then minus 5 minus 5 so this should be 15. so we can actually now append another test saying hey now i expect this to be 15. so first i expected it to be 20 and then i expected it to be 15. now with these multiple expects if any one of them fails the whole test fails so if i if i were to change this to 221 you can see here that the whole test would actually end up failing and it says hey we expected 20 but we got 21. so there we go that is pretty much that the absolute last thing that we need to test is basically once we get to over a hundred we want uh the color to be red so over here you can see here let's let's make this 90. so you can see here or sorry the color to be green if we're over 100 and if we're under 100 we want it or under negative 100 or add negative 100 we want it to be red so that is the last little feature that we need for our our application and then we are completely done now how first of all we have to think about how we want to implement this well let's actually implement this by having a kind of dynamic class name so essentially if a value is over a hundred or at 100 or over 100 we're gonna give the counter a class name of green and this is basically going to have a class like this so let's actually write that down right now so essentially here we're going to have a class known as green and this essentially is going to basically have a styles of the color green and then we're also going to have a class of red and this is going to have color red so essentially if the counter is over 100 at or over 100 we're going to give it this class or if it's at or under negative 100 we're going to give it this class so let's actually write a test that basically tests this out right over here uh let's go ahead so how do we do this well let's do test let's say counter contains correct uh class name so we can do something like this so the first thing is we need to get the counter element of course after we go ahead and we render our components so we have to go ahead and render it and then we have to do const counter element is equal to well render or sorry get by test id of counter so this is that now initially let's write a test that basically tests that hey this doesn't have anything inside of his class it's completely empty uh if if um so right here where is this so our basically our counter should not have anything inside of its class name it should be completely empty if if uh basically our uh our if we initially basically render our component which is basically you know the number is in between uh negative 100 and 100. so you can basically do something like expect and we expect that the counter element and there's a special keyword dot class name we can just say to be empty so now we can actually go ahead and execute this test and as you can see everything passes perfectly because well initially it is empty now let's say that we fire a few events so let's let's go ahead and let's change the input value to like 50. so let's change it to 50 and let's go ahead and test that hey the the input value at this point should still be or the class the class name should still be empty because at this point we're at 50 and we're not over 100 or under negative 100. so this is another test that we can do and then let's go ahead oh something failed over here uh so counter contains correct class name uh oh yeah so saying input element is not defined that was the error so let's go ahead and let's just copy that in there because we don't have it in there so let's let's go ahead so to the two so actually what we have to do is you have to change the input element and then we also have to um uh add or click the button i actually completely forgot that as well so let's let's just copy out the add buttons as well and the subtract buttons and then over here what we'll do is we'll after we change the input value what we can do is we can fire an event and this event is basically going to be a click event and then we're going to click on the add btn alright so now everything still should be perfectly fine now let's say we went ahead and we clicked it again now we actually expect this because now we're at 100. we actually expect this to be green so we can actually save this event and then let's say we went ahead and you can see now it fails because hey we expect a green but we got nothing and now let's say we click this on this again we also expect this to remain green because now we're at 150 so now we can basically test if we continuously increase uh is it going to be green or not and now what we can start doing is maybe we can start clicking on the subtract button so let's say we click on the subtract button twice and at this point we should be at 50 so subtract elements oops subtract subtract so at this point we should be at 50. so now what we should expect is basically this to be completely empty and then let's say we click on this thing twice more at this point we're at negative 50. let's actually click on this um four more times so we're at like negative 150 and over here we expect this to be red so there we go that is a very long and relatively complicated test now this is again still failing and this is because well we haven't written out the functionality for it yet so let's go ahead and write out the functionality the functionality should be relatively easy actually so let's go ahead over here and we are going to give this a specific class name so so over here let's give it a class name we're just going to give it a class name and this is going to be with template literals so we're going to say that hey if so this is going to be with template literals so we're going to say that if the so if the counter so if the or sorry yeah if the counter value is greater or equal to 100 so if the counter value is greater than so if the counter value is greater than or equal to 100 then what we want to do is we want to give you the class of green else we want to give you nothing now we can actually do the exact same thing right over here but now we can basically say hey is it less than or equal to a negative 100 then we want this to be red or nothing so now if we go ahead and we actually save this that big test is actually passing so now we can go ahead and you can see here that this actually is working so now we can let's let's change this to 70 72 now it's green and then and then 70 over here and this is negative so that is terrific and that is pretty oh this is actually looking at the the actual complete version but as you can see this version also works as well so let's actually change this to like 40 and we can see here negative 100 okay so awesome so this is a great introduction that is pretty much it for this crash course i hope this kind of makes sense there's one more thing that we want i want to quickly discuss but this is pretty much it really this this is all that we're doing with react testing library now this is kind of really scratching the bare bones of react testing library if you want to learn more there's a lot of documentation about testing specific applications but i think like this is the approach that you're going to be taking so that is pretty much this now the one last thing that i want to discuss and we'll discuss this in the next section is you can see here that there's for each test there's kind of a repetitive amount of code you can see here that here we have a repetitive amount of code here we have a repetitive amount of code so how can we basically kind of alleviate this repetition we'll get to that in the next section okay so so far we have completely finished our test suite but there's just a little bit of a problem you can see that before each test we have essentially this kind of repetitive code right over here and we want to somehow alleviate this because well we want to keep our test as dry as possible now to do this what we can do is we can run a specific piece of functionality that runs before each test and this is actually kind of a special function known as before each well because this is running before each test and what's great about is we don't have to import anything just completely understands what this is supposed to do and it's going to basically execute this before each test now what is it going to execute well inside of it we are going to create an error function that basically contains the logic that it is going to uh essentially execute before each test so let's say that now what we can do is we can do something like this we can basically copy this and just paste it in there and then we can basically try to get access to the get by test id element for each test without actually having to render it because while we do it before each test now let's actually try to get access to the get by test id element so basically our test can look a little something like this now the problem with this is right now we can't really access the get by test id within each test because of well javascript scoping this right here is within its own scope and this right here is within its own scope so what we can do actually is we can basically do in the global scope something like this we can say okay get by test id and then in here what we can do is instead of destructuring we can say element so we want the or sorry we want the component itself and then we can say that hey get by test id is equal to the component dot get by test id function or method so now what we can do is we can actually completely get rid of this line for each code or each each test because well we're pretty much doing this before each function before each test execution so we can get rid of that let's get rid of all of these and let's get rid of this and a few more i think we're done okay cool so now if we actually go ahead and save this theoretically it should still be working and it is so over here you can see that the before each is basically a predefined set of code that is going to run before each function and this is actually a lot a lot more useful than actually keeping our code dry let's say we want to test some component but before we test it we actually have to let's say log in or something of that nature so maybe what we can do is we can actually add the logic here of logging in so we can basically you know have some sort of event a handler that goes on the input and it changes it to a username and then event handler that changes it to on the input of a password and adds the password and then maybe we can have an event handler a fire event that clicks on the login and then we're able to specifically test that component so we can actually have we can actually fire events but for now we'll just keep it simple and we'll just use it to keep our code dry now another thing is there's actually another function known as after each so after each is basically a function that runs after each uh after each test is executed and what is actually typically done here is after each we have this function called cleanup that we can get and we can actually go ahead and execute this and essentially what this does is it cleans up all of the doms in our in our react tree that we render after each test now what actually happens is is that this actually gets executed by default so we don't necessarily have to specify this this cleanup gets specified by default if we create a react app so we don't really have to specify this now there's also another one called after all so this is maybe if you want to execute something after all of our tests have ran so this is another function that we can execute i don't know if there's a before all that doesn't really make any sense i guess there is so i guess before all the tests are executed we want to execute something once so we go ahead and we we do the before all so those are just different features and that right there kind of summarizes react testing library i hope this crash course was informative
Info
Channel: Laith Harb
Views: 34,059
Rating: 4.9611335 out of 5
Keywords:
Id: GLSSRtnNY0g
Channel Id: undefined
Length: 76min 51sec (4611 seconds)
Published: Sun Feb 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.