Vue Testing with Vue Test Utils

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody welcome back to this channel in this video i'm going to be covering this view testing so we're going to learn how we can test out our view application whether it's a component whether it's multiple components interacting together and really just our whole view application as a whole so we're gonna learn how to test it we're gonna learn the good practices of testing our view application and to do this of course what we're going to need to utilize is some sort of testing library and the most popular view testing library and actually the official unit testing library of view is view test utils and this is really really popular and for a good reason it's really easy to use it's very very effective it's very intuitive i think you guys once use it you guys are going to fall in love with it and so that's what we're going to be utilizing to test out our view applications now i just want to note that under the hood this is using another testing library called jest this is a by far one of the most popular javascript testing libraries it was developed by facebook and it is also very very easy to use and very very effective i actually do have a crash course just purely on jest if you want to take it but a lot of the testing libraries like react testing library is using just under the hood so you don't need to know jest for this but you will know just after taking this crash course because well it's using it under the hood so that's what we're going to be doing and hopefully you guys find this very informative now to do this let's actually just set up our view application and let's install view test utils within it so to do this what we're going to need to do is go inside of our terminal now move into whatever directory that you want i'm just going to move into my desktop directory and in here the first thing that we need to do is create a view application now to do this i like to use the view cli so to use the view cli what we're going to do is just say view create and then we're going to create our application i'm going to call this testing tut now if you don't have view installed and i do expect you to have view knowledge if you're taking this crash course being that this is a view testing i'm not going to be explaining view to you i'm going to explain how to test things to you but you may not have the view cli installed so to install the vue cli you have to just do this command right over here so just do sudo then this is going to be really dependent if you're on a mac or linux machine so if you're on a mac or linux you're probably going to have to do sudo and then if you're on windows you can probably get away with it and then over here you could just do mpm install and then with the g flag meaning that where it's global and then at view underscore cli so go ahead and do this go ahead and install this because we're not only going to create a review application using the cli we're also going to add the testing framework using that cli so again the command to create a uh a view application is view create testing tut so let's go ahead and let's create this and it's going to oh it shouldn't really give you this let's just do i already already created this just to speed things up so i'm just going to add an extra t just so you guys see what uh just so you guys can see here you should get this uh drop down over here and then you're asked hey do you want to use view 2 view 3 or manually select the future select view three and what this should do is go ahead and start installing things you can see i already have a package here i'm gonna go ahead and delete it uh because this this command does take quite a lot while to run i already installed it but once you once this command's done you should have a view application up and running so what i'm going to do is i'm going to move into that view application and i'm going to do code dot and what this is going to allow me to do is open up this directory inside of vs code i set it up so that it does that it might not do it for you if you're utilizing vs code maybe you can do a quick search on the internet to see how you can do it uh but if you're not even using vs code then just open it up in whatever text editor that you're using or you can just open up vs code and just uh manually uh move into this directory so i'm going to go here i'm going to open this up and you can see here like i get a very simple like boilerplate view application so you can see here we have the source directory we have a logo probably the view logo we have a component here hello world you know just a lot of stuff going on here and over here we have our app file so we have our app file and right now i'm actually running it so let me just quickly close it and to run it let's just go to our package.json and over here we can see here to run our application we have to run serve so we're going to do inside of our integrated terminal or if you're using some other editor just go back to this terminal here let's do npm run serve so we're going to do an npm run serve sorry i just had to reset my terminal because i already ran this before and now you can see that our application is up and running on localhost 880. so now what we can do is we can just go to localhost 880 and we have this very boilerplate application over here so we're saying welcome to your view app which is to all terrific we are finally welcome to our view app so now what we want to do is well we want to test our application and if you look at all of our dependencies you can see here that there's nothing really related to jest or that view testing utils library so the reason for this is because we have to add it so let's open up another terminal and to add this and really the best way of adding this is to use the cli because we actually it sets up a lot of things and it actually gives us a mock test that we can look at so over here we're going to do view and then add and then what we're going gonna say is unit jest so we're gonna say unit jest and this is going to add that library in for us so you can see here it's adding a bunch of things for us and this is actually the recommended way of adding it so let's just wait a little bit and if this takes a while probably just pause the video and i will not maybe it's getting closer i was just about to pause it but it is getting there we go it seems like it's it's there maybe i'll have to pause it i really don't want to all right let us wait and there we go awesome okay cool and i guess it's doing some more downloads but in the meanwhile you can see here that we get view test which is something that we get what we also really get is this really really cool test file over here and in here we have our unit test and it gives us this example test and this is kind of the structure that we're going to follow throughout our crash course and let's actually go back to the package.json let's actually copy this over here so i can try to find it in the package.json you can see here that we have added this test utils library and you can see here it's getting from at view which means it's really the official testing library of view so let's go over here to the spec file and we're not going to dissect it now we're going to dissect it in the next section but if you look at this test file we're really it's going to be each test is going to be very very very similar to this over here extremely similar to what's going on here maybe some tests are going to be a little bit more complicated but the premise of what's going on here and i'll explain in great detail what is going on here in the next section is what we are going to be doing for every single test we also get this really cool adjust.config and this is where we can actually configure jest because remember we're using jest under the hood and sometimes we want to configure it in different ways and we can actually do that inside of this file over here now the last thing that i want to note is let's go back to the package.json is now we have inside of the scripts directory we have this brand new test script over here so test a colon unit and what this is going to do is run our tests now actually what we have is one test right over here so we have this one test over here so let's actually go ahead inside of our terminal and let's run npm run test and then colon unit and what this is going to do is it's going to look for all of the test files inside of this directory and the test files have to follow this very specific format example which is the name of our test this can be anything but then dot spec and then dot js so let's go here and let's run this and you can see in a quick second it found this test file over here and and over here this is the name of the test again we'll talk about this later but over here each test has a name and then over here it's running the test and the test has passed and so that is how we're going to be running our tests now in a production application of course we're going to want to run it over here as well but we're also going to want to run it in ci and i just said this just for your information this is not something i will be doing and teaching you inside of this crash course maybe in a future crash course i'll show you how to set up some sort of ci with github actions or circle ci all right well that's awesome we have our application set up now let's start talking about the structure of this test file now that we have set up our application let's start looking at the test structure that we saw in that one test file so what i went ahead and did is i just copied and pasted that test inside of my presentation and we're going to go through every single line of code right now just so we can understand it because again like i said the structure that is going on here is going to be very very similar to the structure that will be going on in most of your other tests so for now let's just focus on this block right over here so from here to here so from here to here now this right here this right here this it statement is representing a test block and what this is is just a block that is going to test something within our component now what is it testing well we're going to describe exactly what we're testing inside of this test block as the first inside of the first parameter over here which is a string and over here this is just going to be description of what we're testing so here we're saying renders props dot message when it's passed so when we pass some sort of message prop it should render that message so that's what we are testing now we're gonna have to write the logic for our test where is that going to live well inside of the second parameter we're going to add a callback and inside of that callback that is where the logic is going to live so that right there is the test block we're going to represent a test block with it and then we're going to have a message saying hey what are we testing here and then we're going to have the callback that's going to have the logic for our test now we can have multiple test blocks in a file and that's extremely common it happens 99 of the time so we can have multiple it statements that test multiple things within our component all right so now let's actually move in within the test block so right here we have const messages equal to new message well this makes sense we're just we just have a variable here but here is where it gets a little bit interesting here we're telling our test exactly what component we want to test so we want to test this hello world component and we get this hello world component from our actual view file so our add components and then helloworld.view and this is the component that we want to test now in order to test it we need to mount it so we need to somehow render and mount it and to do this we're going to use this function right over here we can either we can either use shallow mount or just mount and i'll talk about the difference a little bit later here they're using shallow mount and what they're doing is they're calling shallow mount and they're passing the component and what that does is it creates a wrapper and i don't want to confuse you guys you can just think of a wrapper as an object that contains multiple different methods and properties that is going to be related to that specific component and we'll actually look at one a little bit right later but really we're just mounting it and we're returning a wrapper which is an object that contains a lot of properties and methods that contains a lot of different information about the component that we mounted now as the second parameter we also passed in the prop so we over here we have an object and over here we have passed in the props and then which is the message as you can see here we have the message here so we passed in the props for this component again we went ahead and we also uh mounted it and wrapped it over here and so once we're done this now what we want to do is well we want to test the components we want to test if it works properly in this case we want to make sure that hey this message new message actually appears in this component when i pass it as a prop well that is the job of the assertion so this is the job of the assertion so here what's happening is we're saying expect and then we're expecting the wrapper remember the wrapper is an object that contains properties and methods related to that component one of the methods it's dot text and so this is gonna get all of the text inside of that component don't worry we'll look at all of the different methods a little bit later over here we have wrapper dot text and then over here we have two match and then well to match message which basically means here that the the text all of the text within this component it has to at least match new message so meaning new message should be in there somewhere is what we're saying and this right here is an assertion so we're expecting that the text inside of this inside of this uh component to match this and this is either going to return true or false if it returns false then it's going to go ahead and fail if it returns true then it's going to pass so that right there is really it that is pretty much it it's not that difficult now let's just quickly talk about this describe over here so this is the tests so plural block so this is where we can group multiple tests together in a test file it is not uncommon to have hundreds of tests within it and sometimes what we want to do is to group these uh tests together in a certain category so right now we have just one test so it kind of makes no sense but imagine if we had 10 tests five of which were testing a specific feature of the component and then another five we're testing the same component but kind of a completely separate feature well it might be good to actually group these tests somehow some way well we can do that through a describe block and the way that it works is very similar to the test block we have the string which is the message in this case the describe block is just saying hey we are testing the hello world.view but we can have something more descriptive in here of course and then we have this callback and then inside of the callback we have our tests we can have multiple tests within here and sometimes it's really really important to put things in a describe block or tests block for scoping but we'll talk about that a little bit later but now that you guys understand the premise of the tests file and how this looks like let's actually go ahead and start coding out some tests all right time to get right into it and write our very first test now for this very first test we're going to write a test that is extremely similar to the one that we just wrote except it's going to be for a brand new component that we have just created so let's go over here into our components directory and what i want to do is i want to create this message dot view component so let's go ahead and create that i'm going to go ahead and open up the hello world.view component and i'm just going to copy everything within here and you know what let me make this a little bit bigger for you guys and so let's just paste that in there and this is inside of the message.view component and let's just get rid of all this rubbish so let's go here let's get rid of all this junk let's leave the message over here we can even get rid of this class not really needed we can change this to message and then let's get rid of the styles so this is really very very boilerplate now let's do a very similar test where we are testing that if we pass it the prop of message then it should render that particular message so to do this let's go inside of here and inside of units what i like to do is call this message which is the name of the component dot spec dot js so right now we have our test file up and open now what do we need inside of our test file well we're going to need some things of course to test our component particularly we're going to need to mount our component so how what do we utilize to get that mount method well we're going to utilize that at view at view test utils and in the example it was shallow mount but for now i'm going to use mount and i'll explain the difference a little bit later but for now you can kind of think of them as the same thing they're doing the same thing they're mounting our component and creating a wrapper all right so that's the first thing but now well we want to mount what component well the message component so we need to import that message component and hopefully that's big enough for you guys let's just zoom in here a little bit so we're going to mount the message component from well at components and then slash message dot view all right awesome so now let us well create the structure of our test so with every test file we should probably have a describe block and we shouldn't have to import this describe block from anywhere because this is actually auto imported from jest and the first thing we're going to say is we're going to say message dot view because this is what we are testing and in here we're going to have our callback and then in here we're going to have our test so we're going to say it and then we're going to save something very similar renders the prop dot message when passed so the the message is exactly the same and actually the test is going to be pretty much exactly the same and so right now what we want to do is we want to well get the wrapper so that's the first thing that we want to do so let's say here const wrapper is equal to and well to get the wrapper we have to mount the components and then we also want to pass it some props so let's say props and this time we're not gonna uh make it a variable we're just gonna say props and we're gonna say hello friends so that is what we're gonna say and now what we want to do is okay we have mounted it we have gotten this wrapper ultimately now what we want to do is well we want to assert something so let's say here expect and what we want to do is we expect the wrapper dot and you can see here look at all the different properties and methods that we have we have a lot of things you have find all components find component unmount exists we have a bunch of things but in this case what we want to do is we want to get this text over here what this does is it gets all of the texts inside of our component and this is a method so we have to call it and so it's going to return all of the text inside of our component now what we can do here is then append a dot and then over here we have a bunch of matchers so these are a bunch of just matchers they're not specific to a view and we utilize these matchers in order to actually test our components now uh in the last example we used to match but in this case we can also use something like to contain and you can read about all of these different matchers inside of the jess documentation i'll have that linked in the description below i'm over here i'm going to say well i expect it to say hello friends and so let's go ahead and save this and now how do we execute this well we need to open up our terminal then in here we're gonna run npm run and then actually i forget to command let's go over here to package.json we're gonna say test colon unit so test colon unit we're gonna go ahead and execute this and you can see here that this is gonna be testing our uh our unit files which is right over here and you can see here that it has passed so we see here that it has actually tested this and you can see here that it tested it and we have two tests passing at the moment now let's go ahead and let's say for some odd reason let's say this actually close this to make it a little bit bigger for some odd reason uh you know we're manipulating this file we're doing something here and and for some other reason we remove this part right here so we remove the actual h1 and this is not something that we intended to do this was just by accident well this this is where tests come in to save the day so now we want to say we're done with the code we're happy with it or at least we think we're happy with it and we want to push it to we want to merge it to master we want to we want to deploy it well before we do that we should probably run our test just to make sure that everything works as expected so you run your tests and usually you do you do run it manually and also in ci and then you can see here that oh my goodness one test failed well what test is this well you see right here this is a test that failed message dot view and you can see here that it's expecting this but really it's just getting this and then you can kind of dissect it some more and then you can say oh okay you can either say oh this is a problem or you can say oh this is like an intended change but i forgot to update or remove the test so this is where tests come into place and and and really really help you so now we can go ahead and put this back let's say we do want it this was unintended we can go ahead and run this test suite everything passed and that's terrific now this is the very very simple component in the next sections let's go ahead and start testing some more complex ones great we have written our very first test but now let's actually start working with more complex components and so for the next few sections we're going to build a to do component and we're going to go ahead and test every single aspect of that to do component and consequently we're going to actually have multiple tests inside of our test file that pertain to that specific component so we're going to build this component from scratch and i'm actually just going to be following the view test utils documentation they have a quick crash course on this i'm going to be following that just in video format but if you ever need reference i'll have the link in the description below so let's just get rid of all these all these files over here and in here we're going to create a brand new component from scratch we're going to call this to do app dot view to make things nice and simple let's just get everything inside of the message component and paste it in there now for now we're not going to be rendering anything so let's just get rid of the h1 in here we're going to say that this is a to do app and instead of dealing with props we're going to be dealing with state so let's create a data method and inside of this data method what we want to do is return well some data so let's return and what we want to do is we want to return and i hate how it's not auto filling for me here but what we want to ultimately return is a list of to-do's so a list of to-do's over here and the array of to-do's is gonna be of objects and each to-do is gonna have an id so let's say our first to-do has an id of one our uh it should have also a text so over here uh we should have something well what what is it that we wanted to do well this is gonna be the text so maybe we want to learn view testing that's gonna be the the text and then it's going to have a completed status this is either going to be a false or a true value so this is our array of to-do's and eventually what we want to do is we want to iterate over this array and just render them inside of our review component so let's just give this a save and let me just clear my terminal really quickly and what i actually want to do here is i want to write a test for this and now what specifically do i want to test well i want to test that it actually renders this to do correctly and so to test that well when i render this component i should see this piece of text over here so let's actually go ahead and write the test right now but you might be thinking well this test is clearly going to fail because well we have the data we have our state in here but we're not doing anything with that state we're not iterating over the array and rendering components rendering elements and thus we should not see this text over here inside of this component and thus the test will fail well that's completely fine there's actually an approach in development called test driven development where you write your tests before you actually write your feature and therefore your tests are going to fail first so they're going to show up as red and then eventually you write your future you write the minimal amount of code to make your test pass and that's a very very common practice that is actually adopted by many great and reputable uh tech companies so that's what we're gonna do now i honestly don't really have a preference for test driven development or not test driven development i think we have to write tests for our components regardless whether we do it after we create the future or before sometimes it's just a preference but in this case i'm just gonna teach test driven development if you find that you like to write the feature first and then test it that's completely fine as well all right so let's go here and in the units let's create a to do app dot spec dot js all right and so in here we're going to create our first test so let's just we'll import some things we're going to import mount from at view utils test and then of course we have to import the to do app now let's just go to the tdo app did i miss anything in here no i didn't so let's go here let's just say from we're going to say at components and then to do app dot view very simple all right so now what we want to do is of course test so let's put this in a describe block oh my goodness i hate this auto import so we're going to say to do app dot view and then what we're going to do is we're going to have our test so we'll what are we testing well we're testing that it should render to do text so it should render the to-do text so we're gonna have our callback here and in here well the first thing that we want to do is of course get our wrapper so let's just very easily say const wrapper and this one's going to be very simple we're not going to have to pass in any props or anything and to do app now you could say okay well to finish this test off we can just say something like expect and we can say wrapper dot text so get all the text in the component and we can say you know dot to contain to contain um it should contain what we have here so learning view test this is a very common approach we could we could definitely do this however there's just a little bit of a problem here and let me quickly illustrate that by going through an example so let's say that our application is humongous very very large and a part of our application has this h1 this random h1 and it's maybe it's like maybe it's just like a commercial or something some sort of ad you know and it says hi i don't know i don't know how ads are i'm not in marketing hi let's let's uh learn view testing let's learn view testing now you know let's learn view testing now and then like in another part of our application that's where we actually have our to-do so let's say over here this is like not the ad inside of this div this is where we actually have our to-do's so maybe this can be like an li tag that has all of our to-do's so let's say we had let's go here and let's say we have i don't know clean house and then here pet cat and then here let's say we also have learn view testing so right now what we're doing is with this specific test over here we're testing that this that inside of our whole component there is some sort of text that has learn view testing so right now okay it's completely fine because our to-do is actually rendering but what if we in the future we make some changes and we accidentally don't render this list at all we something happens and we're not rendering this list and then you know of course we want to test out our application and we run this test and it actually is going to pass even though the functionality that we're testing for isn't really working and the reason for this is because we're looking at the component as a whole and we're looking for its text and we're seeing if it contains this piece of text over here and actually it does right here we have learned view testing so instead of testing the component as a whole what a much better approach is is find the specific element that we want to test inside of that component and then test it so we want to specifically find this element over here and just for simplicity's sake let's just get rid of this so we want to specifically find this element we don't care about the other elements we want to make sure that this li element has this text and therefore if this isn't present it's going to fail because well it's not looking for this h1 element it's looking for this li element now what's a good way that we can find elements well we can give elements specific ids so what we can actually do is do something like data test and we can say that this is equal to let's say to do so this right here is equal to do and what we can do is we can find this element by the data test id that is equal to to do and that's going to find this li element and then we can assert that the text inside of this element is learn view testing so i hope that makes sense i i really do i try to make that as clear as possible so let's just go ahead and save this and let's let's we'll do this so instead of doing this what we're going to do is first we want to get that specific element and let's say we give it a data test stuff to do well to do that what we're going to say is const to do is equal to wrapper and we're going to use the get method and this is a very popular method to get html elements inside of our view component and what we can do is we can say here quotes and then we can wrap it in an array and we can say data test is equal to the string to do and now what we can do is instead of asserting that the wrapper.text to contain this we can actually assert that the element that is the to-do dot text and we can assert it to be because we want it to be strictly learn view testing i hope that made sense so now if i were to execute this let's execute this by running npm run test it's gonna fail so it's because we haven't we haven't actually rendered the element but you guys get the point i honestly don't really know what i was going for with executing there we go it fails and so now what we can do is go ahead and actually make this functional and go ahead and actually render this component and once we render this component then we're going to be able to make this test pass so let's actually go ahead and let's just well do that right now so we over here we have this div and so let's say we want to just render for each to do we want to render a div element so here we can say div and we can say div here so a div and to iterate over an array of course we're going to use a v4 for this and so we're going to say to do in to do's and then we're going to supply it with the key of course because we're iterating over it so we can supply that with the to do dot id and then let's give it a data test is equal to to do and now for each element that we're iterating over what we're going to do is we're going to supply it with a to do dot text so let's actually just visualize this because right now we're not even running it i will i mean we are running it and you guys just saw my linkedin page um so let's just go ahead and visualize this a little bit let's just go here real quick and let's go to the view over here let's get rid of that and so now let's just go to our uh to do app let's go to our to-do app here and where is it where is it where is it the not the to-do app let's go to the app.view and what i want to do is i want to render the to-do app so let's go here and let's render this to do app so any instance where we see hello world let's just render to do app right here let's get rid of that and we'll leave the uh we'll leave the component so i think that's good so let's just save that and if i were to refresh you can see that this is really cool it's it's uh it's rendering learn view testing uh so you can see that it works now what we can do actually is go ahead and just run this again and we should it should pass so let's wait here and it does pass and so congrats you have well uh written a relatively well not really complicated but a kind of a meaningful test so congrats in the next part of our application we need to well handle adding new to-do's and so we need to add tests for this functionality and this functionality is actually a little bit more complicated than what we have been doing thus far because right now what we have been doing is just getting elements and asserting that they have a specific value but now we need to actually interact with our component we need to be able to input some text which is going to be the to do and then we need to submit this to do and this should render a new to do inside of our component and we need to be able to test for all of that so as usual let's actually go ahead and write our test first and then we're going to write the feature that is going to be while adding a do and so let's go here and we're going to say that this is going to be another test and this is another test inside of our describe block and here we're going to say it should add new to do so over here and we're gonna have our callback and so what are we gonna do here well of course what we're gonna do is of course mount our component first so let's just copy this and paste it in here we need to mount our component in every single uh test block in order to get this wrapper if this step seems a little bit tedious to you do not worry there's a way we can kind of uh alleviate all this repetitive code within our tests but one thing i do want to note is tests do tend to be very very repetitive uh so i know we we always talk about trying to keep your code as dry as possible and that also does apply to test files as well but test files they're kind of a little bit an exception to the rule because they do seem very very repetitive but even still we should try to make it as dry as possible if we can nonetheless we'll talk about that later all right so what we want to do first is let's actually just do a quick assertion we want to assert that we have one to do at least one to do rendered and we do have one to do let me just zoom in here we do have this one to do rendered over here so we want to assert in the very beginning we have one to do and then later on let's just assert that we have two to do's after we actually add our to-do so let's over here we're gonna say an expect and then in here we're gonna say wrapper so wrapper and instead of wrapper.get we're gonna use find all and what this is going to do is going to return all of the elements inside of an array that match the condition that we specified so we're going to say we're going to find all of the elements that have a data test equal to do because remember each time we render it we are giving it this data test equal to to do so this is going to give us an array and what we're going to do is we're going to say hey we want this to have a length of 1. so let's actually just test this out and this this test should pass right now this assertion should pass because well we do have this right here let's give it a quick go we should have four tests passing and we do all right awesome so that's the very first thing so now what we want to do is we want to uh change the value of a specific input i know we don't have an input in here at the moment but later on we're going to want to have an input change the value of that input by typing into it in the tests we're going to change it and then we're going to want to submit the the form so over here let's just do a wrapper dot get we're going to say data test is equal to we're going to call this this is the input new to do and we want to change the value of that input simulating somebody actually typing so what we can say here there's a very handy method called set value and we can say set value and we can say new to do whatever this new to do is doesn't matter and then after we type into that input we want to go ahead and submit the form so over here we can say we want to get the form at this point i hate this stuff here let's actually make this a little bit bigger for you guys so what we want to do is we want to data test and let's just say that this is the form and in here what we want to do is we want to trigger a submit so what we can actually do is very simply trigger and then in here you can see there's so many things we can trigger so many different things we can trigger so these are like multiple events you know the most common events that you're probably going to use is something like click over here so click but also you can have like click control right so many different things you can trigger in our case we just want to trigger a very simple submit all right so here we're changing the value then we're submitting and then what we should assert is that we have another value in here so we should have two of these so over here two all right so let's save that and let's give this a go and of course it is gonna fail it is gonna fail because well our functionality our to-do app it doesn't support this so well let's let's fix that issue right now so let's just make it functional so down here what we're gonna do is we're gonna add a form so down here we're going to add a form element uh form elements over here and then in here we're going to have an input so a input element we're going to give this a data test that is equal to new to do a data test equal to new to do we're also going to have the new to do inside of our state so this is the new to do text so we're going to have that inside of our state so they need to do text let's just save this and then we're going to want to have two-way binding so to have two-way binding and view we use the view model and in here we're gonna say new to do so new to do all right so that's pretty much all we need for our input but now in our form we want to do some things so let's let's first give it a data test a form and then we're also going to give it an at dot prevent and this is and not submit dot prevent so this is uh so we can prevent the default behavior which is refreshing and then we're gonna say hey we want you to create a to do and so this is a method that we're gonna have to create so right under data which i believe is this one for some reason it's not showing me anything here let's also create some methods so we're gonna say methods and in here we're going to have this create to do method and what we're going to do is we're going to say this dot to do's dot push we're going to want to push our new to do so we're going to want to push our very new to do and so the id we're going to want to give this a obviously kind of either an auto increment id or a random id but for our cases this is not really good but we're just gonna say two uh the only issue with that is well the second one that we add it works for that one but for every single one that we add hard coding to is not really good but it's fine for now we're going to say text and the text is going to be this dot new to do so this is the remember this is the state that we have bound over here in the input so this dot new to do and then we're gonna have the completed status and initially we're gonna give that a false completed status so let's go ahead and save this and really this should work and we can actually test this out so over here let's just say new to do let's press enter and it does work we might eventually also want to clear this but for now we'll just leave it like that let's make it as simple as possible so clearly this works so you know what let's just go ahead and let's just run our tests you know what are we waiting for let's just run our tests you know if this works that's awesome so let's go here and you know we're happy our tests are gonna pass and they fail what is going on okay so there's actually a very good reason why this failed and what i like about jess is it shows you exactly what i expected and what it received so it expected to but it received one meaning that hey this didn't actually end up adding anything but it's strange when we when we tested it manually it did add something well we have to understand that changing state inside of our application is actually asynchronous in view but right now we're handling it as if it is synchronous but changing state is asynchronous so to be able to successfully account for that in our test we have to account that hey this is asynchronous and this also is asynchronous and in javascript the way that we've well i think most steps would deal with asynchronicity is by having an async and then a weight here so the the premise of what i'm trying to say here is changing state in view is asynchronous so we have to handle it in our test so we need async await in our test so anytime we change the state we have to async await it so now if we were to run this test again now it passes so i hope that uh kind of makes sense i do encourage you on your own i'm not going to do this is maybe once we actually add a to-do i want to clear the input so on your own clear the input or on your own write a test that says once you add this input it is the value of it is cleared and then actually implement it i do encourage you to do that but just for time's sake i'm not gonna do that so to wrap up our application what we need to do is to well complete our to-do we need to have the ability to complete a particular to-do and whether that is by clicking on the to-do itself or a text box right next to it we need to complete it and then we need to somehow tell our user that well you've completed this to do now i think the best way is to have some sort of check box right next to the element or the to-do and once we click it maybe we'll have some sort of line through [Music] through the text saying that hey you've completed this so let's actually write the test for this so let's go over here and we're gonna have to write another test so let's just go here and what i'm gonna do is get rid of this for now i am i'm gonna be really lazy here i'm just gonna copy and paste this and here it should be able to should be able to complete to do that is what i'm going to call it and so the first thing here is we have to of course well mount our but now what we want to do is we want to trigger some sort of event and what is this event well i want to click on a check box so let's just get rid of this and let's get rid of this for now and over here what i want to do is i want to get and then what element do i want to get well i want to get to do check box so this is going to get me a check box element and i want to set its value to true so to true check boxes are either true or false all right that's awesome that's really really good and then ultimately what i want to do is i want to expect that for that particular to do element these styles has changed and how are we going to change the styles well that's up to us but i'm thinking maybe i can add a conditional class and if it has that class maybe a class that is completed if it has that class then it's going to style it as if it is completed so here we can say wrapper dot get and then over here of course we're going to want to get the data test is equal to to do's or to do and what we're going to say here is we're going to say dot class so we're going to want to get is classes this is actually going to return an array of all of the classes so we're going to get all of the classes and then over here we're going to say dot contain dot to contain and then we're going to say completed so it's just going to see inside of this array do we have the completed class or the string completed so that's really the test very simple and i'm not going to run it because i i think you guys get the point it is going to fail so let's make it past right now and so to make it pass well over here let's just we're going to have to conditionally render a class so we're going to have to conditionally render some sort of class so let's actually go here and this is going to be uh dependent on the to do or the completed status of this to do and so we're going to say here that hey if to do dot completed if it is completed then we want to render this completed class else we just don't want to render anything so that's what we want to do so that's pretty much it so that's that's very simple now what we need here inside here as well we also need another input element that is a check box so here we can say input and then we can say type is equal to check box and we can say that the v model is the actual to do dot completed all right and then lastly we're gonna give this a data test of to do check box and that's it that's that's that's honestly it very very simple to test this out well it's not going to work well we're not going to see it work because of course we need to style this so let's go inside here let's just copy these styles and then in here we can say that the dot completed we're gonna have a a text transform i honestly do not remember the style of this and the uh the lack of auto completion is not helping so we're going to say line through i think that's a valid style and so if i were to actually click on this we're not getting the line through which is a little bit confusing to me why are we not getting the line through let's get rid of that there we go let's refresh and we're still not getting the line through maybe maybe the the styles is wrong maybe if i give it something like color green refresh that okay there we go okay so it was it was just me just being really confused let's go here's what these back uh i think i think i think the i think you guys can figure out what this is i honestly don't remember let's say if we for done it we're just going to change the color to green okay if you want to have a line through it that's a completely fine but i don't remember the actual css styles i thought that was it but i guess not all right so that's pretty much it so now what we can do is we can go ahead and test this and that's really what we're doing here we just want to test it we want to test that this class is inside of this element and it is terrific so we have pretty much built out our application and this is honestly even though this is a very simple application this is really how most testing is going to be you're going to want to break most of your application into very small components and ultimately you're going to want to test those components in complete isolation and and therefore the test should be relatively simple for each component because we're not having components interacting with one another and this is known as unit testing where you're you're testing each component in isolation however when you want to test uh components that interact with one another and you want to test that hey once they interact with one another you know do they work as expected this is more complicated testing and it's known as integration testing and you can actually do this with jest and view test utils by having a component a very large component the house has many children and just testing how that component is interacting with all those children so you can you can definitely do that that's known as integration testing and if you want to even go one step further you can do e to e testing and a very popular framework a javascript framework for that is cypress so i highly recommend that now we're not done yet there's still so much more to learn and i'll see you guys in the next section in this section what we're going to be doing is looking at how we can reduce redundancy within our code now at the moment there's not really a lot of redundancy but i can actually point to well this over here so for each component it seems like we're just mounting our to do app and we're getting it as a wrapper and again this is it's okay it's not that redundant but we may in the future have a lot of redundant code so how can we fix this well this is something that is actually pre-built with jest and it is going to be the before each hook and what this is going to do is it's going to take in it's a method that takes in a callback and is going to run whatever is inside that callback before each test and what this is going to allow us to do as well reduce the redundancy of our code now before each is not the only thing that exists and just we also have before all so this is going to run once before all of our tests and we also have after after all and after each and you can probably assume what these do now we can definitely use these things to like clean things up but well i'm not gonna do that so how could we uh uh how could we uh um uh you know reduce the redundancy of our code using the before each hook well what we can do is we can just go ahead and just wrap this in here now the only issue is this right here is not going to have access to this right now because this const wrapper is inside of this before each hook so what we could do to fix that so we can give our test access to the wrapper is we could say let wrapper over here in the very top and then in the before each hook we can just say wrapper is equal to mount wrapper and that way what we can do is we can have access to each wrapper and this will significantly reduce the redundancy in our test so this is a very very simple thing that we can do and just to prove to you that it works let's just get rid of that we should still have five tests passing and we do so yeah so this is something that you can definitely utilize to reduce the redundancy in your tests in this section what we're going to be doing is we're going to be talking about different ways that we can find elements now in our to do component we found that we can find a lot of elements with well the get method however sometimes using the get method doesn't really work for our purposes and i'm going to explain why the get method assumes that we have that element inside of our document and if we don't have it it's going to throw an error and it's going to cause our tests to fail and sometimes this is exactly what we want if we can't find an element yes the test should probably fail however sometimes what we want to do is we conditionally render components or elements and we want to test that hey if this condition is met this element should not be present and by using get or get by using get well we're never really able to do that because when we don't find the element it throws an error so we can't assert that that element is not there because well it just is just going to go ahead and fail and so there's actually better ways of handling this rather than using get when you want to assert something like this so to assert something like this let's actually just create another nav dot view and in here let's just copy everything we have in here and very simply what we're going to do is we're going to build a very very very simple nav bar so let's just use the nav html semantic elements here and we're going to have anchor tags so we're gonna have very very simple anchor tags and we're gonna have two anchor tags so over here we're gonna say home and over here we're gonna say my profile now we only want to render my profile when uh or if we are logged in so what we're going to do is we're actually going to go here and we're going to have data so we're going to have data and then what we're going to do is we're going to return and we are going to return a boolean value is logged in and initially we're going to just set this to false so initially we're not going to be logged in and so over here we're going to have our home remember this is going to be rendered regardless if you're logged in or not and over here we're going to have my profile and this is going to be conditionally rendered if this is true so what we can do here is just say vf and we can say is logged in so this is how we can conditionally render things in view let's actually just give this an id of profile and you know we can also give it an href but it's not going anywhere and i am very lazy over here we could kind of do the same thing let's just give this an idea of home and that's pretty much it so now what we want to do is let's go to our app dot view file and i actually already did this so i imported the nav component i have the component here and i'm rendering it here so now if i were to refresh i see absolutely nothing for some reason why is that i am very surprised and that's because this nav is empty okay what were we working on here we were working on this yeah we're working on this which is a copy for some reason i have no idea what's going on let's uh let's just get rid of this copy i honestly have no idea how that got there okay so let's save this and we should see a nav and you see here that we're conditionally rendering it and if this were to be true we should see the my profile and these really don't do anything but just for illustrative purposes so what i want to do is okay if this is false if this is false i want to test that i don't see this so what we could what you probably could do or what you think you could do is use the get method get this element assert that it's not there but again if we can't get the element it's going to throw an error so we can't even reach that assertion so instead what we're going to use is some other method known as find and dot exists so that is what we're going to be utilizing so in here let's just create a nav.spec.js and let's just follow the template over here i'm just going to copy this paste that in there and we're going to say nav we're going to say nav we're going to say nav here and i think that's pretty much it so what we're going to do here is we're going to get rid of all this we're going to say nav here and so terrific so now what we want to do is of course we want to assert let's actually assert in the beginning that if it is true we render the my profile text so we should see say here renders a profile link now initially this is going to be false so what we can do is we can supply it with data and over here we can just return and over here we can return that the uh that the forget what it was called is logged in is true so here we can initially set it the state to true and now what we can do is well we can actually because here we're asserting that it actually exists and if it doesn't exist we probably want to throw an error let's actually use get for this and this this kind of makes sense to use get for so let's say const and we're going to say profile link and then over here wrapper and then dot and then we can say profile so this this is how uh usually we uh we have been getting things by test id but we can also get things by id if we want to by symbolizing hashtag we can also get things by element you can also get things by um class so now what we want to do is well we've got the element and now what we can basically do here is we can say something like profile.text and we can say you know we expect this to equal or to be honestly same thing and we can say that we expect this to be my profile so let's save that and let's just double check over here my profile might as well also change this to nav in the meanwhile and so let's actually go ahead and let's uh give this a go let's run this test and it should pass and it does terrific all right so this is this is really cool and what's great about this is right here if we can't find that particular element it's not even going to reach the expect statement it's going to fail right over here because that's the default behavior of get it's going to throw an error and now in this case it's completely fine because we're testing if that element exists but now what if we're testing if it doesn't exist so we're going to say here it it should not render a profile link so this is what we are testing here all right let's just give you guys more space here so in this case we're going to have our wrapper and our wrapper is going to be false this time so we're going to have false here and so we shouldn't expect this over here and just to prove to you that this is going to trigger an error so i'm gonna have this here and what i'm gonna do is i'm gonna say expect true dot to be truthy to be truthy and what what this does is it just asserts that true is a truthy value and just to 100 prove to you that this is going to pass let's go ahead here let's we're going to comment this line out and we're going to go ahead and just run this test so we should have seven passing tests all right so this assertion over here will always pass now let's go ahead and let's just try to find the elements and we're not gonna find it because this is false and you might think okay we don't find it that's fine but then we're gonna assert that this is true we should still have seven passing tests but that's not the case over here the default behavior is that it's gonna fail so we should have one failing test and three two one we do we do right there and the error is hey we cannot find this element again because the get it by default it throws an error if it doesn't exist so instead what we might want to do here if we want to assert that something exists or it doesn't exist is use find so instead of doing this what we can do here is we can say wrapper and then we can say dot find dot find and then over here we can say hashtag profile and then in here we can use dot exists dot exists and so over here we're saying wrapper.find and we can of course extract this out over here saying const profile link is equal to this and then we can say here that the profile link dot exists and then what this is going to do it's going to return either a true or false value so we can actually leave this but now we can over here say that this is false so we assert that this is not going to exist and now over here if we were to run this again it is going to pass so that's just a nuance that you need to understand if you're asserting for something that doesn't exist you want to use find and you want to use the dot exists over get in this very last section as i promised i'm going to explain the concept of shallow rendering and let's actually do this through an example so what i'm going to do here is i'm going to create two components one of them is going to be a child and one of them is going to be a parent so over here we're going to say parent dot view and then over here we're going to say child dog view so we're gonna have two components one parent and then one child and in here of course we need our typical view application so as usual let's just go into our message dot view and for both let's just go ahead and uh let's add that in there and so what we're gonna do here is we're gonna get rid of this we're gonna get we're gonna change this to parents or child rather and then over here we're gonna get rid of this and over here we're gonna get rid of this we're gonna change this to parents and over here we're gonna get rid of this over here okay cool so now what i want to do is i want to import this child into the parent and render this child in here so let's just say that this is a child save that this is a parent and let's save that and so now okay let's go ahead and let's just go ahead and let's import and we want to import child and then from uh dot slash child dot view and so this is a component that we want to ultimately render so what we can do here is we can say components we can say that well a component that we want is child and over here right under the appearance let's just also render or you know what yeah right under the parent we're going to render the child as well so right here and just to double check that this works let's just render this component inside of our app.view or app component right here so we're gonna say parents and then over here we're gonna have to do some import parent from uh dot slash components slash parent.view we're gonna let's just render it down here for now save that of course we're getting some errors unfortunately super apologies so we have our components we have our parent yes yes i get it i get it there we go okay cool so we have a parent and then we have this child over here so this is really just one component but is comprised of a nested child so what if we wanted to test out our uh we want to test out this parent component so we want to test out this component over here and we want to test out that the text parent is present inside of this parent component so this is actually a very very easy text test that we have done so far so what we can go here is we can say parent if i can type dot spec dot js and as usual i am going to be very lazy and i'm just going to go ahead and copy all this i'm going to paste that in there and i'm going to say parents and over here i'm going to say parents and i'm going to be extremely lazy and i'm not even going to give this test actually i'm not even going to give this test a name i'm just i'm just going to leave it as is okay so over here what we want to do is we want to render the parent component and right now let's just get rid of the props because there is no props so what we want to do is we want to get this wrapper and then we want to find all of the text inside of the parent and i want to test that well the parent exists so the the text parent exists and it should let's just get rid of all these other things and it should because well it does exist we added it right here so let's give this a test and this should result in an extra additional test that passes so we should have eight in total and we do now one thing i want to note is okay so this is awesome this is really cool now let's actually go ahead and let's change this to child so to child let's save that and remember in this other in this parent component we're not the text child doesn't isn't present there uh uh in in the root level component what we're doing is we have this other component here this child component and in here that text is present child so what do you think is going to happen here let's go ahead and let's run this and it is going to pass and so by default when using mount what happens is it mounts the parent component as well as any children component and that is really really great for integration tests as well we can get all of the components that is inside of a parent and just see how they interact with one another and if they result in the exact outcome that we want however sometimes in some cases we really just want to test out our application in complete isolation our component in complete isolation and maybe a good example of this is maybe this is you know child that says something like child with parents child with parents and if this is the case and i were to somehow accidentally get rid of this and if i were to run this test it's still going to pass even though the intended effect wasn't uh like this wasn't the intended effect i wanted to see if the parent text was in the parent component so in that case in this case what we want to do instead is use shallow mount and what this does is it forgets about all of the other components within the parent component and just focuses on that one component and that is what is meant by shallow mount so over here we're going to say shallow mount and now if i were to run this it is going to pass because we have parents here actually it failed so expected substring child but a received parent sorry what was the test doing again oh sorry it should be apparent here so we should have parents here and it's going to pass in this case okay cool however now if i were to remove this even though this passed before because remember in the child we have parents in here what's gonna happen is gonna it's gonna fail because we have shallow rendered it and you can see here that it works as expected so that's a time where you want to use shallow rendering all right i hope you guys enjoyed the tutorial and i'll see you guys in the next one
Info
Channel: Laith Harb
Views: 4,714
Rating: undefined out of 5
Keywords:
Id: QIDhzBg5eWY
Channel Id: undefined
Length: 79min 23sec (4763 seconds)
Published: Sat Sep 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.