Join live session: Top 8 Storybook myths holding your team back
Docs
Storybook Docs

Mocking providers

Components can receive data or configuration from context providers. For example, a styled component might access its theme from a ThemeProvider or Redux uses React context to provide components access to app data. To mock a provider, you can wrap your component in a decorator that includes the necessary context.

.storybook/preview.tsx
import React from 'react';
 
import { Preview } from '@storybook/react';
 
import { ThemeProvider } from 'styled-components';
 
const preview: Preview = {
  decorators: [
    (Story) => (
      <ThemeProvider theme="default">
        {/* ๐Ÿ‘‡ Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it  */}
        <Story />
      </ThemeProvider>
    ),
  ],
};
 
export default preview;

Note the file extension above (.tsx or .jsx). You may need to adjust your preview file's extension to allow use of JSX, depending on your project's settings.

For another example, reference the Screens chapter of the Intro to Storybook tutorial, where we mock a Redux provider with mock data.

Configuring the mock provider

When mocking a provider, it may be necessary to configure the provider to supply a different value for individual stories. For example, you might want to test a component with different themes or user roles.

One way to do this is to define the decorator for each story individually. But if you imagine a scenario where you wish to create stories for each of your components in both light and dark themes, this approach can quickly become cumbersome.

For a better way, with much less repetition, you can use the decorator function's second "context" argument to access a story's parameters and adjust the provided value. This way, you can define the provider once and adjust its value for each story.

For example, we can adjust the decorator from above to read from parameters.theme to determine which theme to provide:

.storybook/preview.tsx
import React from 'react';
 
import type { Preview } from '@storybook/react';
import { ThemeProvider } from 'styled-components';
 
// themes = { light, dark }
import * as themes from '../src/themes';
 
const preview: Preview = {
  decorators: [
    // ๐Ÿ‘‡ Defining the decorator in the preview file applies it to all stories
    (Story, { parameters }) => {
      // ๐Ÿ‘‡ Make it configurable by reading the theme value from parameters
      const { theme = 'light' } = parameters;
      return (
        <ThemeProvider theme={themes[theme]}>
          <Story />
        </ThemeProvider>
      );
    },
  ],
};
 
export default preview;

Now, you can define a theme parameter in your stories to adjust the theme provided by the decorator:

Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  component: Button,
};
export default meta;
 
type Story = StoryObj<typeof Button>;
 
// Wrapped in light theme
export const Default: Story = {};
 
// Wrapped in dark theme
export const Dark: Story = {
  parameters: {
    theme: 'dark',
  },
};

This powerful approach allows you to provide any value (theme, user role, mock data, etc.) to your components in a way that is both flexible and maintainable.