Snapshot-driven Development Capture Visual Tests in Flow
Michael Chan shares his expertise on modern practices in component building and testing. This talk primarily revolved around the utility and alternatives to Storybook, a popular tool for developers building component libraries.
The importance of evaluating different testing tools to find what caters to one's specific needs was also underscored. Preference was expressed for the React testing library, due to its focus on accessibility, with other tools like Chromatic and Storybook also receiving commendation.
However, certain limitations of Storybook were pointed out, suggesting it might not serve all React developers equally. As an alternative, the 'Component Story Format' at the core of Storybook was explored, with a tic-tac-toe tutorial in React used to demonstrate its capabilities.
The conversation concluded with the optimism for a future of simpler, less tool-reliant component testing.
Share this talk
Transcript
I was going to start really dramatically, and then I realized that I was following Saran,
who is one of my favorite storytellers of all time, and I just, best creator ever. Like I feel a little bit nervous, because like Saran, like a hero of mine. So anyway, I'm going to try. I'm going to do my best. All right. Let's go. Thank you. Thank you. Thank you. Okay. All right.
Let's talk about our humble planet, Flat Earth. Flat Earth isn't alone. There are nine flat planets that line up next to the sun. Clearly this is a top-down view, because all the planets are flat. Yes, nine, count them, flat planets.
These nine flat planets don't just line up next to the sun. They move around the sun, all at different velocities and rotations, and the angles with which they orbit the sun are a lot different, not on a flat plane, unlike the planets themselves, which are in fact flat.
These nine flat planets orbiting the sun at various rotations, velocities, and angles themselves have moons and meteor belts that orbit them, orbiting at various rotations, velocities, and angles. Of course, we know that the moons aren't flat, despite the fact that we've only seen one
side of ours. And the star, these nine flat planets and their spherical moon's orbit, is also traveling through space. Of course, this image is incorrect, because our solar system is not a vortex, it's a helix.
But most importantly, vortexes aren't flat, and like planets, but not the moons, our solar system is flat. This is how I see system design, orbits, rotation, gravity, cohesion, dependence, independence,
visible and invisible forces all working together to create something holistic and majestic, epic. So you're meeting me at a very interesting time. It was about 14 years ago that I diverged from my path of general web development into
the world of design systems and componentry. I've always been a very obsessive type of person, and as I was building applications, I kept gravitating towards these micro-interactions that people would experience.
I grew up in the age of progressive enhancement, and I was having a conversation with Adam Argyle yesterday, and we were just talking about how it's a really scary thing to just acknowledge and embrace the fact that your web app will be used by hundreds of thousands of different people, all coming to it from different browsers and capabilities and abilities,
and that they will all have a different experience, and you can't control all of them as hard as you might. So over these last few years, I've developed a lot of ideas about how to build systems, how to build components and component libraries in a way that appreciates the solar system
that they exist in, and not just as the end-all, be-all, or as part of a vertically integrated system. Now there's a handful of tools that I found in this pursuit in 2020, and this is kind
of, I give some talks around this, this is what I landed on, TypeScript for static types in your development environment, at a time, Jest and JS DOM for those unit tests, my crossover integration layer, and then I really like React testing library, or testing library,
for its ability to force you to think about the accessibility of your components. Now from a component perspective, and a user interface perspective, I did feel like the integration layer, and if you didn't notice, this is kind of like the testing trophy on its side.
The integration layer is big and massive, and it felt like two kids in a trench coat for me. And that second piece was this visual testing piece of it. And I think up to that point, the tools have really not been very good for allowing you to visual test something, but visual testing is amazing.
It's like once you get it to look right, that's a test. And I love that. You get to just kind of flow, and if you have the right tools, you can capture all of that stuff just in time, instead of having to spike it out, and then come back and rewrite the test, and do it all over again.
Now the tools that I landed on for this particular part of the stack are Chromatic and Storybook. I wasn't particularly enthused about Storybook, but it was the entry into Chromatic, which was this really easy visual testing for our component libraries. Now I'm going to be really honest.
This doesn't affect you as much, but I've spent the last three years trying to communicate Storybook to developers, trying to bring more people into this really cool visual testing, component testing type of landscape. And I've learned one thing throughout that time, and that it's that Storybook is really good for one thing.
It's good for React developers building a component library, and if that's not you, it's kind of a black hole of suffering.
So this talk could be called, why Storybook is so close to being good for devs, but is financially un-incentivized from ever being so, so don't hold your breath. And the tools are probably good enough that you can just build your own.
Now a more positive title would be this, the DX I'd like to keep after Storybook. So every technology that I've ever used has had one brilliant atomic idea that I've always
kept with me, no matter how far I've gotten away from that technology. So in React, that was Composition. It was always Composition. Don't let anyone tell you that it wasn't.
Heroku has this idea of signals, the return of Knockout.js, 20 years later. Heroku had this idea of product over infrastructure. You shouldn't have to think about all the things that are used to deploy your application. Obligatory triangles.
And PHP has this beautiful philosophy in the community of money over developer experience. If you've ever written a PHP app, it still has those weird freaking tags with the question mark PHP around your whole app. That is beautiful chaos.
So God bless the indie hackers. So my question is, what is Storybook's nugget? What is the beautiful atomic idea that comes out of Storybook and that we can take with us, or that I'd like to take with me into other developer experiences and frameworks?
Well, I think it's Component Story Format. And if you're asking yourself, what is Component Story Format? Actually, I'll just ask you. Does anyone know what Component Story Format is? No. Is there an answer? I don't have an answer. Okay, yes.
So one hand and one definition, and there's a lot of you in the room. So I think of this as stories without the book. It's an ES module format for authoring components in an object-centric way, which is really nice. And I'm going to show it to you today.
And just keep in mind that while I'm demonstrating it in Storybook, it is a thing that's actually Storybook is built on, and it's not exclusively part of Storybook. So the example that we'll be breezing through today is the tic-tac-toe tutorial in React.
I feel like it's the most ubiquitous example that we have to drive from. Here we start with a square, just a plain square on a square component. And we have a story. This is Component Story Format that we're going to use to render this into Storybook.
There's a lot of TypeScript on the page, but basically we import our app component. We export that the app component is the thing that we want to put under test, so all of our stories are going to target that. And then we export a story as a named function, or a named object, and you'll see why the
object is important in a second. Then we get an X on the screen, which is great. It's exactly what we wanted. Real quick, we're going to draw the rest of the L. And this is one of my favorite things about Storybook.
There's so many really great integrations in there, and they work in a way that I feel is very virtuous to the shared component development experience. So with one line of NPM install and one line of configuration addition, I get the benefit
of AXDevTools right in a space that no one has to maintain. This page now has all of these resources to anyone who decides to fall on it or to decide to develop this component further. This is really cool.
There's a lot of great information, and we see that by default, just at this phase when we haven't introduced anything up to this point in terms of gameplay, there is this naturally inaccessible experience where we cannot select any of these squares by a label. So we can actually fix that pretty easily.
We're just going to add some labels. And one of the cool things here is that we actually see that label, so now we don't have to go inspecting through the DevTools to find that label. That was for the test passing, by the way, was the green. It was just a big green flash.
The black, I don't know what the black is for. Let's see. Back to green. Green is better. Black green refractor. There we go. Hey. So we got it back.
And so I love this because it's part of the shared experience. People can just jump in here, see that it has the message that we need to see without having to understand the DevTools, maintain a DevTools environment. This is actually really beautiful. I love it. Now, once we fix the accessibility errors, we can actually like jump into this board and do the next task, which is to put our first X on the screen where someone clicks it.
Now, this is where things get really interesting. A story in concept is this idea of a discrete state of a component that could be via props or it could be via interactions. In this case, we have two stories. We've added a second story. We have a basic default tic-tac-toe board.
And below that, I've added a new story for first move is X. We want to validate that the first move is always X. And we do that through testing library functions. Beautifully, we get to now utilize these accessible labels that we've added to create this state.
And we see all of that kind of come through inside of the storybook UI. So pretty cool so far. We can even write assertions here, which, you know, kind of cool as well. We can do a just style assertion to make sure that it is now labeled with taken space column one, row one.
And we can compose these. So if I want to do a second move is O, we can run the first play function inside of this second or this third story that we want to add, composing them together to create
this final state. Now, there are also features in here about viewports and action logging and more. Those features are just bad. So I'm not going to demonstrate. But I like this. I like this model.
I like the way of writing these in kind of this progressive way where I've done one task. I'm going to move on to the next task, validate it. But along the way, hold on to all of those momentary pieces of information. Now, once you have this, there's this beautiful thing you can integrate with, you know, Percy
and Chromatic and Apple tools to turn these into actual tests that run in the browser. And the beautiful thing about visual tests is they're an integration test between your components and a browser, which is the best closest experience to what your users will experience.
If you want to see a talk where I actually run through the entire workflow, I gave one a couple of years, a year and a half back, called How I Test a Million UI States with Every Merge Visual Testing in Storybook. I have some pretty epic clickbait first frame there.
So if I like this workflow in Storybook, like, why not Storybook? Well, I no longer build UIs, libraries, and that's kind of a big shift that goes back to that original point of mine that I think that Storybook right now is just well-suited
for developing component libraries first and foremost. Now, I think that there's an easy fix that, you know, we can talk about. I think that it could be embedded into your framework. And I think that could actually be a really nice way to move the experience into a place that, like, is the most meaningful to you. Second of all, Storybook can't keep up.
And this is a problem. So when I first started, Remix was kind of on the move. And I wanted to kind of touch on that story, like, kind of get Storybook into Remix. And we opened this issue, Ryan and I, like, two-plus years ago. And there's just been no, like, no movement on it. It's just, like, not prioritized.
Now, this is sad because if the architecture was right and it was embeddable, like, this wouldn't be a question, right? We would just be able to do the thing with the things that are good. And I found this personally when I rewrote my site in Astro. And there was just no hope that this was ever going to be a thing that was, like, solved
for me unless I solved it myself. And so I think, sadly, Storybook will never be a developer product. And I want to say that here because I think that, like, Epic Stack, what Ken's doing, it's such an interesting idea of making your own stack. I think a lot of us are waiting for someone else to make the perfect stack, when really
we should be focusing on composing the tools that make us happiest and work best for us. The problem is some of those tools don't compose well. And so we need to be careful about selecting our tools. And yeah, that's it. This is my favorite slide of the whole thing.
So one of the things that I want to warn you about is free open source versus faux open source. I think we've seen a lot of this lately. There's just been this transition to services. And I don't think that's a bad thing. I think it's a very complex thing. I think services are great for people. I mean, it goes back to that Heroku, PHP.
Maybe you just want to build an app, and that's great. And you should use as many services as you can. But there is a challenge where some of us just want to make stuff. Alex was making that spaceship game. And it's so fun to just own the whole problem sometimes.
So many times, we just want to make something that's fun, that gets us excited, that we fully did ourselves. And so it's really important to find composable pieces. And so from another talk from 2017 React Rally, I asked this question of, do you know whose mouth you're in? Are the tools there? Yeah, there we go.
Sorry, I hadn't considered the ramifications of that statement. We'll edit that out later. Do you know whose mouth you're in? Like, are you going to be a product at some point by making a simple technological decision? And if you are, really, you want to be in this space where you're partnering with tools,
partnering with services to kind of find the best fit for you, the best thing that makes your product work and allows you to communicate with your customers. I see this as that beautiful, orbiting, epic solar system that we defined in the beginning.
And this other side is some, like, chaotic, weird thing that just kind of everything moves, has to move around perfectly. And you have to wait for this thing to integrate with the other thing. And it's just sad. And it's all designed to bring you to a place where you pay someone money to solve a problem for you. And I don't think that's why we got into this.
I think, you know, it makes sense from a business perspective sometimes. But it's not really why we got into it. We got into it because programming is fun. So what does this stack look like today? Well, TS is great. I know TS Zealot. I use a lot of Unknown. I think that's great. I love Unknown. Unknown's a great API. It works for me. I don't work for it. VTest is amazing.
VTest is incredible. It's incredible software. Big fan of it. It kind of moves the integration line, kind of closes in on the integration line. And then Playwright has come in and really sucked up that whole space. And so for my personal site, I use these three.
And I just use this tiny little handful of CSF functions to give that DX experience that I want around writing components. And that's really it. And this is really beautifully simple. And this is something that I would recommend to anyone in the room.
Now, if I were to design an epic component testing wish list, these are the things that I would put on it. I like a CSF story authoring story. I love Playwright. We mentioned that. A DX owned by the framework. So I'd love to see this, especially in file system routing-based frameworks, to have some
type of first class tie-in, have some kind of underscore underscore stories URL at the end of it, like a GraphQL URL that I can just kind of go in there and see all the stories for use on that page. I think that would be amazing. I'd like it to be available in local testing and staging environments and then stripped in production.
That would be an awesome nicety to have. And then visually testable in CICD. All of those things are just super great. And I think that we can get there with less tooling in 2024. So super excited about that. I'm going to be working. I've been working with Kent and Joel on some courses for Epic Web. And we're going to do a component testing one.
So if you want, sign up for it. If you're not already signed up for the newsletter, sign up and you'll get some emails about that when they come out. Yeah, that's it. This is me. This is my 14 years experiment and testimony into the world of component testing and visual testing.
And I hope that my pain can help bring you some successes with these new and better tools that we have. So thank you so much for your time. Have a great conference.