Test Driven Laravel
Lesson 6 of 6 · Test Driven Laravel – e06 – Testing Validation, Importing Vue.js & Tailwind CSS · Education
Test Driven Laravel – e06 – Testing Validation, Importing Vue.js & Tailwind CSS
let's take a look at the author management test so up until this point we've done the very basic of an author can be created so let's go ahead and
tackle how to actually refine this test a little bit more first and foremost let's go ahead and run our entire suite PHP unit and sure enough we are at green now this right here this is bothering me
a little bit so I typically have this be plural as in authors slash authors slash post something like that if we take a look at our book we're actually hitting slash books so let's go ahead and keep
it consistent and that's gonna be my very first change I'll go ahead and hit that with an S and let's run our tests of course we get a failure as we would expect on authors management test line
25 and of course that's going to be right when we try to assert something so what we need to do here is go ahead and change our route so this is gonna be authors and we do have the author's
controller already so that'll be nice and consistent and we're back to green quick little refactor just to get started so the next thing I want to do same as I did with the other test is
actually extract this into its own method and we're just going to call this this data and let's go ahead and create a private function for data and this is simply just going to return that very
same array now the reason why I do this and let me show you in the previous test let's go back to the book management test we scroll down here I do basically have that very same private setup and
the nice thing is this when we're gonna test our validation rules then you can use array merge alongside with this new this data to actually override a single field this will allow us to actually be
able to have valid data being validated in only the particular way that we want to invalidate it as opposed to having to rewrite that over and over the next added bonus is that if we add a new
field then we only need to add it to this array right here and all of our tests would continue to run properly so that's just another nice little thing that we get so we did a small refactor
let's go ahead and run the suite and up until this point of course we've been running the entire suite we really should just be running the author management tests so
go ahead and filter down to just that one and of course it's still at green alright so let's go ahead and tackle some validation a name is required a little bit of review from all the
previous lessons so the only thing I will do here as I will copy this but again I need to modify this data so using a Raymer CH we've talked about this before as a first array we'll pass
our array of fully valid data and then as a second array we're going to override just the name field and we'll set that equal to an empty string essentially just invalidating name but
nothing else so if we had a hundred fields here this would only invalidate the one validation rule that we are trying to test against so we'll have to go ahead and save the response out of
this and then we can assert against the response so let's say response let's make sure that the session has an error for name that's the key that we are looking for because that's what we're
testing all right let's go ahead and run actually let's run this whole file and of course we get it failure because it is missing the expected key and we know this to be true because our author's
controller is doing no validation right now so let's go ahead and tackle this let's do it the very naive way first so we'll say data equals requests validate and of course we'll have our array here
which we'll say has a name and the name is required and we do know that it also has a date of birth for now we'll leave that empty so then instead of having to do this request only as we've been doing
we could just use this validated data this will basically ensure that only the valid fields that we are accounting for are being passed through to our create method all right so let's check that out
and we are back to green great let's do the other one for date of birth we'll do a repeat on this and we'll say a date of birth is required we're gonna hit slash that and then
let's go ahead and invalidate DOB let's go ahead and run the test again and we are failing of course let's make that pass by simply just making this required and there we go good job all right so we
have a little bit better validation when it comes to this so another refactor that I want to do is it's going to check out the books controller very quickly if we take a
look at this I have this validate request protected function right in here now this helps me because whenever I need to reuse any validation you just call this one method and everything
works so let's go ahead and do the same exact extraction on this one and that'll help us clean up this code a little bit so we'll go ahead and extract this into a method a nice little function here
that we have and we'll just say validate data is what we would like to call that function and we'll make it protected private protect it really doesn't matter okay so we have that and this just
returns that array so this at this point is kind of redundant we really don't need to do that we can actually inline this all together so let's go ahead and cut it out bring it in here and so now
we're left with a store method with a single line now I do know that this is probably going to change at some point because I'm going to need to make sure that the same author doesn't get created
twice so I will have to do some validation for that but for now we are in the very simple implementation of this our tests are still at green so we're good to go on that now I did call
it validate request and not validate data so let's keep that consistent let me change that right now validate request that does make more sense than validate data so I like that validate
request will be what basically just returns our validated data array again the reasoning behind this is for example if we take a look at our books controller we have an update method and
that is calling the validate request but we also have this store method which also takes advantage of this validate request we would have had to repeat this code right here in two different places
again if I had to add another field to this then I would have to change it in two places and even furthermore I'd have to go into my book management test and added in every single test instead we're
using these nice small helpers that help us reuse as much of our code that could potentially change as possible just a little bit of future proofing for your code think of
it that way okay so really we are at a point in our project where I feel like it's time for us to start to take a look at how to integrate all of this work that we've done into some front end so
let's shift our focus all together let's go ahead and pull in some view and some tailwind that way we can start to manipulate some of this code through the actual browser so let's start off with
the following right now if we take a look at my app that s CSS file we have all of this code right here the level home page bootstrap all together variables there's a lot of stuff here so
why don't we clean all of this out altogether and go ahead and start fresh so let's go ahead and make a quick commit for this just so that we know that all of the changes we made to
authors and books are all saved so I'll actually use the inline editor right here and we could say get status and of course we have all of these files I don't have a package lock Jason here
that also needs to go ahead and be added but for now let's go ahead and add everything that we have in line then let's make a new get commit with the following message work in progress for
authors and change route from author to authors basically just a quick summary of what we just did now this is a brand new machine so it looks like some of our setup is not done and get so let me go
ahead and take care of that right now all right so let me go ahead and change this email right here and let's go ahead and change the name here to be Victor alright so let me go
ahead and uncomment these lines just to make sure that these do take effect and then as it says here after doing this you can fix the identity of the commit by resetting and running this command so
let me go ahead and run that command yep that sounds good alright so that's good to go let's move on to the next thing so like I said I want to clean all of this out so to do that we run PHP artisan
preset now if you're not familiar with presets let me go ahead and run PHP artisan help preset first just to show you what we have what we can actually do is choose one of the different types of
presets that are available if we run the none that will basically strip everything out and then we can run view just to have view because right now we have bootstrap and view so I just want
you so let me go ahead and run PHP artisan presets none and let me show you what that does first let me go back here at the phpstorm and as you see this file totally empty
also my app that Jas file in my resources totally empty and then our bootstrap Jas all this has is just access and it's making sure that our CSRF token are
properly being passed through so this is essentially nothing at all let's go ahead and bring in view now so we'll say PHP artisan presets view and of course now if we come back here we take a look
at app Jas now we have this window dot view and we are requiring view and of course in my bootstrap no changes there nothing in app that scss either however if we take a look at the package.json
file of course view has been brought in as a dependency all right so now we're ready to install NPM for the very first time so let's go ahead and run as suggested here
let's run npm install ok and that is all done let me go ahead now and visit the Tailwind website and start to pull that in let's go to tailwind CSS calm so now let's take a look at the gating
at section and the very first thing we need to do is of course go ahead and pull in through NPM now I will go ahead and save this under my development dependencies and not just my dependency
so we'll add the – – save – def now just in a quick side note of that you have this dev dependencies here but you could have dependencies as well now the way the workflow works where we actually
compile our code using webpack you don't actually need to have any dependencies in a production server so that's why it's better that we add that – – safe def all right so now if we take a look
here we have tailwind CSS great let's keep following the instructions so we need to add this to our CSS so let me go ahead and copy these lines and let's go into my app that s CSS file and we'll
just paste those right here at the top okay let's keep running through these instructions now if you want to create a config file which we do let's go ahead and run npx
notice how this is X and not NPM and px tell Whitney nichts we'll run that command so that creates a tailwind config dot Jas let's take a look back in phpstorm we now have this tailwind
config dot Jas any of your additional things that you'd want to add that's where this is gonna go now right now everything of course is empty and that's okay but we definitely
want to set up this project to have some nice custom stuff in tellen so we need this file otherwise we can't compile our code alright back to the instructions and now we do want to process our CSS
now we're not going to use the CLI if we keep scrolling here we actually have a layer of a mixed section right here so this very first one is just if you want the plain old CSS in our case we're
using sass so this is the version that we want so let's go ahead and copy these options because this line right here it's actually already in there force and I'll show you that in just a second now
the file that this is referring to is the file called web pack mix jeaious and it's right at the root directory of every layer of our project and here it is here's that one line I told you it's
already there so let's add a new one here for options and the other thing we need to do is maybe make this a little prettier let's make this into a newline so now it's
requesting this tailwind CSS function so we need to go ahead and pull in that at the top so we'll copy that line right after mix we'll paste that in and now we need a path to that tailwind config dot
J's file this one now of course this is basically right next to each other if you look over here on the bottom you have tell when config right next to web pack that mix so all you need is just a
period slash tailwind config J s and with that we're basically ready to go let's go ahead and run npm run dev for the very first time this does take a couple of minutes so let's let it do its
thing and we'll be right back okay and we are all done so everything got compiled down for us and we are good to go so the very first view I want to handle is going to be with our authors
and the reason for that is because you really can't create a book unless you have some authors in the database so let's go ahead and start hacking away at one of these views let me go into my
views directory that's gonna be resources views and we do have this layout now this app that blade layout is what ships with level now right now it is riddled with all of this bootstrap
stuff that I don't really need and that's really just the navigation so what are we disable and just comment out the navigation for now I will comment out every single line in that and we can
use the rest of this now the nice thing with this app that blade layout is that it does include your J s already and your CSS all of your compiled stuff is being pulled in here so that's a nice
thing we can get rid of these fonts right here and clean this up a little bit okay so let's change our name this is not gonna be label but this is gonna be for now just library still looking
for a good name for this project so if you have any ideas definitely let me know what we should call this project I've just been calling it library all along ok so as you know
in my authors controller you know that the way that I label all of my views is using authors dot and then the name of my method so the very first method that we need is the create method so let's go
ahead and do creates and this is gonna return a new view which doesn't exist yet in my authors dot create again the following convention authors being authors that belongs to that controller
and then the creates and then they create belongs to the name of this method this really helps me to find the appropriate views for each of these methods without even thinking about it
it's a nice workflow to get into let me go ahead and create a new file here it's gonna be inside an authors directory and it's going to be called create that blade that PHP will go ahead and add
that to get and will get us a at extends what does it extend extends layouts dot app and of course we're going to have section of content let's go ahead and end that section
all right in here we'll just have a div and really just for now I do want to test that tailwind get pulled in properly however I can already see all of my classes here
so I know it came in but let's go ahead and do a BG gray 300 or something like that and let's give this a height of screen that way we know that everything is working okay so we're almost ready
now I still don't have a route for this so let's go ahead and add a new route for my authors let's create a new one this is not gonna be a post but it's gonna be a get and it's gonna be at
authors slash create now another consistency here you don't have to start everything with the leading slash but it looks like I kind of did around everything else so let's go ahead and
keep that consistent so we'll change these routes to slash author and this is gonna hit my create method okay let's go ahead and give it a go very first time we actually pull this up
in our browser so let's go to authors slash creates and sure enough we got tailwind we got everything ready to go all right so let's jump right to this inside this content yes we're gonna need
navigation we're gonna need all that I am not concerned with any of that just yet I want the simplest possible implementation that I can have so why don't we say how about give me a width
of 2/3 and then let's go ahead and have a background of gray 200 and then I want to have this centered on the page so let me go ahead and add a margin X of auto that will do the trick for us if I hit
refresh there's no content there let me add a little bit of content and sure enough so this is centered just where I want it so now here comes the nice thing with our tests it will guide the process
of doing this because if we take a look at the author's management test we know that we're going to need a name and a DOB a date of birth these are the only two things required so we're gonna need
a div we're really going to need three so let's go ahead and create three of them and the first one is going to have an input of type text and that's gonna be of named name and let's go ahead and
have a placeholder of full name okay now let's go ahead and do the same thing with the date of birth so that's gonna be dop we'll say here date of birth and of course down here we'll
need a button and this button will just be called add new author there we go now this whole thing of course is going to need to be wrapped in a form tag so let's just go ahead and take care of
that now and where is the action gonna be well let's take a look at our test our action is gonna be slash authors and it's going to be a post request we've already written all the code to make
this work so really we just need to write the view to make it happen so our method is gonna be post okay now we do need our CSRF token but we'll let the code kind of guide us there
let's take a look at this refresh doesn't look like much right now so let's start to add some classes to this first and foremost let me add some padding let's do padding top of 4 and
let's do that to each of these right here just to add a little bit more spacing yeah that looks better and then let's go ahead and add a little bit of padding all the way around in the entire
thing so we'll say p5 perhaps maybe 6 so p6 that looks good let's start with the button as this is the easiest one let's do a BG blue maybe 400 we'll have text that is white and we'll do rounded
corners all the way around let's check that out okay that's looking good let's add a little bit of padding let's go ahead and do a padding top and bottom of two and then let's do padding left and
right with px of 4 let's take a look at that okay that's looking good now these right here these input types let's go ahead and style them right now so go to the end and let's add some classes first
and foremost let's add rounded so that way the corners are rounded and let's go ahead and add a little bit of padding this will make the world a difference let's add the same exact thing px 4 and
py 2 right away this starts to look like a real website all right so let's make them a little bit wider let's say maybe a width of let's try 32 let's see what
that looks like hmm that's too small let's do width of 1/2 that's good now let's go ahead and Center the whole thing I just feel like that's gonna look better so what we
could do is turn this into a Flex container and then we can say all right go ahead and flex but let's flip into columns and we take a look at this now it should look exactly the same but now
we can say items Center and we can actually Center the whole thing now it looks like we lost our width because it's at half let's go ahead and actually give this a value let's say with do we
have a 64 we do okay that looks pretty good now it looks like this flex is being affected by this form so this item Center will actually have to be in the
form in order for us to be Center because right now we are centering our block but each of the individual items are not Center and I do want everything Center let's see let's go ahead and add
some classes here let's move all of this in here and let's see what happens sure enough that'll fix it so of course because this form is the one that's acting on each of these divs that's why
we need to move this a little bit closer into our actual HTML okay let's add a title to this we'll say h1 add new author and sure enough we have a nice title
let's add a shadow' to this small box here I don't know if you'll be able to see this but it adds a nice little shadow all the way around here and so at that point we're basically good to go
are we ready to test this yeah pretty much so if I go ahead and hit this the first thing I get is Page expired as I mentioned before we are missing the CSRF so let's go ahead and add that now at
CSRF let's go back here hit refresh and now it seems like nothing happened but what is really happening is we're hitting the server we're getting some validation errors back but we're not
displaying them just yet so let's go ahead and do something right here right at the top of this I'm gonna do just a temporary dump of this variable of errors now if you are familiar with this
bear with me for just a second but of course this is our error back whenever we do any validation with Lenovo it returns this errors and this errors is simply just an error back that contains
any validation errors inside so I just want to take a look at what we're actually getting because of that so right now our bag is totally empty if we hit add new a little bit different so we
have two errors as we see here we have one for name saying the name field is required and we have one for date of birth saying the date of birth field is required so we need a way to basically
tap into this make sure that there's one for each one and maybe display a nice message underneath here so let's start with that so right underneath this input field we could say something like at if
so we need to check if it has errors actually before I do this let me erase this for just a second let me show you how to do that so we could say errors and then we have this nice helper
function of house and to that we could pass name so check this out if I hit refresh right now we get false now if I go ahead and add a new author then I get true meaning there is an error for name
great so we're gonna use this let's go ahead and copy this out and again let's go back to what we were doing before let's say if it has an for name we're gonna do something so
let's go ahead and if we have an error maybe we can add ap tag and let's go ahead and add some classes here of text read let's try 600 at first and now I want to
grab that error message so we can do that by saying errors so we have this errors but again each could be different so all we need to do is grab the first one give me the first error right and
we'll tackle the first one in each instance all right so let's take a look at it in the browser so of course it has false if I hit this now we have the name field is required exactly what we were
looking for we can actually stop dumping this errors up here and let's do something very similar with our date of birth I had the same thing but this is not gonna be for name but rather this is
gonna be for date of birth and now if we click add a new author we do notice that we have this name field for both of them okay no problem easy fix there all we need to do is pass in a field name to
each of these first calls so we'll add name and then DOB and now let's take a look at the difference and sure enough now we get the correct error okay so this is working this is good this will
work in a lot of versions of level however there is a new helper and that is the at error helper so why don't we refactor this to see if that's any cleaner for us so let's check this out
I'm gonna actually comment this out just so that we see a side-by-side so we have this new error and two error we could say name so basically if you have a name then let me go ahead and copy this P tag
right here and then we don't need to do any of this as a matter of fact we can actually just use message and message is provided for you inside this error and then we'll say and error and let's check
out on the browser refresh same exact thing however we don't have to check if it has a name we don't have to do this first or anything like that I think it's nice and clean let me go
ahead and keep this and let me refactor the date of birth as well so instead of name we're gonna do DOB and we can get rid of these three lines we have a nice little helper to do that
very cool very easy so again this is kind of new so if this is not working for you then it means that the laravel version doesn't have this feature just yet so go ahead and do the other version
I did want to show you both just so that we see how that works okay so let's go ahead and try to validate this I'll say Victor and then 0 514 1988
add new author and sure enough we tried to hit our database and now we don't have one set up let's set up an SQLite database very quickly just to wrap up this lesson so we can say touch database
and then it's gonna be called database that SQLite now if you don't have touch available because you're in Windows then you're gonna have to create this database that SQLite file inside the
database directory manually just go ahead and create that and then we do need to change our env so let's browse through here dot E and V right now it's set up to MySQL so let's change that to
SQLite and erase everything else okay so with that PHP artisan migrate and there we go okay let's go back to the chrome and let's see if we can make this happen now refresh and sure enough it doesn't
show anything but believe me this did get added to our database so how cool is that we were able to write all this code and we know that all this code works and we did all of it using TDD and then we
just simply made a view and we know that the code works we're not worried about adding this authors and database and all of that we already took care of that so we don't have to worry about it that's
the nice thing of using a TDD workflow so with that we'll go ahead and wrap up this lesson a little bit long but I feel like you get the point we did a lot in this lesson so go ahead and review it if
you have any questions at all don't forget to subscribe to the channel if you have any questions on any of the level stuff I do have a full level 5.8 from scratch so you can visit any of
these concepts and learn anything that you missed in this episode so in the next lesson let's go ahead and keep working out these views
Let’s take care of some last minute validation for our Authors flow and then let’s shift our focus to the front-end. First, we remove all remains of Bootstrap and then install Vue and Tailwind CSS. Finally, we get to see all of our code that we’ve written through TDD be accessible through the browser.
For the best experience, follow along in our interactive school at https://www.coderstape.com
DigitalOcean Referral
https://m.do.co/c/7dce5364ef4d
Resources
Course Source Code
https://github.com/coderstape/library
Hit us up on Twitter with any questions or comments @codertape (https://twitter.com/CodersTape)
About This Course
We are tackling a brand new series to showcase a real-world workflow that you may adapt to your liking. We will be building a library management software for our local library that will include the ability to checkout books, reserve books and much more. We will be doing this through the TDD methodology, come along as we dissect Test Driven Laravel Development.