Check out a free preview of the full Design Systems with Storybook, v2 course

The "Play Functions" Lesson is part of the full, Design Systems with Storybook, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Steve uses the play function to simulate user interaction. Tests can be added to stories to ensure the UI responds appropriately to different interaction scenarios.


Transcript from the "Play Functions" Lesson

>> What we're gonna talk about next is all the promises I made to you about testing things and validating things that work the way do. What if you can pull a lot of what you have in your test suite because we're all maybe you're better than me. We're all really good at writing unit tests we're kinda good at writing those large like playwright tests component tests.

And what if we could use storybook to make testing easier, right and have, that things actually work the way that we want. And there's a lot of really great functionality that will take the tests that you hate writing the most. You're gonna like them, but they're gonna be a lot better.

And we'll show some of the tooling involved so you can make sure you're not breaking stuff cuz two components, fine. 60 components not fine, right? Especially if you've structured things do large scale color changes and stuff like that. Kinda one of things we're talking about is there's I've talked a lot of stuff about this idea of testing our components and stuff along those lines.

Yeah, there's a lot of visual tests. There's also this idea of interaction, there's some things that call out button, right? All right, fine, right? I can look at those and I can see them. But there's a lot of our UI that you have to actually have to touch.

These will always vary somewhat, right. And could you just write stories that put the component in that state? You could argue a lot of times you should, right, cuz that's easy. But sometimes, there's no real way to say, hey, if the input field is disabled, they shouldn't be able to click on it and type into it, right.

You can't really set the scene like that too much. If they click on this thing or a little to do list, okay, they enter something in and hit enter. I would like to see it on the page, right? All those things are one level kind of above and beyond what you might see in a just regular old story.

So we got a whole bunch of different use cases that we could do here. Let's consider this text area that is effectively an old school Twitter textbox where it should at least get yell at you and change its state in the situation where you go under 140 characters.

You go hey Steve, isn't it 280 now listen, put it 140 this textbox was annoying enough I regret that it wasn't 10. So leave me alone. But we wanna be able to simulate that, okay that we can that it does change state as we go in there and that this count reflects the number of things in there as well.

Luckily, the integration of this in storybook is shockingly easy. So, let's take a look at it. That text component does exist. So, we've got a task list that will play around with anyway, later. But we've got this text area, and it's mostly set up already. And what we wanna do is actually create some stories around it.

So let's go ahead and we'll say yeah called default, like that suggestion. Let's see what it looks like in storybook with no args because yeah, it's not really a primary text area. It's just like a text area if we didn't do anything and here it exists now, there's my text area.

Okay, I could I've got disabled not disabled, required to get the font little dot, that's great. Some placeholder tags, all that kind of fun stuff, it's all wired up. It's got a dark mode, whatever. So you can go look at that code if you just wanna see in other examples that is in there for you as an exercise reader.

But we want to create a second story and say export car show what the disabled one litre so we'll go make that since, the auto complete was there for me. But what I want is export cost with count, and that'll be a story as well. I'm just hijacking the max length, which is a built-in property on text areas that I don't think does anything.

Things that I learned preparing for this is how input fields you can have a validity check? Blowing past the max length on a text area does not trigger the DOM's invalid pseudo selector. So that's fun. So we'll say 140 characters and what I should have then is you notice the space in here as well.

So if you use a cyclic Pascal case if you start with a capital letter. We've got that in place where we get this little count here, and ideally big count goes up, and this is where I regret 140 characters. The whole thing should, we'll take a look at why that part didn't turn red.

It does in dark mode. It's the way you need visual regression tests that you didn't undo to get back to the starting point of the workshop. But yeah, so, [LAUGH] you know what? We'll work on it in dark mode. We'll put it back in there, too. So it turns red, but at least these turn red down here as well, so on and so forth.

We'll debug that in a moment, that's annoying. So what we wanna do is to say, hey, one want to type in this field and like that count should reflect whatever you typed in there, right? To if they blow past the amount, I wanna validate that, it does have the additional CSS classes that I'm expecting.

And I don't want it to context switch and deal with also then writing component tests. Because those are always the ones that I skip. But also the idea of breaking this stuff out in storybook means that it's also isolated, easy to component test as well. And so we've got the storybook test and you see I have some basic things in here.

I think that it is true that storybook seven and earlier used testing library, I think eight might be something different. It doesn't really matter, it's abstracted away. It's under at storybook test and what it is under the hood is not super important. But if you've ever used something like testing library, which is framework agnostic in so far that there is a flavor for most of the puppy frameworks.

Including just a regular, it is a set of libraries for go find the selector, and then simulate a click so on and so forth. So, we've got to expect, which is if you've ever used any testing library, it does exactly what you think it does. Within just help scope the selector and user event simulates user events, okay.

So let's start with the easiest possible thing. We're gonna say play. And there are you have container in here. I think you've also got what args were passed in. What are types, you get a lot of metadata, as well. I don't actually want the container I want the canvas element.

That is the playground that I am in, right. So we have that and we'll say is canvas equals that within canvas element. So this is now everything I now we're only looking Inside of our storybook canvas. So what we'll do here is we'll say, don't ruin the surprise, const text area equals canvas get by role text box, text areas have the aria role text box.

If you wanna ask me why isn't text area, I don't make the rules around here, I just tell you the answers. And let's just start by doing something really easy. We'll go and just to demonstrate this sure we'll do a weight user event dot type. And if you're not running a test and you're not waiting for to be filled in, you can skip the await but it's not hurting anyone.

But If you do forget the await asked me how I know this, your tests will fail and you will lose at least 10 minutes of your life. Before you remember why your tests fail when it's clearly in the box because JavaScript is hard and asynchrony is weird. This is Ruby, we wouldn't have these problems, but we'd have a different set of problems.

Cool, and you look back at our story, the cursor is flashing in there, right? Because we went in there, we typed, hello world. I'm gonna, if you watch very carefully, you can see the letters go in there, right? And so it is simulating that user event and who thinks that passes an accessibility test?

And so we've got that in there as well. So we've got 13. That feels right. Do I really wanna count the number of letters in hello world? I do, so what we'll say is cons input value is hello world. I'll put that in there. I don't like magic numbers.

And we'll say that we expect the we need to count and one thing that I know that you don't know that I know is that the actual count itself, I have this data dash test ID length. So this is not magic. I put a data attribute to select it easily with my tests in here and so what I'll say is cons count equals canvas dot get by test id length, there we go.

I am better at typing when I'm not standing on a podium I promise you. Cool, and then we wanna say that we expect that count to have, it's only that to have text content that is equal to input value. And because Typescript has saved my butt so many times, but when it gets angry at me, it's like, lengths that could actually be undefined, I'm, I know that it's not, it's a DOM node.

So we'll say, too strange to keep Typescript happy with me. And what should happen now is if we go in here and we look at interactions, first of all, if it couldn't find the text area, the test would fail everything that you do technically counts as an expectation.

So you can see that, it did successfully type in there, right? And so if he couldn't type in there for some reason like your test would fail but then to it did go look in there and saw that the text count was in fact, correct, right? So now you can refactor away and this is not even really just the design of this is the functionality, right?

And this test will run every single time you change the code in your browser, right? And again, if you were not on a 14-inch laptop, zoomed in to an unreasonable, to a text resolution or screen resolution from 2008, then you would be able to work side by side.

But, you can also do things like go back a step and step through everything as well. Really kind of a powerful set of tooling.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now