In the last lesson.
You set up a test case that actually tests an express API endpoint.
Now it worked the first time around but it failed the second time around a second time around it failed
because the email was already registered from the first time it ran.
In this lesson you'll learn how to use just lifecycle methods to run some code just before or after
a test case that will allow you to set up some code that clears the database so your test cases can
consistently execute as expected.
Now you can learn more about this over in the just documentation in the sidebar under introduction.
There's a section called setup and tear down this outlines everything we're going to talk about in this
lesson we'll be using various lifecycle methods such as those shown below to actually configure our
project.
Let's go ahead and do just that over here inside of the user dot test dot J.S. file.
We're going to call a couple of functions that just provides us as Global's similar to how we have access
to expect and to test right here.
One of those is before each.
I'll go ahead and call before each passing in a single argument.
This is a function to run this function runs before each test case in this test suite.
Now in this case we only have one test case so it would only run a single time.
Let's go ahead and add a simple console dot log call inside of here so we can see when exactly this
runs and I'll just log out the message before each down below.
We'll also call after each which runs a single time after each of your test cases in the test suite
right here.
Once again we passed to the function to run and we'll just use console log to print a message after
each.
Now with this in place we can go ahead and save our test suite.
It's still going to fail because we're not actually manipulating the database just yet.
But if I scroll up in the output I should be able to see before in each print and then after each print
afterwards as long as you're seeing before each and after each then everything is actually running correctly.
Now the next step we need to take is to actually do something meaningful and we're going to go ahead
and do something meaningful in before each.
Now we don't need after each for this particular project I did want to let you know that it exists though.
We'll go ahead and remove that from our test suite and we'll just use before each.
Now you also have access to before all and after all which will run just a single time before your test
cases or after them.
In this case though before each is the correct one because we want to make sure that every single test
that runs runs in the same environment with the same test data in the database now for the moment all
we're trying to do is wipe all of the users inside of there.
So our test can consistently run correctly which means we need access to that user model.
So right here I'm going to go ahead and load it in concert uppercase U user I'll use require followed
by dot dot forward slash source forward slash models a forward slash user to load in that Mongoose model
then all we're going to do is use some of the methods we have access to down below to delete all of
the records.
So what I'll actually be doing is removing the console log call and using user dot right here.
Delete many now if we call delete many it's going to delete every single user since we haven't provided
any sort of search criteria.
And that's what we want.
We want to start off with a nice clean slate.
Now currently nothing's going to work as expected because before each has asynchronous code inside of
here.
But we're not doing anything to tell just that it is asynchronous.
So once again we have the same options we hand below with our test case.
I could go ahead and provide the done parameter calling it when I'm done or I could go ahead and set
this up as an async function which is the approach that I'll take down below we just use a wait with
our promise.
This is gonna make sure that the users are deleted before just considers this done once it considers
this done it will move on to the test cases.
So we definitely want to make sure the users are gone before the test runs.
So with this in place we've solved the problem we had before we added four lines of code to the user
test suite but down below our test cases are gonna pass and they will consistently pass over time because
we're always starts off with an empty database which is a good thing we want to make sure that we have
a consistent set of data for our tests to work with.
Now wiping all of the data is a good start but there are also test cases that are going to test features
like logging in and in that case it would be nice to have some very specific data in the database that
we can use when testing.
So we are going to start by deleting all of the users.
Then we'll go ahead and add a user in that could be used with test cases such as test cases for testing
log in which we'll be doing in just a minute or two.
So what we're gonna do is create a new user right here in before each just after we go ahead and call
delete many and I'll define that data up above and then we'll pass it in.
Down below right here let's define a constant which I'll call User 1.
Now I'm calling it User 1 as opposed to just user to leave the door open for other test users later
on if we needed them.
And this is just going to be an object with those basic properties on there.
So right here as an example I will specify the name for our test user.
I'm going to go ahead and use something like Mike and as well I'll provide the email for this test user
Mike at example dot com and then I'll provide a password as well.
I'll go ahead and use a 5 6 watt exclamation mark exclamation mark as my password.
And there we go.
We have all of the data we need to create this test user.
Now down below we actually have to save them to the database and we'll do that just after calling delete
many.
So right here what I'm gonna do is use a wait with the following.
I'll use the new operator with user like we've done so many times before and I'll provide the user one
object.
Then right there I'll just chain on a call to save to save things.
So we're doing everything in one shot as opposed to first storing this in a variable and then referencing
it on the next line though we could do that as well.
For example I can cut this out.
I could have a variable called user which I create up above like this.
These two solutions are identical.
We're gonna go ahead and go with the first solution since everything fits on one line and it works pretty
well for our purposes.
So with this in place our existing test case should still pass.
We have our test user in there.
Yes but the emails don't conflict and that's a good thing.
Right here I'm gonna go ahead and save user dot test dot J S that's going to rerun everything and we
can see we have a passing test suite now the whole point of having this test data in the database is
to test those other endpoints like the ability to log in and that is exactly what we're going to do
down below.
Now don't worry we will expand on our test cases such as this one once we learn more about just but
we're going to go one step at a time so we can keep all of this actually comprehensible.
Right here what we're gonna do is call the test function once again we're gonna pass to it the name
of our test.
Something along the lines of should log in existing user.
Then we'll set up our async function and we can go ahead and actually use super test to test things
out.
So once again I'll use a way to calling request and passing in our Express application exactly like
we've done up above.
Now in this case we're also trying to access an endpoint that uses post so I'll be using post right
here.
Then we'll go ahead and provide the you are well that is forward slash users forward slash log in from
here.
We're gonna go ahead and send a cross good data.
So in this case I want to provide the correct data the data that our 1 test user has been created with.
So down below.
Let's go ahead and do just that.
I call send to provide the data with the object like we did up above.
And I need to provide my email and password to log in.
So I'll go ahead and set both of those up right here.
Now the current approach would be to just type out the correct email and password inside of quotes.
You could also just reference these ones on this object up above and that's what I'm going to do.
So right here the email is not going to be a new String.
We'll just grab the existing one from user one dot email and then the same thing for the password down
below.
User 1 dot password.
Now that we've sent the correct data off we can expect something about the response and once again we're
just going to stick to the status code right here.
We will expect a 200 which is exactly what we should get now that we have this in place.
Let's go ahead and fire off the request and see if it works as expected.
Right here the test suite is rerunning and in a couple of seconds we should see all passing and that
is exactly what we have.
So in this case we are setting up test data for our test cases to interact with.
Now you might say why not just create the user right here and then go ahead and try to log in.
Well the problem is that a lot of our test cases are going to need a user to already exist things for
logging in adding an avatar updating a profile creating a task and others.
So it's best to just do it once.
Up above to set up the database and then use it over and over again in your test cases.
Now it's challenge time you're going to create a test case that makes sure when these credentials are
bad things fail as expected.
So right here here is what I'd like you to do test do log in.
Failure you're going to create a new test case should not log in nonexistent user.
Then you're going to send off the request with bad credentials and by bad credentials.
I mean anything but what we have right up here then you're going to go ahead and expect the correct
status code in the response.
Feel free to refer to the application code or run the request and postman if you forget what that was.
And finally test your work save the test suite and you should go from eight passing test cases to nine
if the test case fails try to use the error message to figure out why.
All right.
Paul is the video knocked that out when you're done come back and click play
how'd that go.
Let's get to it by defining the new test case.
I'll be calling test one more time.
Right up above or down below the order of your tests is not particularly important.
And then we'll go ahead and set up the name should not log in non existent user.
Perfect.
We'll set up our function as an async function.
We'll be using async await and almost all of our test cases since pretty much everything we're doing
is indeed asynchronous.
And right here we're going to send off the request with bad credentials.
So it starts off exactly like what we had above.
I use a wait I call request passing an app then I call post with the same path forward slash users forward
slash log in and I still want to send some data.
I'm just going to send bad data so I could leave something off.
Or I could just have a bad password as an example.
So I'll set email equal to the following user 1 dot email.
You did not need to do this.
You could have used any sort of set of credentials and then I'll set password equal to something else.
This is not my pass or anything else would have worked.
Once again it's not important that you had the exact same data just something that's going to cause
the failure.
Next up we want to expect something about the status code.
So we call the expect method that super test provides.
And in this case if you looked at the code you'd remember it's a four hundred four when someone tries
to log in but it fails.
Now with this in place the only thing left to do is to test our work.
That's step number four.
So I'll go ahead and remove the challenge comments.
I'm going to save the test suite then we'll see what we get down below.
Hopefully we have 9 passing test cases and that is exactly what we're getting.
So there we go.
We now have test cases that create data and test cases that work with existing data and we were able
to do all of that by using before each and Mongoose methods that we've already worked with earlier in
the class.
So when we use jest it gives us everything we need to set up our test suite without having to write
a whole bunch of code ourselves.
We're able to get up and running really quickly even with more advanced testing things like testing
and express application.
Here we have a test suite with three tests and just 36 lines of code.
Now yes we're gonna add more but this is a great place to start in the next lesson we'll continue on
writing test cases.
I'm excited to get to it.
So let's jump right into the next lesson.