> For the complete documentation index, see [llms.txt](https://argos-ci.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://argos-ci.com/docs/quickstart/storybook-quickstart/storybook-test-runner-quickstart.md).

# Storybook Test Runner visual testing quickstart

Set up visual testing in Storybook with Test Runner and the Argos CLI.

To add visual testing with [Storybook Test Runner](https://storybook.js.org/docs/writing-tests/integrations/test-runner), install `@argos-ci/storybook` and `@argos-ci/cli`, call `argosScreenshot(page, context)` in the `postVisit` hook of `.storybook/test-runner.ts`, run `test-storybook` against your built Storybook, and upload the screenshots with `npm exec -- argos upload ./screenshots` in CI with the `ARGOS_TOKEN` environment variable set.

### What Argos adds

* **A screenshot of every story.** The `postVisit` hook captures each story after Test Runner has rendered it and run its `play` function.
* **Baselines from your Git history.** Argos picks the [baseline build](/docs/learn/platform-fundamentals/baseline-build.md) automatically, so there are no images to commit.
* **Review on the pull request.** Visual changes become a pull request check that your team [approves or rejects](/docs/learn/review-workflow/review-a-build.md).

{% hint style="info" %}
If you use the Storybook Vitest addon (Storybook 9 or later), follow the [Storybook quickstart](/docs/quickstart/storybook-quickstart.md) instead.

If you use a legacy version of Storybook (\<v8), follow the [legacy Storybook Quickstart](/docs/quickstart/storybook-quickstart/storybook-legacy-less-than-v8-quickstart.md).
{% endhint %}

### Prerequisites

* Node.js 22 or later
* [Storybook v8+](https://storybook.js.org/docs/get-started/install) set up in your project
* [A project created in Argos](https://app.argos-ci.com/new)

{% stepper %}
{% step %}

### Install

Install the Argos CLI, the Argos Storybook SDK, and Storybook Test Runner:

{% tabs %}
{% tab title="npm" %}

```
npm i --save-dev @argos-ci/cli @argos-ci/storybook @storybook/test-runner
```

{% endtab %}

{% tab title="yarn" %}

```
yarn add --dev @argos-ci/cli @argos-ci/storybook @storybook/test-runner
```

{% endtab %}

{% tab title="pnpm" %}

```
pnpm add --save-dev @argos-ci/cli @argos-ci/storybook @storybook/test-runner
```

{% endtab %}

{% tab title="bun" %}

```
bun add --dev @argos-ci/cli @argos-ci/storybook @storybook/test-runner
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Add a test script

Add the following script to your `package.json`:

{% code title="package.json" %}

```json
{
  "scripts": {
    "test-storybook": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-vm-modules test-storybook"
  }
}
```

{% endcode %}

{% hint style="info" %}
`NODE_OPTIONS=--experimental-vm-modules` is required because Storybook Test Runner uses Jest, which needs this flag to run modern packages like the Argos Storybook SDK.
{% endhint %}
{% endstep %}

{% step %}

### Capture screenshots

Add a `.storybook/test-runner.ts` file to your project. The `postVisit` hook captures a screenshot of every story:

{% code title=".storybook/test-runner.ts" %}

```ts
import type { TestRunnerConfig } from "@storybook/test-runner";
import { argosScreenshot } from "@argos-ci/storybook/test-runner";

const config: TestRunnerConfig = {
  async postVisit(page, context) {
    await argosScreenshot(page, context);
  },
};

export default config;
```

{% endcode %}

Screenshots are written to the `./screenshots` directory. Add `./screenshots` to your `.gitignore` file to avoid committing them.
{% endstep %}

{% step %}

### Set up CI

Add a workflow that builds your Storybook, runs the tests, and uploads the screenshots to Argos. If you use another CI provider, adapt the steps with [Run Argos in CI](/docs/learn/how-to-guides/ci-pipelines/run-argos-in-ci.md):

{% code title=".github/workflows/argos.yml" %}

```yaml
name: Argos

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  argos:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22

      - name: Install dependencies
        run: npm ci

      - name: Build Storybook
        run: npm run build-storybook

      - name: Install Playwright dependencies
        run: npx playwright install --with-deps chromium

      - name: Run Storybook tests and capture screenshots
        run: |
          npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
            "npx http-server ./storybook-static --port 6006 --silent" \
            "npx wait-on tcp:127.0.0.1:6006 && npm run test-storybook"

      - name: Upload screenshots to Argos
        run: npm exec -- argos upload ./screenshots
        env:
          ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
```

{% endcode %}

`ARGOS_TOKEN` is the project token from **Settings → General → Token**. On GitHub Actions, you can also use [OIDC or tokenless authentication](/docs/learn/integrations/github-actions-authentication.md) to avoid managing a secret.

To learn how to run tests on a deployed Storybook, refer to the [Storybook Test Runner documentation](https://storybook.js.org/docs/writing-tests/integrations/test-runner).
{% endstep %}
{% endstepper %}

### You're all set

Push your changes and open a pull request — the Argos check appears on it once the build is uploaded. Review the visual changes, approve or reject them, and merge with confidence.

{% hint style="info" %}
Argos needs a baseline to compare against. Until a build runs on your default branch, pull request builds are marked as [orphan](/docs/learn/platform-fundamentals/baseline-build.md#orphan-builds). Merge this setup or run the workflow once on your default branch to establish the baseline.
{% endhint %}

### Frequently asked questions

<details>

<summary>How do I update the baseline after an intended change?</summary>

You don't update any file. Review the build in Argos and [approve the changes](/docs/learn/review-workflow/review-a-build.md): an approved build is eligible as a baseline. Once you merge, the build on your default branch, which Argos approves automatically by default, becomes the baseline for the pull requests that follow. See [Baseline build](/docs/learn/platform-fundamentals/baseline-build.md).

</details>

<details>

<summary>Why do screenshots differ between my machine and CI?</summary>

Fonts, text rendering, and browser versions depend on the operating system, so the same page renders slightly differently on macOS and on a Linux CI runner. The workflow above uploads screenshots only from CI, so Argos only compares screenshots captured on CI. Keep your CI on the same image and browser version from one run to the next. See [Browser glitches](/docs/learn/reliability-and-flakiness/flaky-tests/browser-glitches.md) and [Stabilize screenshots](/docs/learn/reliability-and-flakiness/flaky-tests.md).

</details>

### Next steps

* [Stabilize screenshots](/docs/learn/reliability-and-flakiness/flaky-tests.md) – Prevent flaky diffs before they reach your pull requests
* [Storybook SDK reference](/docs/reference/storybook.md) – All options and helpers
* [Storybook + Test Runner example](https://github.com/argos-ci/argos-javascript/tree/main/examples/storybook-test-runner) – A complete working setup

***

Need help? [Join our Discord](https://argos-ci.com/discord), [open an issue on GitHub](https://github.com/argos-ci/argos/issues), or [send us an email](mailto:contact@argos-ci.com).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://argos-ci.com/docs/quickstart/storybook-quickstart/storybook-test-runner-quickstart.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
