Skip to content

Commit

Permalink
Merge pull request #38 from gemini-testing/sp.storybook
Browse files Browse the repository at this point in the history
docs(storybook): add documentation about storybook
  • Loading branch information
sipayRT authored Oct 10, 2024
2 parents 4765a51 + 6d5a34b commit d012d1d
Show file tree
Hide file tree
Showing 11 changed files with 1,009 additions and 0 deletions.
30 changes: 30 additions & 0 deletions blog/storybook-testing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Screenshot testing with Storybook
slug: screenshot-testing-with-storybook
hide_table_of_contents: false
date: 2024-09-26T13:00
---

Now, for automatic visual testing of your components, you only need Storybook with your components and the `@testplane/storybook` plugin. There’s no need to write any tests anymore.

<!-- truncate -->

[Storybook][storybook] is a tool for developing user interfaces based on components. It allows developers to independently visualize components in various states in an isolated environment, separate from other components.
This "showroom" is perfect for screenshot testing your components, as this isolated environment makes such tests significantly more stable and faster compared to e2e testing.

With the [@testplane/storybook][testplane-storybook] plugin, you can automatically verify changes to your components using screenshot testing without writing a single line of test code.
You just need to describe your component in `Storybook` and Testplane will automatically generate all necessary tests upon execution, run them in the required browsers and provide a visual report for updating screenshots.
Additionally, if a [play function][play-function] has been declared for the components, Testplane will execute it before the test begins to set the component to the desired state.

However, if these capabilities are not enough, you can directly describe a Testplane test in the story file, which will be executed as an additional test for the component.

How to use it?

Learn more about this in our documentation [Screenshot testing with Storybook][vt-story].
Also you can try it yourself in our [example project][example] on GitHub with customized screenshot testing.

[storybook]: https://storybook.js.org
[testplane-storybook]: https://github.com/gemini-testing/testplane-storybook
[play-function]: https://storybook.js.org/docs/writing-stories/play-function
[vt-story]: ../../docs/v8/visual-testing/with-storybook
[example]: https://github.com/gemini-testing/testplane/tree/master/examples/storybook-autoscreenshots
202 changes: 202 additions & 0 deletions docs/plugins/testplane-storybook.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import Admonition from "@theme/Admonition";

# @testplane/storybook

## Overview {#overview}

Use the [@testplane/storybook][testplane-storybook] plugin to automatically check the changes in your Storybook components with screenshot testing without a single line of test code.

This plugin adds:

- automatic screenshot tests for storybook stories;
- an ability to write Testplane tests for storybook stories right inside of the stories.

## Installation {#install}

```bash
npm install @testplane/storybook --save-dev
```

## Setup {#setup}

<Admonition type="info">Storybook 6.4+ is required to use this plugin.</Admonition>

### Storybook

If you use `storybook@6`, you will need to enable [buildStoriesJson][build-stories] feature in your `storybook` config:

```typescript tytle=".storybook/main.js"
export default {
// ...
features: {
// ...
buildStoriesJson: true,
},
};
```

You don't need to do this with storybook@7 or storybook@8.

### Testplane

Add `@testplane/storybook` plugin into your Testplane config:

```typescript title=".testplane.conf.ts"
export default {
plugins: {
"@testplane/storybook": {},

// other Testplane plugins...
},

// other Testplane settings...
};
```

With this minimal config, you will be able to run `npx testplane --storybook` to autotest each storybook story with [Testplane assertView][assert-view] command. Testplane will open each story, wait for play function to finish (if defined), and then call `assertView` command. These tests would be generated in runtime.

### Description of configuration parameters {#setup_description}

<table>
<thead>
<tr>
<td>**Parameter**</td>
<td>**Type**</td>
<td>**Default**</td>
<td>**Description**</td>
</tr>
</thead>
<tbody>
<tr>
<td>enabled</td>
<td>`Boolean`</td>
<td>true</td>
<td>Enable / disable plugin.</td>
</tr>
<tr>
<td>storybookConfigDir</td>
<td>`String`</td>
<td>".storybook"</td>
<td>Path to the storybook configuration directory.</td>
</tr>
<tr>
<td>autoScreenshots</td>
<td>`Boolean`</td>
<td>true</td>
<td>Enable / disable auto-screenshot tests</td>
</tr>
<tr>
<td>localport</td>
<td>`Number`</td>
<td>6006</td>
<td>Port to launch storybook dev server on.</td>
</tr>
<tr>
<td>remoteStorybookUrl</td>
<td>`String`</td>
<td>""</td>
<td>URL of the remote Storybook. If specified, local storybook dev sever would not be launched.</td>
</tr>
<tr>
<td>browserIds</td>
<td>`Array<String | RegExp>`</td>
<td>[]</td>
<td>Array of `browserId` to run storybook tests on. By default, all of browsers, specified in Testplane config would be used</td>
</tr>
</tbody>
</table>

<Admonition type="info">
Storybook tests performance greatly depends on [Testplane testsPerSession][testsPerSession]
parameter, as these tests speeds up on reusing existing sessions, so setting values around 20+
is preferred. These tests ignore [Testplane isolation][isolation]. It would be turned off
unconditionally.
</Admonition>

## Advanced usage

If you have `ts-node` in your project, you can write your Testplane tests right inside of storybook story files:

<Admonition type="info">
Storybook story files must have `.js` or `.ts` extension for this to work. Formats `jsx/tsx` are
not supported yet.
</Admonition>

```typescript title="stories/Primary.stories.ts"
import type { StoryObj } from "@storybook/react";
import type { WithTestplane } from "@testplane/storybook";

export const Primary: WithTestplane<StoryObj> = {
args: {
primary: true,
label: "Button",
},
testplane: {
"my test": async ({ browser, expect }) => {
const element = await browser.$(".storybook-button");

await expect(element).toHaveText("Button");
},
},
};
```

You can also specify extra options in story default config:

```typescript
import type { WithTestplane } from "@testplane/storybook";
import type { Meta, StoryObj } from "@storybook/react";

const meta: WithTestplane<Meta<typeof Button>> = {
title: "Example/Button",
component: Button,
testplane: {
skip: false, // if true, skips all Testplane tests from this story file
autoscreenshotSelector: ".my-selector", // Custom selector to auto-screenshot elements
browserIds: ["chrome"], // Testplane browsers to run tests from this story file
assertViewOpts: {
// override default assertView options for tests from this file
ignoreDiffPixelCount: 5,
},
},
};

export default meta;
```

If you decide to create separate config for storybook auto-tests (which is suggested), you need to specify config path via CLI option. For example:

```bash
npx testplane --storybook -c .testplane.storybook.conf.ts
```

This allows you to store references next to your story files:

```typescript title=".testplane.conf.ts"
import path from "path";
import { getStoryFile } from "@testplane/storybook";

export default {
screenshotsDir: test => {
const relativeStoryFilePath = getStoryFile(test);
const relativeStoryFileDirPath = path.dirname(relativeStoryFilePath);

return path.join(relativeStoryFileDirPath, "screens", test.id, test.browserId);
},
// other Testplane settings...
};
```

In this example, screenshot references would be stored in `screens/<testId>/<browserId>` folder, next to each of your story files.

## Useful links {#useful_links}

- [@testplane/storybook plugin sources][testplane-storybook]
- [assertView command][assert-view]

[assert-view]: ../commands/browser/assertView.mdx
[build-stories]: https://storybook.js.org/docs/6.4/configure/overview#feature-flags
[isolation]: ../config/browsers.mdx#isolation
[testplane-storybook]: https://github.com/gemini-testing/testplane-storybook
[testplane]: https://github.com/gemini-testing/testplane
[testsPerSession]: ../config/browsers.mdx#tests_per_session
60 changes: 60 additions & 0 deletions docs/visual-testing/visual-testing-intro.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Visual testing

Visual testing is implemented in testplane, with which the user can check the visual changes of an individual component, a viewport or the entire page.
We recommend using the [html-reporter][html-reporter] plugin, which provides a user-friendly UI for analyzing tests, saving/updating modified images and running tests.

![Html-report](/img/docs/html-reporter/html-reporter.overview.png)

### Screenshot Comparison Features {#features}

For screenshot checks, Testplane provides the `assertView` command, which allows you to take a screenshot of a specific element or the entire viewport.
When the assertView command is invoked, it searches for the required element on the page with automatic waiting. By default, animations will be disabled on the page before taking a screenshot to eliminate potential instability in the test due to the changing state of the element.
After taking a screenshot, the resulting image will be compared with the reference image. If the reference image does not exist yet, then it must be saved using the html reporter UI or the `--update-refs` CLI option.
To compare images, we use our own library [looks-same][looks-same], which differs from competitors in high performance and accuracy of comparison.

The following settings are taken into account during comparison:

- the blinking cursor in text inputs is ignored by default;
- elements specified in the comparison options are ignored in the image;
- comparison accuracy settings (acceptable deviations) are considered;
- anti-aliasing (the most common diffs in screenshots) accuracy settings for fonts are considered.

### Usage {#usage}

```typescript
await browser.assertView(state, options);
await browser.assertView(state, selector, options);
await element.assertView(state, options);
```

The `assertView` command is available both in the browser context and in the context of the found element. The set of arguments is different in these cases:

```typescript
it("check search view", async ({ browser }) => {
// ...

// screenshot of the current browser viewport
await browser.assertView("viewport-screen");

// screenshot of a specific element on the page (call from the browser context)
await browser.assertView("any-state-name", ".DocSearch", opts);

const searchInput = await browser.$(".DocSearch");
await searchInput.click();

// taking screenshot of a previously found item (from the element context)
await searchInput.assertView("any-state-name");
});
```

Read more about the capabilities of the `assertView' command in the relevant sections.

### Useful links {#useful_links}

- [browser.assertView command][browser-command]
- [element.assertView command][element-command]

[html-reporter]: ../../html-reporter/html-reporter-setup
[looks-same]: https://github.com/gemini-testing/looks-same
[browser-command]: https://testplane.io/docs/v8/commands/browser/assertView/
[element-command]: https://testplane.io/docs/v8/commands/element/assertView/
Loading

0 comments on commit d012d1d

Please sign in to comment.