So we need to write some more tests to complete testing our handlers, those specifically that either
access the session or that hit the database.
And I said last time, I'm probably going to start with this one, which is the post to search dash
availability.
But I'm actually not going to I'm going to start with this one instead, the make dash reservation page
when we post to that.
And the reason I'm going to start with that one is because this one actually includes everything you
need to know in order to write the tests yourself.
So it covers every possible possible situation for all of the tests that I have to write for the remainder
of my handlers.
And I don't want to force you to watch me writing these tests one at a time because it gets extremely
repetitive after a while.
And what I'll do instead is after I've done the necessary coding to write the tests for the post to
the make desk reservation.
You, Earl, I will post the complete source code as it exists at this point in the course.
Write to the next lecture and you can use that as a reference to write your own tests and I'll talk
more about that later.
But right now I want to test the Make Reservation, the posting to make Dasch reservation.
So how am I going to do that?
Well, I'm going to go to the bottom here and I'll create a new function func.
And it is for the repository test repository, test repository and post reservation right there.
So I'm testing the post reservation method or function in that has the receiver repository and it's
a test.
So let's go look at that and see what it does.
So let's go over to handlers and here is the function post reservation.
So this, first of all, passes a form.
And you may recall some time ago I said it's always good practice to call parsed form whenever you're
parsing form data.
In fact, you have to call it.
But it's good practice for a reason.
And I'm going to draw your attention to this because we need to pay attention to what happens in this
function a little bit later on.
So that's the first thing I have to test.
And if I have problems with that, well, it's going to right now just throw a server error.
And as was the case in our previous test, I don't want that to happen.
I want instead to give more meaningful feedback to our users.
So let's make that change right now.
And I'm going to go up to reservation and do the same thing I did here, a copy this and post it down
in here to replace this server error.
And I'll change the error message and the error messages can't pass form, and I'll just take them back
to the home page with a status temporary redirect that a little bit further down, I try to pass the
start and end date.
Now, in theory, those should always be OK because we're using a date picker to put them in the correct
format.
But I never trust user input.
So again, I'm going to test for that and I'll change the error message to can't pass start date.
And I better still pass.
Right.
And again, these error messages are just to get the error message in here.
For our purposes, you would probably have more meaningful error messages in a live application will
do the same thing for end date, can't pass and date and get rid of that and room ID, same idea.
So we write here, we are saying error invalid data.
So that one's OK.
That's giving me my status.
Temporary redirect.
I want that.
Then we build our reservation model up and we pass our form.
We generate our form and start testing some things and then we test for first name, last name and email
which have to be there.
We make sure that first name is three characters along at least that email is in the form of email.
And if it's not, we take them back to the form, repopulate it with the data that they've entered and
highlight the errors that they have.
OK, assuming we get past that, we then attempt to insert something into the database and get a reservation.
So we attempt to assert the reservation into the database and get a reservation back.
And again here I don't want to helper's server error.
I want to take them back somewhere and I'll say can't insert reservation into a database, which is
just an error message, and we'll take them back to the homepage, which is sufficient for our purposes
right now.
And lastly, we try it with the room restriction.
So again, I don't want a server error.
I'm going to say can't insert room restriction.
Try that again there.
So now I have things I can actually write test for.
So let's go back and start writing this test and look at the very first thing we need to do.
So the first thing we need to do in our test is to pass the form.
And here is where you need to draw your attention back to what pass form does.
I said a while ago, good practice to do this.
And here's what it actually does, is read on the screen in front of us pass form, populates our form
and our post form for all requests.
Pass form passes the raw query.
From the URL and updates our form, so what I need to do then is to generate a post request that actually
supplies a body that will pass the form data.
So let's go back and start writing our tests.
So here, what's the very first thing I need to do?
Well, it's pretty much the same as what I did in my reservation here, my repository in a repository
reservation.
I need to create a request to get a context for the session so I can write to that, generate a new
recorder.
So let's copy that and come down here and paste it in and I'm going to post not get.
So I'm creating a request that says create a post to make reservation and I can't pass the Knill for
the body.
You would think you could you would think you could just maybe construct a U URL values and put that
somewhere.
No, that won't work.
You actually need to construct the body.
So let's think about how we can do that.
Well, you know that when you pull anything out of a post request, the art form and a handler, when
you say ARGT form aget first underscore name, you're getting that as a string.
And that's actually pretty indicative of what we need to do here.
We need to generate a string and then pass that as an argument to new request.
Now, if we look at new request, a new request, it says it requires three parameters method, which
is a string.
We have that it's post you URL, which is a string make reservation.
We have that as well.
And then it requires a body o reader or something that satisfies the requirements in order to be taken
as an iReport reader.
And we have something that does for that does that for us writing the Strings package.
But we'll get to that in a moment.
First of all, let's build our post request.
There are other ways to do this, but I think this is a good exercise for you to figure out how post
requests actually work.
First of all, I'm going to create a string which I'll call recorded.
That's going to be a string.
And right now I'm just going to put one thing in here, one of the required form parameters that we
know have to be here and that start date.
And that's going to be equal to and I'll put it way in the future.
So I know that it's going to be a date, that it's never going to cause me problems for a long time,
20, 50 zero one zero one.
So now I have a string and now I'm going to append to that one line will append every request parameter
that we need to make this a valid post for our handler.
So I'll say Rech Body and I will use the format package, which is part of the standard library, and
I will use the method or the function as print F and I'm just going to build up my string one line at
a time.
So this will take two placeholders a percent s followed by an ampersand followed by a percent.
S and those placeholders are replaced with request body.
So the first part of this string will be what the request bodies currently equal to, which is this
line right here.
And the second one will just be my next parameter, which is Endi, and that will be equal to 20 50
zero one zero two.
And then I'll duplicate that line.
And my next parameter that I require is my first name, which has to be three characters long.
So I'll make it John, which is four characters then the last name, which will be Smith.
I'm just putting valid data in here quite deliberately.
My next one is my email, which can be anything in the form of an email John at Smith dot com.
And the last one we need right now is phone.
There's one more actually, and that can be anything.
One, two, three, four, five, six, seven, eight, nine.
And lastly, we need a remedy, which I will make one.
OK, now I've built up a string which will read as follows.
Start date equals 20 50 dash zero one zero one ampersand and date equals twenty fifty dash zero one
zero two ampersand.
First name equals John and all the way down to we get to remedy.
So now I have everything I need to make my post and what I need to supply here.
As you can see, when you look at new request, I need an IO reader.
Well fortunately String's has a really nice function.
The Strings package, which is built right into the standard library, has a function called New Reader,
and it just takes one argument, which is a string, which is request body, in our case, our Rikyu
body.
So now I've built up a request and that request has this post data as the body.
So now that I've built this up, the next thing I do is the same thing I did before.
I just create a context by calling get get context, this function down here passing at the request
that I created right here.
And it gives me back a context that knows about the session.
And then we just add that context right back into the request by calling request dot with context and
passing it the context we just created.
So now I'm pretty much ready to make that request.
There's only one more thing I'm going to add here, and it's something that may not actually be required,
but I think it's excellent practice.
That is to set the header for the request, so I'm going to call one of the methods or one of the functions
built into my request called header, and I'm going to set the header and I'm going to set it to tell
the Web server about the kind of request that is coming its way.
And I want to tell the Web server that it is a form post.
And I do that by specifying this header content dash type with a capital C and a capital T, that's
the name of the header.
And the value is application slash x dash w w w dash form dash u url encoded.
And that's part of the web standard and what that actually says to the web server is, hey, the request
you're about to get, it is a form post and this is the header that tells a Web server that this is
a form post.
So now I create my my new recorder, just as I did before, and then I need my handler.
So we'll turn our our handler, which in this case is called post reservation into a handler func.
So I'll again, just like I did before, create a variable and assign at the value of http dot handler
func.
Handler func.
And pointed to the correct correct handler, which in our case is repo post reservation there.
Now I have a handler, so that means I can actually call this handler.
So let's try that handler dot serve HTP and pass it.
Our response writer, which is not really a response writer, but it's something that satisfies the
requirements for being a response writer.
Our and our pointer to an HDB request, which is just to request the one we built up above.
So now that I've built this, I can actually do the same thing I did up here.
I can copy this code, paste it down here and find out what do I want this to have for a return type
and the return type.
If we go back to our our handlers and assume that everything worked OK, our return type at the very
end of this function is status the other.
So I'll copy that, go back to my tests and not look for a temporary redirect.
I will look for status the other and I will say change this to post reservation post reservation handler
returned wrong response code.
Got this, wanted that and substitute what we got from our, our test server and what we expected which
is the other.
So let's see if that worked.
So we'll go back to our terminal, make sure that we're in the right direction.
We are.
And run our test go test.
And that past.
OK, so this one actually works.
So now we know how to actually manually build up the body of a post request and send it to the server
and make sure that it all worked.
But all we're testing here right now is that every situation is correct, that we've done everything
right.
So what we need to do is to actually test other situations.
So what do we need to test?
Let's go back to our handlers and start at the very top of the post reservation, which is right here.
So the first thing we want to fail is what if there's no body to the request?
What if we don't we can't pass the form.
In other words, so I've already changed this from a helper's server error to a nice redirect, which
means we'll be looking for the status of temporary redirect, but we need to make another call to our
handler.
But this time we want to make sure that there's nothing in the body of the request.
So what I can do is just reset everything so I can copy all of this stuff.
I'll just copy all of it and put a comment here, test for missing post body and paste it in there.
And of course, this becomes an equal sign.
And I'm not going to pass the request body this time.
I'm going to pass in a mail, which should cause that to fail.
And this context is not a sign anymore.
It's a new we're getting a new sessional context just to make sure everything is starting from a known
proper value and will make the response writer.
We don't need an assigned there.
I'm going to get rid of these spaces just to make things a little closer.
And we're not assigning a new handler.
We're simply redefining our handler with our new we don't even need this line, but I'm going to put
it in to make it readable.
And then we make a request.
And what we want to see here is status C other and put it down here.
Post Reservation will change our message to handle returned wrong response code for missing post body.
Let's try that and see what happens.
So I'll clear my screen go test.
And it failed and I got three or seven wanted 303, let's see what we have here.
So did I get that wrong in my handlers?
That's temporary redirect.
That's right.
It's not the other.
So my test told me exactly what I wanted to find out, which is good.
Let's try that again.
Clear the screen.
Run it.
Good.
Now, let's try our coverage, see what's missing so far and there'll be a lot missing.
So what is missing?
Well, we haven't got this yet.
We'll take care of that later on.
That's no problem.
All of this is green.
I mean, the first one is great.
The second one is great.
And here's the one I'm looking at.
Reservation.
That's great.
Now, here's the one I'm looking at post reservation.
OK, so we managed to handle the first case, which is great.
Now we want to handle the cases where the start date and then the end date and then the remedy are all
invalid.
OK, well that's easy.
We know how to do that already and it just becomes a matter of copy and paste and changing content.
So what I'm going to do is copy this entire thing, create a new comment here that says test for invalid
start date and paste that in there and get rid of this comment.
And now I need to change this data and I'm going to do this by copying the entire thing and changing
the one value that I want.
So I'll come back down to where my comment is and I need to reset my post body and make this a string's
new reader.
And in body, this becomes an equal sign because we've already declared that variable above.
And now I want to put the start date in an invalid format and the word invalid is a perfect invalid
format.
OK, so that should fail.
This part should pass when we actually make the first request.
So over here in our handlers, this should pass.
We should get past that.
No problem, because we have a form data that we can pass.
This is no problem because I'm just getting values from the form post.
If there's nothing in there that just becomes an empty string, but this part should fail and we're
again going to be getting a temporary redirect.
So let's make sure we're actually testing for a temporary redirect at the end of this.
We are, but we need to change this part of our error message for invalid start date.
OK, so let's run that test and see if we missed anything.
Go test.
It should pass.
And it does check our coverage and make sure it's actually testing what we think it's testing.
So here it is all the way down to post data and that got tested properly.
Good.
Now I once again, just to make this clear, what I'm doing, I'm going to test for an invalid date,
a copy and paste the whole thing invalid and date.
And this time I'll make sure the start date is valid.
Twenty fifty dash zero one zero one.
The end date is invalid and I'll just make it again the word invalid.
Change my error message to end date and run the test.
And there's of course copying pasting the whole blocks of code like this.
Really not a good idea, but I'm just trying to make it eminently readable for you.
What I would do once I figured out how I'm writing this test is make this a table test and just build
up my data as a slice of whatever format I need and run it through a for loop.
But this works just fine for our purposes today and we're trying to make it clear how everything is
getting tested.
So now that coverage close, close, close, that go back to here and go test, it should passed.
It does.
And now coverage.
And there it is.
OK, so let's go down here and make sure that it actually tested what we thought it would end date.
It does.
So now we need to do the same thing for our remedy.
So let's close this and go back to our editor and once again, copy all of this, paste it in here.
And this time we're testing for invalid remedy.
Now, what's going to make it an invalid remedy is if it's not something that can be converted into
an.
So, again, I can put the word invalid here and change the end date to a valid end date, 20, 50 zero
one zero two and change my error down here.
Invalid remedy.
Save that and let's actually run our test again.
Go test.
It passes and lets do our coverage and make sure that it tests what we think it's testing.
And this is post preservation and here it is remedy.
Now that is tested as well.
So what's left to test?
What's left to test is we need to make sure that it passes form validation.
And if it's not valid, we want to take them back to that screen.
So let's test that.
How can we make sure that our form validation fails?
What we can do that by either leaving something out like first name or making sure that first name is
not at least three characters long.
So let's go back to let's close this window again, go back to our code, copy everything here, paste
it down and say test for invalid data.
So we'll leave everything the same except for first name, which I'll make one character long.
OK, and that should test it for us for invalid data instead of remedy.
Save that.
Go back.
Run our tests.
The test passed was checker coverage to make sure we have the right thing being tested up, it comes
down to post reservation, which is right here, and we want to make sure, no, that did not actually
work.
So what do we have here?
Why did it pass?
Let's go back and look at our data.
I'll close this window, go back and look and see what I got wrong here.
Test for invalid data.
First name is Jay.
Last name is Smith.
Posted in there.
Get context if it's not equal to temporary redirect.
Aha.
So let's see.
That's the part.
That's the problem.
It's a set up test handlers don't go hendershott go.
What happens when we fail our validation test.
If form is not valid, status the other.
So let's see what happens here.
This should be status C other status the other.
I think that's still going to fail.
I think I missed something else.
Start date, end date.
First name is equal to J.
Is that what I'm actually checking.
First name.
First name has to be at least three characters along, OK, if not form is valid, then it takes us
back there and returns and that should be status the other.
OK, let's see what happens.
Go test.
Got three or seven, wanted three or three, why did that fail?
I must have left something, set the wrong way back in our test start date and date.
Oh, yeah.
Remedy changed that to one.
That's my own fault.
I can't see what's in front of me.
Let's try that one more time.
Go test.
And now it passes and now if we look at our coverage, that should actually test.
Right here, the form is not valid.
Perfect.
So now we have to do two more.
We have to do our insert reservation and our insert room restriction.
How are we going to do that?
Well, we'll do it much the same way we did for one of our earlier tests.
We'll go look at the test repo and we want to test insert reservation and we want to test insert room
restriction.
So what we can do is use this reservations model and we can just do arbitrary things.
So what I'm going to say is if the test if the room ID is to then fail, otherwise pass.
So if restroom ID is equal to two, I'll return.
It doesn't matter what I return for the int.
I want an error errors donu some error and I'll do the same thing down here, but I'll do that next
to make sure I get the right data in there.
So let's go back and do this part of the test first.
Once again, I'm just going to cheat and say copy all of this and put in a comment test for failure
to insert reservation into a database.
And this time I'll make sure all of the data is valid.
So, John, change this comment to say this was built.
Right?
Uh, reservation handler.
Failed when trying to fail in inserting reservation.
Not the best comment in the world, but it gets the idea.
And what response code should that return at this point?
So it's at this point status temporary redirect.
So let's go back here.
Change this to status, temporary direct.
Change this to status, temporary redirect and make sure that we give it a room ID of two, which is
going to generate the failure.
So this should work.
That's valid.
All of that is valid.
Let's give it a try go test.
And it passed.
Let's get our coverage and make sure we tested the right thing.
Scroll on down, this is reservation.
This is post reservation, so hopefully, yes, we're down to only one thing left to check and that
isn't inserting the room restriction.
So let's close that window and close this window and go back to our editor and do our last test for
this particular handler.
So I will copy.
Get rid of that comic that doesn't need to be there.
Copy all of this.
And this time I want to get past the room restriction or the the saving of the reservation.
And I want to test for failed to insert restriction into database, which means this has to be remedy
one.
So we'll pass the saving of the reservation.
But now we want to return something that's going to fail no matter what we do.
So let's go back here to our our test repo and see how we can do this.
We're saying here, if the reservation ID is equal to two, then fail.
And here I can say insert room restriction.
I want to check the model's room restriction that needs to fail somehow.
So I need some arbitrary value that's actually going to fail.
So let me try this.
If our DOT remedy is equal to one thousand, there's one that I know is is just not likely to ever cause
me grief.
Then I want to return a new error.
Errors.
Dot knew some error.
So what I'm doing here is saying if when I tried to insert a room restriction for room ID 1000, then
fail.
So let's go back to our handlers test and see how we can do that.
We have validated it here.
Let's give it remedy of one thousand and this should return a temporary redirect.
I think.
Let's make sure when it fails to insert the room restriction, I get a temporary redirect.
So this should work.
Let's run it.
Go test.
It passes coverage.
Go down to post reservation, which is right here, and that should be entirely green at this point.
And it is all right.
So what I'm going to do now is I'm going to go finish writing these tests myself and then I'll post
a very short lecture, which will just be a slide probably that has all of the code necessary for you
to refer to when you go and try to write the test for the remaining functions.
And you'll see there's quite a few that you have to test yet, some that we've never written a test
for.
But you should have at your disposal now everything you need in order to write the tests yourself.
And I encourage you to try to do it yourself.
And if you get stuck, go look at my source code, but just look at enough that you can verify are you
can solve your problem of the moment, because if all you're doing is copying and pasting someone else's
code, you're really not learning anything.
The only way you learn to write tests or the only way you learn to write code is to write tests or write
code.
So I encourage you to try that on your own and you will bang your head against the wall every once in
a while and you'll be pulling your hair out and you'll be having, you know, some real problems, but
you'll be able to solve them.
You do have right now in front of you, if you've written the code up to this point in the course,
you have everything you need in order to write tests that will give you one hundred percent coverage
for your handler's package.
So good luck.
If you get stuck, look at my code.
And if not, then you've done a great job.
So this gives us enough that we can move on to the next major topic of this course.