A guide to Storybook Test for interaction testing
Tags: storybook, webdev
Published: 2024-02-22 15:39:19

**Written by [Nwani Victory
](https://blog.logrocket.com/author/nwanivictory/)✏️**

Since its relaunch in 2017, Storybook has become an indispensable tool for frontend developers to test and maintain modular frontend components in isolation. Storybook supports all major frontend frameworks and libraries, including React, Angular, Vue, Svelte, and a host of others. 

In this tutorial, we’ll spotlight the recently released `@storybook/test package`, highlighting its new APIs and how it improves on the existing `@storybook/jest` and `@storybook/testing-library` packages. To follow along with the hands-on steps in this tutorial, which will demonstrate the use of the `@storybook/test` package within a demo Next.js application, you will need:

*   Node.js to run the demo Next.js application locally
*   [A basic understanding of Storybook](https://blog.logrocket.com/storybook-js-adoption-guide/)
*   A basic understanding of the JavaScript programming language

Let's get started.

## Understanding Storybook Test

Storybook Test is a new test environment that combines the APIs of `@‌storybook/jest` and `@‌storybook/testing-library` into a single package. Its purpose is to improve the DX of Storybook, and it does so in many ways. 

Consolidating these tools gives you fewer configuration requirements. You also no longer need to have the `@‌storybook/jest` and `@‌storybook/testing-library` packages installed, as you can import the test utilities from them through the `@‌storybook/test` package, making the project more lightweight. 

The new test environment is also [powered by Vitest](https://blog.logrocket.com/guide-vitest-automated-testing-vue-components/), allowing you to import utilities from the `@vitest/spy` and `@vitest/expect` packages. Leveraging Vitest helps boost speed and introduces some new testing patterns to help decrease load times. 

Since releasing Storybook Test, Storybook has encouraged developers to adopt [explicit action args](https://storybook.js.org/blog/storybook-test/#:~:text=Explicit%20action%20args) as a new pattern when writing actions and spies for stories. This approach improves the performance of large stories. Additionally, as explicit action args don't depend on docgen to autogenerate function mocks, they enable us to add types to the action args. They also ensure that the `Play` function has consistent results, which we’ll discuss more later. 

The next section of this tutorial will demonstrate using explicit action args while writing interaction tests for the components within a demo application.

## Testing stories with `@storybook/test`

To keep the focus on Storybook, we will be testing the components within a pre-built Next.js application. The components in the application were designed in the public [Style Guide Starter](https://www.figma.com/file/tJsOHrnCXZbqyBQcV56SsH/Style-Guide-Starter-(Copy)?node-id=0%3A1&mode=dev) board from the Figma community. The application also uses Tailwind CSS to style the elements. 

Launch the terminal or command prompt application of your choice. Then, execute the command below to clone the pre-built application from its GitHub repository:

```shell
git clone https://github.com/vickywane/storybook-test.git
```

You can also manually download the [project folder from the repository](https://github.com/vickywane/storybook-test). The complete code for this tutorial is within the `feat/storybook-test` branch of the repository. 

Run the following commands to change the directory into the cloned project and install its dependencies:

```shell
#change directory into project
cd storybook-test 

#install project dependencies 
npm install
```

At this point, the prebuilt application does not have Storybook installed or any stories to test. The next sections will guide you on how to set up Storybook with the latest versions that come with the `@storybook/test` package. 

Run the following command to preview the application before you move on to adding Storybook for the individual components:

```bash
npm run dev
```

As shown in the following image, navigating to [http://localhost:3000](http://localhost:3000) will display the demo Next.js application: ![Preview Of The Demo Next Js App Used In This Tutorial To Explore Storybook Test](https://blog.logrocket.com/wp-content/uploads/2024/02/Demo-Next-js-app-explore-Storybook-Test.png)

### Setting up Storybook in the prebuilt application

Execute the following `init` command to add the latest version of Storybook into the application via the interactive CLI:

```bash
npx storybook@latest init
```

The CLI is smart enough to automatically install relevant dependencies and set up Storybook based on the existing frontend technologies being used in your project. When you perform this fresh setup of Storybook, `@storybook/test` is one of the packages that the `init` command will add to your project. 

You will need to execute the following upgrade command if you were using an existing setup of the older Storybook versions:

```bash
npx storybook@next upgrade
```

After the update, you will then need to install the `@storybook/test` package manually.

### Writing stories using Storybook Test

At this point, you have Storybook fully set up in the demo Next.js application. The previous `init` command creates boilerplate Storybook components and examples to give you a good starting point. 

Let’s create stories for the `TextInput` and `ProjectDetailsForm` components within the application. Each of these two stories will use some of the new features from the `@storybook/test` package. 

First, create a `TextInput.stories.tsx` file within the `stories` directory to create a story for the `TextInput` component. Add the content of the code block below into this file. The code renders the `TextInput` component in the single default state:

```javascript
import { userEvent, within, expect, fn } from "@storybook/test";
import TextInput from "../components/TextInput";
import { Meta, StoryObj } from "@storybook/react";

const meta: Meta<typeof TextInput> = {
 title: "TextInput",
 component: TextInput,
};

export default meta;
type Story = StoryObj<typeof TextInput>;
const MOCK_LABEL = 'Project Label'

export const Default: Story = {
 tags: ["autodocs"],
 args: {
   label: MOCK_LABEL,
   placeholder: "Enter project label name",
   type: "text",
   handleTextChange: fn(),
 },
 play: async ({args, canvasElement }) => {
   const canvas = within(canvasElement);

   const labelElement = canvas.getByTestId("label-element")
   const inputElement = canvas.getByTestId("input-element");
   await userEvent.type(inputElement, "Sample Project Name", {
     delay: 50,
   })

   await expect(labelElement.innerHTML).toBe(MOCK_LABEL)
   await expect(args.handleTextChange).toHaveBeenCalled();
 },
};
```

The main focus of the story above is on the interaction tests for the `TextInput` component through [the Play function](https://storybook.js.org/docs/writing-stories/play-function):

*   Using the `fn()` method from the `@storybook/test` package, we are mocking and spying on the `handleTextChange()` action within [the args object](https://storybook.js.org/docs/writing-stories/args) is being mocked and spied.
*   Within the tests, we expect the `type()` method from the `canvasElement` method to call the `handleTextChange` function as it types in mock characters into the input field.
*   We can then use the `toHaveBeenCalled()` assertion on the `handleTextChange()` action spy in the `args` object to confirm that `handleTextChange` is being called as expected.

Note that the `expect`, `within`, and `userEvent` testing utilities now come from the single `@storybook/test` package rather than the `@vitest/spy`, `@storybook/testing-library`, and `@storybook/jest` packages. 

The image below shows the interaction tests within the `TextInput` story being executed: ![Example Of Interaction Tests With Storybook Test](https://blog.logrocket.com/wp-content/uploads/2024/02/Example-interaction-tests-Storybook-Test.png) With the `TextInput.stories.ts` file, you now have your first story using the `@storybook/test` package to perform interaction tests!

## Conclusion

Congratulations on completing this tutorial! We explored the `@storybook/test` package, why the Storybook team consolidated the `@storybook/jest` and `@storybook/testing-library`, and the significant performance benefits of adopting the explicit action args pattern to make your stories independent of docgen. 

I hope you found this article interesting and useful as you set up or upgrade your Storybook projects to use the `@storybook/test` package.

---

##Get set up with LogRocket's modern error tracking in minutes:

1. Visit https://logrocket.com/signup/ to get an app ID.
2. Install LogRocket via NPM or script tag. `LogRocket.init()` must be called client-side, not server-side.

NPM:
```bash
$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
```
Script Tag:
```javascript
Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
```

3.(Optional) Install plugins for deeper integrations with your stack:
*   Redux middleware
*   ngrx middleware
*   Vuex plugin

[Get started now](https://lp.logrocket.com/blg/signup)