New
Automatic visual tests in Storybook, plus 2.2x faster build times for React+TSVisual test with Chromatic
Star80,409
Back to integrations
Add your integration
Categories
  • ⭐️ Popular
  • 🧩 Essentials
  • 🛠 Code
  • ⚡️ Data & state
  • ✅ Test
  • 💅 Style
  • 🎨 Design
  • ⚙️ Appearance
  • 🗄 Organize
How to install addons Create an addon
storybook-addon-module-mock
Provides module mocking functionality like `jest.mock` on Storybook.
npm install storybook-addon-module-mock
Last updated 9 days ago
1.1k
Downloads per week
Readme View on GitHub

storybook-addon-module-mock

Provides module mocking functionality like jest.mock on Storybook.

usage

Added 'storybook-addon-module-mock' to Storybook addons.

Storybook@6 & Next.js

  • .storybook/main.js
// @ts-check
/**
 * @type { import("@storybook/react/types").StorybookConfig}
 */
module.exports = {
  core: {
    builder: 'webpack5',
  },
  stories: ['../src/**/*.stories.@(tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-coverage',
      options: {
        istanbul: {
          exclude: ['**/components/**/index.ts'],
        },
      },
    },
    'storybook-addon-next',
    'storybook-addon-module-mock',
  ],
  features: {
    storyStoreV7: true,
    interactionsDebugger: true,
  },
  typescript: { reactDocgen: 'react-docgen' },
};

Storybook@7 & Next.js

  • .storybook/main.ts
import type { StorybookConfig } from '@storybook/nextjs';

const config: StorybookConfig = {
  framework: {
    name: '@storybook/nextjs',
    options: {},
  },
  stories: ['../src/**/*.stories.@(tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-coverage',
      options: {
        istanbul: {
          exclude: ['**/components/**/index.ts'],
        },
      },
    },
    'storybook-addon-module-mock',
  ],
  features: {
    storyStoreV7: true,
  },
  typescript: {
    reactDocgen: 'react-docgen',
  },
};

export default config;

Sample1

MockTest.tsx

import React, { FC, useMemo, useState } from 'react';

interface Props {}

/**
 * MockTest
 *
 * @param {Props} { }
 */
export const MockTest: FC<Props> = ({}) => {
  const [, reload] = useState({});
  const value = useMemo(() => {
    return 'Before';
  }, []);
  return (
    <div>
      <button onClick={() => reload({})}>{value}</button>
    </div>
  );
};

MockTest.stories.tsx

createMock replaces the target module function with the return value of jest.fn().
The mockRestore() is automatically performed after the Story display is finished.

import { expect } from '@storybook/jest';
import { userEvent, waitFor, within } from '@storybook/testing-library';
import { createMock, getMock } from 'storybook-addon-module-mock';
import { ComponentMeta, ComponentStoryObj } from '@storybook/react';
import { MockTest } from './MockTest';
import React from 'react';

const meta: ComponentMeta<typeof MockTest> = {
  title: 'Components/MockTest',
  component: MockTest,
};
export default meta;

export const Primary: ComponentStoryObj<typeof MockTest> = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    expect(canvas.getByText('Before')).toBeInTheDocument();
  },
};

export const Mock: ComponentStoryObj<typeof MockTest> = {
  parameters: {
    moduleMock: {
      mock: () => {
        const mock = createMock(React, 'useMemo');
        mock.mockReturnValue('After');
        return [mock];
      },
    },
  },
  play: async ({ canvasElement, parameters }) => {
    const canvas = within(canvasElement);
    expect(canvas.getByText('After')).toBeInTheDocument();
    const mock = getMock(parameters, React, 'useMemo');
    expect(mock).toBeCalled();
  },
};

export const Action: ComponentStoryObj<typeof MockTest> = {
  parameters: {
    moduleMock: {
      mock: () => {
        const mock = createMock(React, 'useMemo');
        return [mock];
      },
    },
  },
  play: async ({ canvasElement, parameters }) => {
    const canvas = within(canvasElement);
    const mock = getMock(parameters, React, 'useMemo');
    mock.mockReturnValue('Action');
    userEvent.click(await canvas.findByRole('button'));
    await waitFor(() => {
      expect(canvas.getByText('Action')).toBeInTheDocument();
    });
  },
};

Sample2

message.ts

export const getMessage = () => {
  return 'Before';
};

LibHook.tsx

import React, { FC, useState } from 'react';
import { getMessage } from './message';

interface Props {}

/**
 * LibHook
 *
 * @param {Props} { }
 */
export const LibHook: FC<Props> = ({}) => {
  const [, reload] = useState({});
  const value = getMessage();
  return (
    <div>
      <button onClick={() => reload({})}>{value}</button>
    </div>
  );
};

LibHook.stories.tsx

import { expect } from '@storybook/jest';
import { userEvent, waitFor, within } from '@storybook/testing-library';
import { ComponentMeta, ComponentStoryObj } from '@storybook/react';
import { LibHook } from './LibHook';
import { createMock, getMock } from 'storybook-addon-module-mock';
import * as message from './message';

const meta: ComponentMeta<typeof LibHook> = {
  title: 'Components/LibHook',
  component: LibHook,
};
export default meta;

export const Primary: ComponentStoryObj<typeof LibHook> = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    expect(canvas.getByText('Before')).toBeInTheDocument();
  },
};

export const Mock: ComponentStoryObj<typeof LibHook> = {
  parameters: {
    moduleMock: {
      mock: () => {
        const mock = createMock(message, 'getMessage');
        mock.mockReturnValue('After');
        return [mock];
      },
    },
  },
  play: async ({ canvasElement, parameters }) => {
    const canvas = within(canvasElement);
    expect(canvas.getByText('After')).toBeInTheDocument();
    const mock = getMock(parameters, message, 'getMessage');
    expect(mock).toBeCalled();
  },
};

export const Action: ComponentStoryObj<typeof LibHook> = {
  parameters: {
    moduleMock: {
      mock: () => {
        const mock = createMock(message, 'getMessage');
        return [mock];
      },
    },
  },
  play: async ({ canvasElement, parameters }) => {
    const canvas = within(canvasElement);
    const mock = getMock(parameters, message, 'getMessage');
    mock.mockReturnValue('Action');
    userEvent.click(await canvas.findByRole('button'));
    await waitFor(() => {
      expect(canvas.getByText('Action')).toBeInTheDocument();
    });
  },
};
Join the community
6,314 developers and counting
WhyWhy StorybookComponent-driven UI
Open source software
Storybook

Maintained by
Chromatic
Special thanks to Netlify and CircleCI