Skip to content

Commit

Permalink
Merge pull request #35 from storybookjs/feat/CH-1358-support-auto-title
Browse files Browse the repository at this point in the history
Support auto title stories
  • Loading branch information
yannbf committed Jan 31, 2022
2 parents dd3dc55 + 8a26a58 commit b1db5ef
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 13 deletions.
6 changes: 5 additions & 1 deletion .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const { STRESS_TEST, STORY_STORE_V7, WITHOUT_DOCS } = process.env;

const stories = ['../stories/basic/*.stories.mdx', '../stories/basic/*.stories.@(js|jsx|ts|tsx)'];
const stories = [
{
directory: '../stories',
},
];

if (STRESS_TEST) {
stories.push('../stories/stress-test/*.stories.@(js|jsx|ts|tsx)');
Expand Down
2 changes: 1 addition & 1 deletion playwright/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { transformPlaywright } = require('../dist/cjs/playwright/transformPlaywri

module.exports = {
process(src, filename, config) {
const csfTest = transformPlaywright(src);
const csfTest = transformPlaywright(src, filename);

const result = babelTransform(csfTest, {
filename,
Expand Down
12 changes: 9 additions & 3 deletions src/csf/transformCsf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ export interface TestContext {
}
type FilePrefixer = () => t.Statement[];
type TestPrefixer = (context: TestContext) => t.Statement[];
const JEST_GLOBAL_REGEX = /(before|after)(All|Each)$/;

interface TransformOptions {
clearBody?: boolean;
filePrefixer?: FilePrefixer;
testPrefixer?: TestPrefixer;
insertTestIfEmpty?: boolean;
defaultTitle?: string;
}

const prefixFunction = (
Expand Down Expand Up @@ -73,9 +73,15 @@ const makeDescribe = (key: string, tests: t.Statement[]): t.Statement | null =>

export const transformCsf = (
code: string,
{ filePrefixer, clearBody = false, testPrefixer, insertTestIfEmpty }: TransformOptions = {}
{
filePrefixer,
clearBody = false,
testPrefixer,
insertTestIfEmpty,
defaultTitle,
}: TransformOptions = {}
) => {
const csf = loadCsf(code, { defaultTitle: 'FIXME' });
const csf = loadCsf(code, { defaultTitle });
csf.parse();

const storyExports = Object.keys(csf._stories);
Expand Down
2 changes: 1 addition & 1 deletion src/playwright/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { transform as babelTransform } from '@babel/core';
import { transformPlaywright } from './transformPlaywright';

export const process = (src: string, filename: string, config: any) => {
const csfTest = transformPlaywright(src);
const csfTest = transformPlaywright(src, filename);

const result = babelTransform(csfTest, {
filename,
Expand Down
81 changes: 76 additions & 5 deletions src/playwright/transformPlaywright.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
import dedent from 'ts-dedent';
import path from 'path';
import * as coreCommon from '@storybook/core-common';

import { transformPlaywright } from './transformPlaywright';

jest.mock('@storybook/core-common');

expect.addSnapshotSerializer({
print: (val: any) => val.trim(),
test: (val: any) => true,
});

describe('Playwright', () => {
beforeEach(() => {
const relativeSpy = jest.spyOn(path, 'relative');
relativeSpy.mockReturnValueOnce('stories/basic/Header.stories.js');
jest.spyOn(coreCommon, 'serverRequire').mockImplementation(() => ({
stories: [
{
directory: '../stories/basic',
titlePrefix: 'Example',
},
],
}));
jest.spyOn(coreCommon, 'normalizeStories').mockImplementation(() => [
{
titlePrefix: 'Example',
files: '**/*.stories.@(mdx|tsx|ts|jsx|js)',
directory: './stories/basic',
importPathMatcher:
/^\.[\\/](?:stories\/basic(?:\/(?!\.)(?:(?:(?!(?:^|\/)\.).)*?)\/|\/|$)(?!\.)(?=.)[^/]*?\.stories\.(mdx|tsx|ts|jsx|js))$/,
},
]);
});

const filename = './stories/basic/Header.stories.js';
it('should generate a play test when the story has a play function', () => {
expect(
transformPlaywright(dedent`
export default { title: 'foo/bar' };
transformPlaywright(
dedent`
export default { title: 'foo/bar', component: Button };
export const A = () => {};
A.play = () => {};
`)
`,
filename
)
).toMatchInlineSnapshot(`
if (!require.main) {
describe("foo/bar", () => {
Expand Down Expand Up @@ -43,10 +74,13 @@ describe('Playwright', () => {
});
it('should generate a smoke test when story does not have a play function', () => {
expect(
transformPlaywright(dedent`
transformPlaywright(
dedent`
export default { title: 'foo/bar' };
export const A = () => {};
`)
`,
filename
)
).toMatchInlineSnapshot(`
if (!require.main) {
describe("foo/bar", () => {
Expand Down Expand Up @@ -74,4 +108,41 @@ describe('Playwright', () => {
}
`);
});

it('should generate a smoke test with auto title', () => {
expect(
transformPlaywright(
dedent`
export default { component: Button };
export const A = () => {};
`,
filename
)
).toMatchInlineSnapshot(`
if (!require.main) {
describe("Example/Header", () => {
describe("A", () => {
it("smoke-test", async () => {
page.on('pageerror', err => {
page.evaluate(({
id,
err
}) => __throwError(id, err), {
id: "example-header--a",
err: err.message
});
});
return page.evaluate(({
id,
hasPlayFn
}) => __test(id, hasPlayFn), {
id: "example-header--a",
hasPlayFn: false
});
});
});
});
}
`);
});
});
34 changes: 33 additions & 1 deletion src/playwright/transformPlaywright.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { resolve, join, relative } from 'path';
import template from '@babel/template';
import { serverRequire, normalizeStories } from '@storybook/core-common';
import { autoTitle } from '@storybook/store';

import { transformCsf } from '../csf/transformCsf';

export const testPrefixer = template(
Expand All @@ -19,12 +23,40 @@ export const testPrefixer = template(
plugins: ['jsx'],
}
);
export const transformPlaywright = (src: string) => {

const getDefaultTitle = (filename: string) => {
// we'll need to figure this out for different cases
// e.g. --config-dir
const configDir = resolve('.storybook');
const workingDir = resolve();

const main = serverRequire(join(configDir, 'main'));

if (!main) {
throw new Error(`Could not load main.js in ${configDir}`);
}

const normalizedStoriesEntries = normalizeStories(main.stories, {
configDir,
workingDir,
}).map((specifier) => ({
...specifier,
importPathMatcher: new RegExp(specifier.importPathMatcher),
}));

const filePath = './' + relative(workingDir, filename);

return autoTitle(filePath, normalizedStoriesEntries);
};

export const transformPlaywright = (src: string, filename: string) => {
const defaultTitle = getDefaultTitle(filename);
const result = transformCsf(src, {
// @ts-ignore
testPrefixer,
insertTestIfEmpty: true,
clearBody: true,
defaultTitle,
});
return result;
};
1 change: 0 additions & 1 deletion stories/basic/Button.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
import { Button } from './Button';

export default {
title: 'Example/Button',
component: Button,
argTypes: {
onSubmit: { action: true },
Expand Down

0 comments on commit b1db5ef

Please sign in to comment.