Skip to content

Commit

Permalink
Docs: UI testing handbook MSW and Storybook 8
Browse files Browse the repository at this point in the history
  • Loading branch information
jonniebigodes committed Jun 12, 2024
1 parent a6932e7 commit f8358a6
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ const config = {
name: '@storybook/react-vite',
options: {},
},
docs: {
autodocs: 'tag',
},
};
export default config;
```
Expand Down Expand Up @@ -164,10 +161,9 @@ export default {
},
};


/*
*👇 Wraps the component with a custom render function.
* See https://storybook.js.org/docs/react/api/csf
* See https://storybook.js.org/docs/api/csf
* to learn how to use render functions.
*/
export const Default = {
Expand Down
62 changes: 37 additions & 25 deletions content/ui-testing-handbook/react/en/automate.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Our workflow will run when code is pushed to any branch of our repository and it
- Run user flow tests with Cypress

```yaml:clipboard=false
# .github/workflows/ui-tests.yml
name: 'UI Tests'
on: push
Expand All @@ -53,10 +55,12 @@ jobs:
interaction-and-accessibility:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 20
- name: Install dependencies
run: yarn
- name: Install Playwright
Expand All @@ -72,25 +76,27 @@ jobs:
visual-and-composition:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required to retrieve git history
fetch-depth: 0 # Required to retrieve Git history
- name: Install dependencies
run: yarn
- name: Publish to Chromatic
uses: chromaui/action@v1
uses: chromaui/action@latest
with:
# Grab this from the Chromatic manage page
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# Run user flow tests with Cypress
user-flow:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install dependencies
run: yarn
- name: Cypress run
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v6
with:
start: npm run dev
```
Expand All @@ -113,6 +119,8 @@ Finally, create a new commit, push your changes to GitHub, and you should see yo
Each job runs independently, which means the CI server has to install dependencies in all three jobs. That slows down the test run. We can cache dependencies and only run `yarn install` if the lock file changes to avoid that. Let’s update the workflow to include the `install-cache` job.

```yaml:clipboard=false
# .github/workflows/ui-tests.yml
name: 'UI Tests'
on: push
Expand All @@ -123,9 +131,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Commit
uses: actions/checkout@v2
- name: Cache yarn dependencies and cypress
uses: actions/cache@v2
uses: actions/checkout@v4
- name: Cache Yarn dependencies and Cypress
uses: actions/cache@v4
id: yarn-cache
with:
path: |
Expand All @@ -142,12 +150,14 @@ jobs:
runs-on: ubuntu-latest
needs: install-cache
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '16.x'
- name: Restore yarn dependencies
uses: actions/cache@v2
node-version: 20
- name: Restore Yarn dependencies
uses: actions/cache@v4
id: yarn-cache
with:
path: |
Expand All @@ -170,11 +180,11 @@ jobs:
runs-on: ubuntu-latest
needs: install-cache
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required to retrieve git history
- name: Restore yarn dependencies
uses: actions/cache@v2
fetch-depth: 0 # Required to retrieve Git history
- name: Restore Yarn dependencies
uses: actions/cache@v4
id: yarn-cache
with:
path: |
Expand All @@ -184,7 +194,7 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-v1
- name: Publish to Chromatic
uses: chromaui/action@v1
uses: chromaui/action@latest
with:
# Grab this from the Chromatic manage page
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
Expand All @@ -193,9 +203,11 @@ jobs:
runs-on: ubuntu-latest
needs: install-cache
steps:
- uses: actions/checkout@v2
- name: Restore yarn dependencies
uses: actions/cache@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Restore Yarn dependencies
uses: actions/cache@v4
id: yarn-cache
with:
path: |
Expand All @@ -205,7 +217,7 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-v1
- name: Cypress run
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v6
with:
start: npm run dev
```
Expand Down
16 changes: 8 additions & 8 deletions content/ui-testing-handbook/react/en/composition-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Applications are built by plugging components into each other. This means a bug

![minor tweaks cause major regressions](/ui-testing-handbook/minor-major-regressions-1.gif)

Consider the Button component from [Storybook’s design system](https://5ccbc373887ca40020446347-oghpnhotjv.chromatic.com/?path=/docs/button--basic). It is used countless times across multiple pages. A bug in `Button` will inadvertently lead to bugs in all those pages. In other words, one failure can compound exponentially. As you move up the component hierarchy towards the level of pages, the impact of these bugs increases. Therefore, we need a way to catch such cascading issues early and figure out the root cause.
Consider the Button component from [Storybook’s design system](https://5ccbc373887ca40020446347-idzavsdems.chromatic.com/?path=/story/button--basic). It is used countless times across multiple pages. A bug in `Button` will inadvertently lead to bugs in all those pages. In other words, one failure can compound exponentially. As you move up the component hierarchy towards the level of pages, the impact of these bugs increases. Therefore, we need a way to catch such cascading issues early and figure out the root cause.

![The same button component is being used across multiple pages of an app](/ui-testing-handbook/design-system-inconsistent-buttons.jpg)

Expand Down Expand Up @@ -79,7 +79,7 @@ export const Default = {
};
```

Notice the `argTypes`. [Args](https://storybook.js.org/docs/react/writing-stories/args) are Storybook's mechanism for defining inputs to a story. Think of them as framework-agnostic props. Args defined at the component level are automatically passed down to each story. In our case, we have defined three event handlers using the [Actions addon](https://storybook.js.org/docs/react/essentials/actions).
Notice the `argTypes`. [Args](https://storybook.js.org/docs/writing-stories/args) are Storybook's mechanism for defining inputs to a story. Think of them as framework-agnostic props. Args defined at the component level are automatically passed down to each story. In our case, we have defined three event handlers using the [Actions addon](https://storybook.js.org/docs/essentials/actions).

These simulated actions will show up in the addons panel as you interact with `TaskList`. Allowing you to verify that the components are wired correctly.

Expand Down Expand Up @@ -187,7 +187,7 @@ yarn init-msw

<div class="aside">

💡 Public directory may differ depending on the project. For custom configurations, we recommend reading MSW's [documentation](https://mswjs.io/docs/getting-started/integrate/browser#where-is-my-public-directory) to learn more about them. To see the changes reflected in Storybook, you'll need to update the [`staticDirs`](https://storybook.js.org/docs/react/configure/overview#using-storybook-api) configuration element in `.storybook/main.js`.
💡 Public directory may differ depending on the project. For custom configurations, we recommend reading MSW's [documentation](https://mswjs.io/docs/getting-started/integrate/browser#where-is-my-public-directory) to learn more about them. To see the changes reflected in Storybook, you'll need to update the [`staticDirs`](https://storybook.js.org/docs/configure/images-and-assets#serving-static-files-via-storybook-configuration) configuration element in `.storybook/main.js`.

</div>

Expand Down Expand Up @@ -223,7 +223,7 @@ Lastly, restart the `yarn storybook` command. And we’re all set to mock API re
`InboxScreen` calls the `useTasks` hook which in-turn fetches data from the `/tasks` endpoint. We can specify the mock responses using the `msw` parameter. Notice how you can return different responses for each story.

```javascript:title=src/InboxScreen.stories.jsx
import { rest } from 'msw';
import { http, HttpResponse } from 'msw';

import InboxScreen from './InboxScreen';

Expand All @@ -238,8 +238,8 @@ export const Default = {
parameters: {
msw: {
handlers: [
rest.get('/tasks', (req, res, ctx) => {
return res(ctx.json(TaskListDefault.args));
http.get('/tasks', () => {
return HttpResponse.json(TaskListDefault.args);
}),
],
},
Expand All @@ -253,8 +253,8 @@ export const Error = {
parameters: {
msw: {
handlers: [
rest.get('/tasks', (req, res, ctx) => {
return res(ctx.json([]));
http.get('/tasks', () => {
return HttpResponse.json([]);
}),
],
},
Expand Down
2 changes: 1 addition & 1 deletion content/ui-testing-handbook/react/en/conclusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ If you've been coding along, your repository and deployed Storybook should look
Want more? Here are some additional helpful resources:

- [**Visual Testing Handbook**](/visual-testing-handbook) is an in-depth guide to testing UI appearance—with learnings from leading engineering teams like BBC, Adobe, Target and more.
- [**How to test UIs with Storybook**](https://storybook.js.org/docs/react/writing-tests/introduction) details how you can use Storybook for UI testing.
- [**How to test UIs with Storybook**](https://storybook.js.org/docs/writing-tests) details how you can use Storybook for UI testing.
- [**Discord chat**](https://discord.gg/UUt2PJb) puts you in contact with the Storybook community and maintainers.
- [**Blog**](https://storybook.js.org/blog/) showcases the latest releases and features to streamline your UI development workflow.

Expand Down
16 changes: 8 additions & 8 deletions content/ui-testing-handbook/react/en/interaction-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ yarn storybook
In the previous chapter, we catalogued all the use cases of the InboxScreen component in the `InboxScreen.stories.jsx` file. That allowed us to spot-check appearance during development and catch regressions via visual tests. These stories will now also power our interaction tests.

```javascript:title=src/InboxScreen.stories.jsx
import { rest } from 'msw';
import { http, HttpResponse } from 'msw';

import InboxScreen from './InboxScreen';

Expand All @@ -77,8 +77,8 @@ export const Default = {
parameters: {
msw: {
handlers: [
rest.get('/tasks', (req, res, ctx) => {
return res(ctx.json(TaskListDefault.args));
http.get('/tasks', () => {
return HttpResponse.json(TaskListDefault.args);
}),
],
},
Expand All @@ -92,8 +92,8 @@ export const Error = {
parameters: {
msw: {
handlers: [
rest.get('/tasks', (req, res, ctx) => {
return res(ctx.json([]));
http.get('/tasks', () => {
return HttpResponse.json([]);
}),
],
},
Expand All @@ -105,12 +105,12 @@ export const Error = {

[Testing Library](https://testing-library.com/) offers a convenient API for simulating user interactions—click, drag, tap, type, etc. Whereas [Jest](https://jestjs.io/) provides assertion utilities. We'll use Storybook-instrumented versions of these two tools to write the test. Therefore, you get a familiar developer-friendly syntax to interact with the DOM, but with extra telemetry to help with debugging.

The test itself will be housed inside a [play function](https://storybook.js.org/docs/react/writing-stories/play-function). This snippet of code gets attached to a story and runs after the story is rendered.
The test itself will be housed inside a [play function](https://storybook.js.org/docs/writing-stories/play-function). This snippet of code gets attached to a story and runs after the story is rendered.

Let's add in our first interaction test to verify that the user can pin a task:

```javascript:title=src/InboxScreen.stories.jsx
import { rest } from 'msw';
import { http, HttpResponse } from 'msw';

import InboxScreen from './InboxScreen';

Expand Down Expand Up @@ -152,7 +152,7 @@ Each play function receives the Canvas element—the top-level container of the

We're looking for the "Export logo" task in our case. Then find the pin button within it and click it. Finally, we check to see if the button has updated to the unpinned state.

When Storybook finishes rendering the story, it executes the steps defined within the play function, interacting with the component and pinning a task—similar to how a user would do it. If you check your [interactions panel](https://storybook.js.org/docs/react/writing-tests/interaction-testing#interactive-debugger), you'll see the step-by-step flow. It also offers a handy set of UI controls to pause, resume, rewind, and step through each interaction.
When Storybook finishes rendering the story, it executes the steps defined within the play function, interacting with the component and pinning a task—similar to how a user would do it. If you check your [interactions panel](https://storybook.js.org/docs/writing-tests/interaction-testing#interactive-debugger), you'll see the step-by-step flow. It also offers a handy set of UI controls to pause, resume, rewind, and step through each interaction.

<video autoPlay muted playsInline loop>
<source
Expand Down
2 changes: 1 addition & 1 deletion content/ui-testing-handbook/react/en/user-flow-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Start the app in development mode by running `yarn dev`. Then open [http:https://local

### Set up Cypress

Run: `yarn add --dev cypress` to install the Cypress package. Then add the Cypress command to the scripts field of your `package.json` file.
Run `yarn add --dev cypress` to install the Cypress package. Then add the Cypress command to the scripts field of your `package.json` file.

```json:clipboard=false
{
Expand Down
2 changes: 1 addition & 1 deletion gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ module.exports = {
},
'ui-testing-handbook': {
react: {
en: 7.6,
en: 8.1,
ko: 6.5,
},
},
Expand Down

0 comments on commit f8358a6

Please sign in to comment.