Sign inSign up
Introduction

Delay snapshots

Components sometimes trigger custom interactions on render. For example, JavaScript-driven animations that cannot otherwise be disabled or third-party functionality outside of your control.

You can delay capture for a fixed time to allow your story to get into the intended state. Using delay requires Storybook 4.0 or later.

How long can I set delay?

The maximum time for snapshot capture is 15s. Your story should finish loading resources and be ready to capture in 15s.

Delay a story

Use story-level delay to ensure a minimum amount of time (in milliseconds) has passed before Chromatic takes a screenshot.

ℹ️ The chromatic.delay parameter can be set at story, component, and project levels. This enables you to set project wide defaults and override them for specific components and/or stories. Learn more »
// MyComponent.stories.js|jsx

import { MyComponent } from "./MyComponent";

export default {
  component: MyComponent,
  title: "MyComponent",
};

export const StoryName = {
  args: {
    with: "props",
  },
  parameters: {
    // Sets the delay (in milliseconds) for a specific story.
    chromatic: { delay: 300 },
  },
};

This technique is intended for interactions and animations that end after a certain period of time (e.g., “animate in”). If your animation is continuous and you cannot disable it, you may need to use an ignore region to stop Chromatic from considering such parts of your component.

Use an assertion to delay snapshot capture

For finer-grained control over when a snapshot is captured, use interactions and the play function to write assertions that check for DOM elements or set timeouts. Chromatic waits for interactions to pass before capturing a snapshot.

Check for DOM elements using getBy, findBy, or queryBy (docs here).

// MyComponent.stories.js|jsx

/*
 * Replace the @storybook/test package with the following if you are using a version of Storybook earlier than 8.0:
 * import { waitFor, within } from "@storybook/testing-library";
 * import { expect } from "@storybook/jest";
 */
import { expect, waitFor, within } from "@storybook/test";

import { MyComponent } from "./MyComponent";

export default {
  component: MyComponent,
  title: "MyComponent",
};

export const StoryName = {
  play: async ({ canvasElement }) => {
    // Assigns canvas to the component root element
    const canvas = within(canvasElement);
    //   Wait for the below assertion not throwing an error anymore (default timeout is 1000ms)
    //👇 This is especially useful when you have an asynchronous action or component that you want to wait for
    await waitFor(async () => {
      //👇 This assertion will pass if a DOM element with the matching id exists
      await expect(canvas.getByTestId("button")).toBeInTheDocument();
    });
  },
};

If your UI requires extra time to paint after the DOM loads, consider setting a timeout by adding this step to your play function:

// MyComponent.stories.js|jsx

import { MyComponent } from "./MyComponent";

export default {
  component: MyComponent,
  title: "MyComponent",
};

export const StoryName = {
  play: async ({ canvasElement }) => {
    // Assigns canvas to the component root element
    const canvas = within(canvasElement);
    //👇 This sets a timeout of 2s
    await new Promise((resolve) => setTimeout(resolve, 2000));
  },
};

Delay all stories of a component

Chromatic uses Storybook’s built in parameter API to make it straightforward to set delay on a group of stories:

// MyComponent.stories.js|jsx

import { MyComponent } from "./MyComponent";

export default {
  component: MyComponent,
  title: "MyComponent",
  parameters: {
    // Sets a delay for the component's stories
    chromatic: { delay: 300 },
  },
};

export const StoryName = {
  args: {
    with: "props",
  },
};
export const SecondStoryName = {
  args: {
    with: "other-props",
  },
};