0.4.0 • Published 9 months ago

storybook-addon-vis v0.4.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

storybook-addon-vis

Storybook Vitest Image Snapshot add-on.

Captures and compare image snapshot automatically and manually.

This add-on is inspired by jest-image-snapshot.

Starting from storybook 8.3, you can run Storybook stories with vitest browser mode.

Since it is running in actual browser, jest-image-snapshot does not work. This add-on provides similar functionality to jest-image-snapshot. In addition, you can capture image snapshot manually.

Install

npm install --save-dev storybook-addon-vis

pnpm add --save-dev storybook-addon-vis

yarn add --save-dev storybook-addon-vis

Config

This add-on provides features on both storybook and vitest, thus you need to add it to both storybook and vitest.

On vitest, you need to add storybook-addon-vis/vitest-plugin plugin in vitest.config.ts.

// vite.config.ts or vitest.config.ts
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin'
import { storybookVis } from 'storybook-addon-vis/vitest-plugin'
import { defineConfig } from 'vitest/config'

export default defineConfig({
   plugins: [
    storybookTest(),
    storybookVis()
	],
  test: {
    browser: {
      // ...
    }
    setupFiles: ['./vitest.setup.ts'],
  }
})

Also note that you need to add vitest.setup.ts file to set up the test environment. You need to do that anyway when you set up storybook with vitest.

In vitest.setup.ts, you need to extend vitest expect and register lifecycle hooks so that storybook-addon-vis can access the test context info to capture image snapshot.

// vitest.setup.ts
import { type StoryContext, setProjectAnnotations } from '@storybook/react'
import {
  configureSnapshotBeforeAll,
  configureSnapshotBeforeEach,
  page,
  shouldTakeSnapshot,
  toMatchImageSnapshot,
} from 'storybook-addon-vis/vitest-setup'
import { afterEach, beforeAll, beforeEach, expect } from 'vitest'
import * as projectAnnotations from './preview'

const project = setProjectAnnotations([projectAnnotations])

expect.extend({ toMatchImageSnapshot })

beforeAll(async (suite) => {
  project.beforeAll()
  await configureSnapshotBeforeAll(suite, /* options */)
})

beforeEach(configureSnapshotBeforeEach)

afterEach<{ story?: StoryContext }>(async (ctx) => {
  if (!shouldTakeSnapshot(ctx)) return

  await expect(page.imageSnapshot()).toMatchImageSnapshot(ctx.story?.parameters.snapshot)
})

On storybook, you need to extend the expect from @storybook/test

// .storybook/preview.tsx
import { expect } from '@storybook/test'
import { toMatchImageSnapshot } from 'storybook-addon-vis'

expect.extend({ toMatchImageSnapshot })

// ...

Usage - automatic snapshot

The afterEach hook above is how to capture the image snapshot automatically, when you add a snapshot tag to the story.

// story.tsx
export default {
  title: 'Button',
  // Take image snapshot automatically for all stories in this file
  tags: ['snapshot']
}

export const MyStory = {
  // Take image snapshot automatically for this story
  tags: ['snapshot'],
  // ...
}

You can provide options to the automatic toMatchImageSnapshot matcher using parameters.

import { defineSnapshotParam } from 'storybook-addon-vis'

export const MyStory = {
  // Take image snapshot automatically for this story
  tags: ['snapshot'],
  parameters: defineSnapshotParam({
    failureThreshold: 70,
  })
  // ...
}

You can disable snapshot capturing with the !snapshot tag, much like !test.

export default {
  title: 'Button',
  tags: ['snapshot']
}

export const MyStory = {
  // Disable image snapshot for this story
  tags: ['!snapshot'],
  // ...
}

Usage - manual snapshot

Besides automatic snapshot, you can capture image snapshot manually.

import { expect } from '@storybook/test'

// `page` and the like are proxy to `@vitest/browser/context` to work in storybook
import { page } from 'storybook-addon-vis'

export const PageSnapshot = {
  // ...
  async play() {
    await expect(page.imageSnapshot()).toMatchImageSnapshot()
  }
}

export const ElementSnapshot = {
  // ...
  async play({ canvas }) {
    const element = await canvas.getByTestid('subject')
    await expect(page.imageSnapshot({ element })).toMatchImageSnapshot()
  }
}
0.4.0

9 months ago

0.3.0

9 months ago

0.2.0

9 months ago

0.1.0

9 months ago

0.0.16

9 months ago

0.0.15

9 months ago

0.0.14

9 months ago

0.0.13

9 months ago

0.0.12

9 months ago

0.0.11

9 months ago

0.0.10

9 months ago

0.0.9

9 months ago

0.0.8

9 months ago

0.0.7

9 months ago

0.0.6

9 months ago

0.0.5

9 months ago

0.0.4

9 months ago

0.0.3

9 months ago

0.0.2

9 months ago