18. Showing the book edit form


So the next goal is to edit a book. The link will be here but we're going to dive straight in and start to write the test out
so we can see on that page that we've got everything that we need. So let's go ahead and start with writing out a test. We'll go ahead and make a test in here called book edit test. So this will be to show the edit page and then we'll create a book put test
to show that it actually updates in the database. Now let's make sure we use the pest flag here and let's go ahead and open up this test and start writing. Now before we do anything let's go ahead and grab the refresh database tray over here
and we'll pull that in and let's think about what we need to do. So the first thing is we can't access this page if we're not authenticated. It doesn't make sense. So let's say it redirects unauthenticated users and we already know that we've got
some helper functionality for this so we can just very easily say expect guest to be redirected for and let's think about the url that we want to use. It'll be books slash the id of the book and then slash edit. Okay let's go ahead and run this test on its own.
So tests feature book edit test and of course it fails because we don't have a page here. We get a 404. So let's start with actually building this page out. So we're going to say make controller and this is going to be our book edit controller
and we'll hook this up over in our roots. So roots and web and let's go and just put this underneath here. So it'll be books slash the book id and edit and that's going to use the book edit controller. Okay let's rerun the test again and let's check what we've got.
Okay so invalid root action. Let's open this up and let's add an invoke. Let's just do nothing. Rerun and now we get a 200 of course because we don't have our middleware.
So we create a constructor. We add in our middleware and that middleware is going to be auth. So now we should get a passing test. So we know that this page works but what we need to do is make sure we actually see the
book details in this form. So let's write a test out for this first of all just so we can kind of figure out what information we want to see. So let's say it shows the book details in the form.
Again we're going to make this fairly rough. You can refine it later. What do we need to do? Well we need a user.
So that's the first step. Let's go ahead and create out a user here. The second one is going ahead and adding the book to that user's list of books. So we're going to go ahead and attach that book and assign it at the same time.
We've already done this already so it should be pretty familiar. We create that and of course pass in the pivot information as well. So let's set this pivot information to reading for example. We should see that within the drop down and that should be active within the drop down.
Really importantly. So let's think about our expectations. First of all we want to go ahead and act as that user. We want to go ahead and hit that page.
So it's going to be slash books but now we need to add the ID. Here we could get away with just using any ID. But here we actually need to pass in the book ID slash edit. And what do we want to do?
Well let's just first of all assert that this is okay and that it works. Now if we go over and hit this at the moment we have to just pull the user model in. And if we go ahead and hit this that works of course because we're just hitting that route. We're not returning a view.
Let's assert that we can see something on the page here. And let's say that we want to be able to see the book title. And we want to be able to see the book author. Now again this is pretty rough because the book title and the book author could be shown
anywhere on the page. We're specifically saying that we want to see this within an input. But we'll kind of just leave it like this for now just to keep things simple. Now obviously this is going to fail because it's not going to see anything on that page.
So we don't get them two things. So now we can just start to fill this in and output what we need. So if we come over to our book edit controller let's return a view in here and fill this in. So we're going to say books.edit.
Let's head over and create this in our resources. So let's come down here to books. Let's create edit.blade.php. And we can pretty much steal the create.blade.php template.
So let's pull this in and let's say edit book at the top. That action we'll go ahead and get rid of for now because we're not sure at the moment. Of course we want to edit the title. We want to be able to edit the author.
And we want to be able to edit the status as well. We still want to iterate through all the statuses. Really important because we need to pre-select one and allow another one to be edited and or changed and we'll just change the button here to edit book.
So let's go and just rerun this test. It still fails. That is of course because we need to pre-populate the title and the author with that information. So simple as going ahead and setting the value in here to the book title and the author to the
book author. Now what we also want to be careful of is that we want to keep persist old data in here. So we're going to use old and then we're going to say title. And otherwise we're going to output the book title in here.
Now we haven't got the book passed in at the moment but let's just grab this value and put the same thing in author here. And let's try this out. So at the moment it's not going to work.
We get a 500 because we don't have book being passed down. So let's pass that book down into here that we get through into our invoke magic method. And there we go. That should be enough if we actually write book and not best to pass this test.
And there we go. We have our test in there. Now the next thing we want to make sure we see if we just head over to our book edit test is a pre-selected value of reading.
Now if we actually come over to that edit page now. So let's look this up in the database and we've got let's just say book four. So book slash four slash edit. Now at the moment that says want to read.
But inside of our pivot table that is actually want to read. So let's pick a different one. Let's pick book two. And it still says want to read.
So we want this to be pre-populated. So let's go ahead and write exactly what we want to see. So let's say assert C. And this time what we're going to do is add some markup in here.
Now because we're going to be adding markup which is going to look something like this option value equals reading for example. And let's end that option there. And then put reading in here.
That's what we want to see on the page because we want this to be selected. So we want to see this markup on the page with selected for reading because that's what's in the pivot. Now at the moment this isn't quite going to work because
Laravel is going to escape these characters. So we can actually pass false in here to not escape these when we are looking for something. So let's go ahead and just rerun our test. And of course we don't see this in here because it will have selected
the first option in that list by default. So we want to change up this iteration or at least add something in here based on that pivot. So inside of each of these options let's go ahead and add a ternary in here and say book, pivot and status.
And if that equals the key that we're iterating through then we're going to output a space and selected. Otherwise we'll just output an empty string. So remember there's no space here.
Space comes in here. Let's run our test and see what we get. And it still fails. So we get a 500 error here.
Let's just have a quick look at the top here. And yeah, we get attempt to read property status on null. Now the reason for that is over in our book edit controller we're accepting a book in. Let's just die dump on that and just see what we get over in here.
Now that's not going to have any pivot information because this is going to be looked up directly in the database, not within the context of a user. So let's fix this up and relook this up via the user. So we'll go ahead and pull our request in here or you could do that with the auth helper
and we'll say request user books and let's find the book ID that we get through. So not an ideal solution because technically we're performing another query, but let's go over and try this out. Okay, so that looks like it worked.
And of course our test should now pass. Okay, great. So the last test that we're going to write is, obviously we don't want to be able to edit a book that doesn't belong to us.
Let's just test this out in the browser first of all. So we have got one user in here at the moment. Let's just duplicate this and create out a new user just so we can play around with this. And I'm going to go ahead and over in book user assign this one to user two.
So we've got book ID four here. Let's go over to book ID four and it looks like we can edit this. So we shouldn't be able to do that because of course we don't own the book. Now we'll refactor this later because I think the best option here would be
authorization using a policy, but let's wrap this in an if statement because if we can't look this book up in the context of the user, it's of course going to fail. So we can just go ahead and abort this with a custom 403 status code. Now that actually did fail when we, if I just come back to it here,
because of course we can't look that book up in the context of a user, but we get a 500 error here and the more appropriate thing to do would be to throw a 403, which is really what we want to test for. So if we just make sure that we say if that's not found, we should here see a 403 forbidden.
Great. So we know that that's not working, but of course we want to cover this with a test. So when we refactor this later, probably to a policy, we know it's going to work. So I'm going to go ahead and copy and paste this test down here
because the structure of this is pretty much the same and we're going to say it fails if the user does not own the book. Okay. So what do we need?
Well, we need a user that can sign in, but we need another user who owns this book. So we're going to say another user books attach this book and then down here when we try and access this, we can assert that it's not working. So let's get rid of these assertions here
and let's pretty much just fill in what we've already seen. So assert status 403. Okay. Let's rerun this test and there we go.
We get green. We already know it didn't work over here. So that's pretty obvious. But now when we do refactor this later, we can easily see whether we've broken it or not.
35 episodes4 hrs 19 mins


Pest is a PHP testing framework that brings beautifully simple syntax to your tests, without sacrificing on features. In this course, we'll get up and running with Pest in a Laravel project and write tests for a real-world application that we'll build along the way.

You'll learn how to set Pest up in a Laravel project, write tests with Pest's built-in assertions, generate code coverage, and more.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!


No comments, yet. Be the first to leave a comment.