Skip to content

Instantly share code, notes, and snippets.

@mfolnovic
Created October 18, 2019 09:40
Show Gist options
  • Save mfolnovic/915c7194bd8249bc6699547ca998aff6 to your computer and use it in GitHub Desktop.
Save mfolnovic/915c7194bd8249bc6699547ca998aff6 to your computer and use it in GitHub Desktop.
Storybook + Jest (React specific)
import React from 'react';
import { storiesOf, getStorybook } from '@storybook/react';
import { startCase } from 'lodash';
import { render } from '@testing-library/react';
// from storybook/lib/core/src/client/preview/start.js
function matches(storyKey: string, arrayOrRegex: any) {
if (Array.isArray(arrayOrRegex)) {
return arrayOrRegex.includes(storyKey);
}
return storyKey.match(arrayOrRegex);
}
// from storybook/lib/core/src/client/preview/start.js
export function isExportStory(
key: string,
{ includeStories, excludeStories }: any
) {
return (
// https://babeljs.io/docs/en/babel-plugin-transform-modules-commonjs
key !== '__esModule' &&
(!includeStories || matches(key, includeStories)) &&
(!excludeStories || !matches(key, excludeStories))
);
}
// from storybook/lib/router/src/utils.ts
function storyNameFromExport(key: string) {
return startCase(key);
}
export default function describeStories(stories: any) {
// from storybook/lib/core/src/client/preview/start.js
const { default: meta, ...exports } = stories;
const {
title: kindName,
parameters: params,
decorators: decos,
component,
} = meta;
// filtering out all non-export stories
const storiesExports = Object.keys(exports).filter(key =>
isExportStory(key, meta)
);
const kind = storiesOf(kindName, stories);
kind.addParameters({
framework: 'react', // hardcoding React
component,
...params,
});
(decos || []).forEach((decorator: any) => {
kind.addDecorator(decorator);
});
storiesExports.forEach(key => {
// from storybook/lib/core/src/client/preview/start.js
const storyFn = exports[key];
const { name, parameters, decorators } = storyFn.story || {};
const decoratorParams = decorators ? { decorators } : null;
const displayNameParams = name ? { displayName: name } : {};
const storyName = storyNameFromExport(key);
kind.add(storyName, storyFn, {
...parameters,
...decoratorParams,
...displayNameParams,
});
});
const storybook = getStorybook();
describe(meta.title, () => {
const section = storybook.find(x => x.kind === kindName) || { stories: [] };
test.each(storiesExports)('%s', async key => {
// Given
const story = section.stories.find(
story => story.name === storyNameFromExport(key)
);
// When
if (story) {
render(<div data-testid="root">{story.render()}</div>);
} else {
fail('Story not found');
}
// Then
await expect('[data-testid=root]').toMatchScreenshot();
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment