React UI Library Structure, Storybook and Tests

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's refactor a ui library to get into shape by setting up its file structure storybook and also its unit tests let's get right into it okay so a couple weeks ago i did a huge hour-long video where we put together a micro front end setup and as part of that we created a ui library that exposed this app shell which is this header section as well as the nav bar over here and it was all set up with react router six and it was super cool but i gotta say the way that i put together the ui library was kind of janky and half-hearted and i've been asked over the years how would i structure a ui library so i'm going to show you how i would do that and we'll restructure this little ui library and we'll go and add a storybook and also unit tests to it it's really fun actually all right but before i get started let me just say this is in a mono repo but it doesn't just apply to mono repos you can apply this to just a single repo as you please it just happens to be in a mono rebo all right so let's start it out okay so the first thing i'm going to do is i'm going to clone this project over here in mf router 6 and the link to that is in the description down below i'm going to copy this and i'm going to go over over to my terminal and i'm going to get clone it and now i'm going to bring it up in vs code okay so first thing i need to do is do pm pmi and that's going to go and install all the packages and get everything all linked up in our mono repo but before i get there let's just do a quick overview of what we got we've got two apps we got the movies and the playlist app and we got a whole bunch of packages in here and the one that we're gonna be playing with is the ui package which at this point just has a package.json a type configuration and an index.tsx file that contains uh just the one piece of ui that we're exporting which is the app shell which is that header and then the nav bar along the side so this isn't that great i admit i'm sorry okay anyway all right so we've done our our pm pmi so let's do a pmpm dev just to make sure that everything actually still works out of the box and this is going to bring up all of those libraries compile all of those libraries and then compile our two apps and if everything goes to plan we should basically just see exactly the same thing here which we do yay okay cool and go to our playlist we can add items to our playlist there you go doctor strange and lost city cool okay we don't really care about any of that what we're caring about more is this header bar up here some movies and the nav bar over here and that's all implemented with this app shell okay we really don't honestly care what the app shell does either honestly we just want to go and restructure this library to make it more sane okay so first what we're going to do is we're going to just move around the files a bit so i'm going to go over and create a source directory which kind of makes sense so i'm going to have ui source and for each component we are going to expose we're going to have a directory so i'm going to call this one app shell as you'd imagine and i'm going to go take the index.tsx and drop it into app shell but i don't really think that's actually the right way to do this what i'm going to do is i'm going to change this to app shell.tsx so the component is just going to have the name of the component within that directory and then we're going to have an index file in every one of these directories that is just going to export that component so i'm going to export star from the app shell and then over in our new index.tsx that we're going to put at the top level we are going to export star from source app shell okay so what is creating this little directory here given us well it's given us a place where you can put all kinds of cool assets we can put a storybook file that has all the stories in it we can put a unit test file that has all the unit tests in it we can put a css file that has the associated css modules and the great thing about that is we decide to move any of this stuff around later if we're going to pick up app shell and move it to another package basically just pick up that one directory and you pretty much have everything that you would need for that component theoretically i mean if it of course depended on other things in the same package then you'd have to kind of rejigger that a little bit but you know it's still it's a nice way to kind of contain everything and this is pretty standard i've definitely seen this in a lot of projects so i you know it's a little pedantic i would say but i think it's fine okay so the next thing we need to do is make sure that of course worked and it looks like it did so thumbs up to that awesome okay it's cool so let's get started adding in the storybook so i'm going to go into packages ui and within that i'm going to do pmpx storybook init so this is a nice little handy helper function from a storybook that goes and sets up our project for us and if you are not a monorepo fan you will have another reason to say that you're not a monterey bow fan coming up here in a second as it doesn't quite like being inside of a monorepo it's going to give us a warning about workspaces and actually unfortunately not work but it's going to get us pretty close it's going to go and set up some stuff which is great yep and there you have it so i blew up on this workspace thing but what it did do is it actually created this dot storybook inside of here which has our storybook configuration in it which is great it also created a stories directory down here which has some example stories built into it what it didn't do is update the package json with all of the dependencies so we need to go and manually add those so let's go and do that one by one okay the first one i'm going to bring in is storybook react in development mode and that's just the basic storybook mechanism customized to react so storybook slash react and the dash d is for development mode so that we don't bring it in in production mode which makes sense next thing we need to bring in is react dom the reason that we're bringing in that is that webpack server depends on it as does storybook and we don't have it we didn't have it normally as part of this package because it's a ui library package so we're bringing it in in development mode in this case next i'm going to bring in the storybook testing library also in development mode all of this is in development mode and then i'm going to bring in a set of storybook add-ons including links essentials and interactions and this would all have been done normally by that storybook and it it's just because we're in this monorepo so don't hate on storybook it's fine you know it's mike my thing about having it in monterey but okay so we've got our dependencies so the next thing we need to do is go over to package.json and create a script where you can launch it so i'm going to do i'm going to do storybook and i'll say start storybook and i'm just going to give it no port number let's see what happens so i'll do pmpm storybook okay it looks pretty good and this is basically all of the out-of-the-box storybook stuff so we've got all of these buttons in here we've got a header yada yada this is their kind of demonstration of all the things that you can do with storybook which is great but we don't need any of it so we're going to get rid of it we're going to delete all of those files and what we're going to do instead is create an app shell dot stories.tsx in the same directory as the app shell so this is going to be our story for the app shell and why is that going to work well if we go over here to i think main it basically tells us where it's going to source all of those stories all of the have all the add-ons and the framework but anything that says dot stories dot jsx tsx and mdx which we'll get to in a bit is going to be included as one of the stories so that's why you can have that app shell.story.tsx and it'll work okay so i'm gonna import some stuff i'm gonna import react i'm going to bring in component story and component meta from storybook react as well as the app shell from the current directory so the next thing we need to do is define the component for storybook and that's going to use that component meta so we're going to say that the title here is app shell and that the component is that app shell and then we need to define a template so this template is what it's going to use to render the app shell in the with the different stories so it's going to have a component story with the type of app shell bring in some arguments and then it's going to give all of those arguments to the app shell but we're also going to go and give it some required stuff for example the routes and the nav links which are required for this particular component and then finally we're going to go and export any stories we want so in this case we're going to export the primary story and that all we need to do is just bind the template to that and give it some default arguments so in this case my app would be the title that we want so let's hit save here and see we get over in our storybook alright so now we've got app shell over here and hit primary and ah check that out it's even got some togglers for light and dark mode click on those and we really didn't have to do any of that right so that how cool is that that is really nice one thing is a little bit irksome is that there's a little bit of padding in here and that would be normally fine but i think when you're showing off like a container like this what you really want is you want to just you know take up the entire frame so let's go and get that going so to make that change i would go over into my configuration for storybook in preview.js which has our parameters and i'm just going to set the layout to full screen so it's save and let's see yep there you go now it's gotten rid of that padding and now our canvas stories take up the full frame okay so the next thing we're gonna do is we're gonna go and bring in jest and that's gonna give us the ability to unit test our components and then we're gonna add another component and show you how to do stories slightly differently and test that one so we're basically going to do this all over again just to give you some sense of confidence as to how to do this but before we do that let me just go and add to the repository our current state so i'm going to say that we've added storybook and that will give us a nice fallback if things mess up and of course in the meantime if you're liking this video hit that like button if you're really liking the video hit that subscribe button okay so let us bring in everything we need for jest so we're going to bring in jest as well as ts gest which makes it easy to do typescript based tests as well as type suggest so that gives us all the types for things like it and describes and all that as well as the testing library for react that's going to give us a nice way to be able to kind of look at the components once they're rendered and render them and then also the jest environment for the js dom which you need when you're going to do dom based testing which is what we're going to do here because we're doing react components we're doing like node stuff that's already built in i think and you just have the just test environment of node and now we're going to set up the typescript configuration by doing a mpx with ts jest and say that we want to initialize the configuration this is just a handy little helper that sets up the jest config file over here and sets up the preset with the ts jest but we also want to go and change that to js dom because we're doing ui testing okay so next thing we need to do is over in here in package.json we create like a test so we'll say that we want a test and to implement our test we will call jest test with jest yay all right so let's go make our first test so we'll go here create a new file call it app shell dot spec dot tsx and into there i'm going to bring in render from the testing library for react and also our handy dandy app shell and now we're going to describe say app shell i guess that's fine and we need to give it a function and we'll say it renders okay cool so now we're going to render an app shell but i'm not going to use a snapshot test for this i'm not a huge fan of snapshot tests and we need to add some parameters here for our app shell so i'm just going to set the nav links to an empty array i'm going to set the routes to ah we'll give it a route in here so we'll say that we want a home route and then we want the element to say something like div hello cool and finally we need a title and that should be something like foo so the output of this is actually really cool so we picked a container here we don't have to do that so i'm going to go and take a look at all of the stuff that comes out of here we can do all kinds of find buys and the one that i want is query all text all by text so i'm going to expect that if we query all by text foo it will be yeah it'll have a length of one that actually that's that's fine that's cool uh but i'm gonna start off with fubar here and we're gonna try it out all right now let's give it a try with our pmpm test all right looks like we have one failure let's go take a look and we can see that we expected to have a length of one what we got back was a length of zero and where did we get that well we looked for fubar and we expected to have one and we got zero so let's take a look so you're looking for foobar when in fact the title is foo so let's change that to foo instead of foobar and let's run it and there we go it passed so we can also look for this hello over here because the slash path is going to be the one that is rendered by default so let's check for that as well so let's see and we'll do something different here we'll say to be truthy all right now let's run it and the test toe passes awesome cool all right so let's do this one more time we'll go and create another component so i'll show you how to get started and go all the way through it so i'm going to go and close this out and we will create a component called a product card so i will go and create a new folder here called product card inside of source and then we'll start off with the implementation of the product card itself so the product card dot tsx and into that i'm going to bring some mantine stuff i'll bring in card title button text droop and paper and that'll help us make our product card and then i'll bring in react so that we can specify it as a react functional component and we'll do that down here say product card is a react functional component awesome and it's going to take a title and a description and it's going to return so a product card is surrounded in a paper it's got a little bit of shadow and radius on it and inside of that is our card that has a title section it has a description and then a button that says buy this so now let's get it out of our library and that starts with putting an index file in there and that index file is going to export everything from the product card and then we'll go and add it to our index.tsx and so what should we do first i think we should go take a look and see how it looks so let's do product card dot stories dot mdx i'm going to use the markup syntax for our stories this time this is really cool this actually came out just recently with storybook and it's a really fun way to be able to specify stories using an extended markdown syntax so what does that look like so over the top we're going to import some stuff from the storybook meta story in canvas like we had before we're going to get our product card from our local index and we're going to say what this story is so we're going to give it meta where the title is product card so it's going to show up in our storybook is product card and the components can be a product card and then we got to do that template thing like we did before so we're going to export templates so so far it kind of looks like like tsx actually but now we can start adding also some markdown syntax so i can add in for example hash product card like hey it's the product card stories and we'll say let's define a story for our product card component and we'll just do that so we'll say we got a story the name of the story is basic and now just like we have before with args over here in like app shell stories we do that this way but in mdx we can just make it part of this story tag and then we just bind that template in there so let's take a look let's try it out so once again pmpm storybook all right well that's a pretty decent looking product card but even cooler so currently i'm on this canvas tab if i click over here to docs this is when we really see that mdx so we see the product card stories which is this line up here let's define our story which is this line down here and then we got that story in there in fact wouldn't it be cool if i had one of these that said like code on it so i could actually see the code turns out that is super easy barely even an issue so we can just do for example we can drop it in here with a canvas and now when you wrap this story in the canvas we get this awesome [Music] show code down here and now we can actually show the code how cool is that storybook is just freaking amazing honestly so the next thing to do is add a test so let's add that product card dot spec.tsx and let's just bring in our respect from the other one so i'm going to go and copy this and paste it into our spec and it is not a app shell as a product card so i'll go and change that and let's see so what are our inputs our inputs are title and description so let's say that our title is pokemon go and our description is pokemon go game and let's just look for that pokemon go so let's see pokemon go to have a length of one give it a try so now we'll do pmpm test and run our tests so now we've got two different tests one for product card and one for app shell and both are passing but let's you know pokemon stop here i should have gone and done a failing test before i did a running test so there we go let's look for pokemon stop and yep it fails because there's no pokemon stop switching to pokemon go again and it should work yeah cool all right so here we go we've got a really nicely factored ui library okay so let me clean up a little bit here and i will check all that stuff into github and get it over to you of course in the link down below but let's just talk about a little bit about what we've done here so we have created a source directory as opposed to having just everything at the top level and then within our source directory we have one folder for each one of our components so that would be our app shell and our product card and then we have all the assets for each one of those components in that directory we've got for example with the app shell we've got the component itself we've got the storybook stories that explain what the component is and show it off we have our tests if we had some css it would also be in here and then we've got the index which goes and exports that so that it can be then exported by the index of the whole project itself okay cool and i would say if you have a really complex component here if app shell for example were to break out like a header and a nav bar as different components i would just personally have all of those in that same directory kind of as a group unless i was going to independently expose those so at this top level you should only have components in my opinion that are the components that are exposed publicly by the library if there are sub-components for each one of these then those would just be additional entries you know at the top of that or somewhere in that directory all right well i hope you enjoyed this and i hope you got some ideas for how to structure your ui library of course you can do it any way you want look at all these awesome tools like storybook and just that you have at your fingertips it's really great stuff of course in the meantime i would love to hear from you and how you do it in the comments section down below and if you like this video hit that like button and if you really liked the video hit the subscribe button and click on that bell and be notified the next time a new blue collar coder comes out
Info
Channel: Jack Herrington
Views: 38,844
Rating: undefined out of 5
Keywords: React UI Library Structure, React UI, React Storybook, React Tests, jest react, react jest, react unit testing, react storybook, react ui testing, react ui testing jest, react ui storybook, react ui library, react ui structure, storybook react, react ui test, reactjs testing jest, reactjs unit tests, reactjs storybook, reactjs ui structure, react unit tests, react unit test
Id: NgkYH97Z3nk
Channel Id: undefined
Length: 22min 49sec (1369 seconds)
Published: Tue Jun 21 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.