Skip to content

Commit

Permalink
Merge pull request #341 from storybookjs/next
Browse files Browse the repository at this point in the history
Release 0.13.0
  • Loading branch information
yannbf authored Aug 4, 2023
2 parents c19da16 + 5cce841 commit f7bd91a
Show file tree
Hide file tree
Showing 29 changed files with 2,372 additions and 2,243 deletions.
3 changes: 1 addition & 2 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const addons = [
: '@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-coverage',
'@storybook/addon-mdx-gfm',
];
module.exports = {
stories,
Expand All @@ -40,7 +39,7 @@ module.exports = {
disableTelemetry: true,
},
framework: {
name: '@storybook/react-webpack5',
name: '@storybook/react-vite',
options: {},
},
docs: {
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Usage: test-storybook [options]
| `--watch` | Watch files for changes and rerun tests related to changed files.<br/>`test-storybook --watch` |
| `--watchAll` | Watch files for changes and rerun all tests when something changes.<br/>`test-storybook --watchAll` |
| `--coverage` | Indicates that test coverage information should be collected and reported in the output <br/>`test-storybook --coverage` |
| `--coverageDirectory` | Directory where to write coverage report output <br/>`test-storybook --coverage --coverageDirectory coverage/ui/storybook` |
| `--url` | Define the URL to run tests in. Useful for custom Storybook URLs <br/>`test-storybook --url http://the-storybook-url-here.com` |
| `--browsers` | Define browsers to run tests in. One or multiple of: chromium, firefox, webkit <br/>`test-storybook --browsers firefox chromium` |
| `--maxWorkers [amount]` | Specifies the maximum number of workers the worker-pool will spawn for running tests <br/>`test-storybook --maxWorkers=2` |
Expand All @@ -150,6 +151,7 @@ Usage: test-storybook [options]
| `--junit` | Indicates that test information should be reported in a junit file. <br/>`test-storybook --**junit**` |
| `--ci` | Instead of the regular behavior of storing a new snapshot automatically, it will fail the test and require Jest to be run with `--updateSnapshot`. <br/>`test-storybook --ci` |
| `--shard [shardIndex/shardCount]` | Splits your test suite across different machines to run in CI. <br/>`test-storybook --shard=1/3` |
| `--failOnConsole` | Makes tests fail on browser console errors<br/>`test-storybook --failOnConsole` |

## Ejecting configuration

Expand Down
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"build-storybook": "storybook build",
"release": "yarn build && auto shipit",
"test-storybook": "node dist/test-storybook",
"test-storybook:failures": "SKIP_SNAPSHOTS=true TEST_FAILURES=1 yarn test-storybook --json --outputFile test-results.json",
"test-storybook:failures": "SKIP_SNAPSHOTS=true TEST_FAILURES=1 yarn test-storybook --json --failOnConsole --outputFile test-results.json",
"test-storybook:no-cache": "yarn test-storybook --no-cache",
"test-storybook:json": "yarn test-storybook --stories-json",
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"yarn build-storybook --quiet && npx serve storybook-static -l 6006\" \"wait-on tcp:6006 && yarn test-storybook\"",
Expand All @@ -55,15 +55,15 @@
"@babel/preset-typescript": "^7.18.6",
"@jest/types": "^28.1.3",
"@storybook/addon-coverage": "^0.0.7",
"@storybook/addon-essentials": "^7.0.0",
"@storybook/addon-interactions": "^7.0.0",
"@storybook/addon-mdx-gfm": "^7.0.0",
"@storybook/addon-essentials": "^7.2.0",
"@storybook/addon-interactions": "^7.2.0",
"@storybook/jest": "^0.1.0",
"@storybook/react": "^7.0.0",
"@storybook/react-webpack5": "^7.0.0",
"@storybook/testing-library": "^0.1.0",
"@storybook/react": "^7.2.0",
"@storybook/react-vite": "^7.2.0",
"@storybook/testing-library": "^0.2.0",
"@types/jest": "^27.0.3",
"@types/node": "^16.4.1",
"@vitejs/plugin-react": "^4.0.3",
"auto": "^10.3.0",
"babel-jest": "^28.1.3",
"babel-loader": "^8.1.0",
Expand All @@ -73,30 +73,23 @@
"jest-image-snapshot": "^5.1.0",
"lint-staged": "^13.0.3",
"prettier": "^2.8.1",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"rimraf": "^3.0.2",
"semver": "^7.3.7",
"storybook": "^7.0.0",
"storybook": "^7.2.0",
"ts-jest": "^28.0.8",
"tsup": "^6.5.0",
"typescript": "~4.9.4",
"wait-on": "^6.0.0"
"wait-on": "^6.0.0",
"vite": "^4.4.5"
},
"lint-staged": {
"*.{ts,js,tsx,jsx,css,md}": "prettier --write"
},
"publishConfig": {
"access": "public"
},
"storybook": {
"displayName": "Storybook test runner",
"unsupportedFrameworks": [
"react-native"
],
"icon": "https://user-images.githubusercontent.com/321738/63501763-88dbf600-c4cc-11e9-96cd-94adadc2fd72.png"
},
"dependencies": {
"@babel/core": "^7.22.5",
"@babel/generator": "^7.22.5",
Expand Down Expand Up @@ -136,5 +129,12 @@
"npm",
"released"
]
},
"storybook": {
"displayName": "Storybook test runner",
"unsupportedFrameworks": [
"react-native"
],
"icon": "https://user-images.githubusercontent.com/321738/63501763-88dbf600-c4cc-11e9-96cd-94adadc2fd72.png"
}
}
19 changes: 12 additions & 7 deletions src/config/jest-playwright.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import path from 'path';
import { getProjectRoot } from '@storybook/core-common';

const TEST_RUNNER_PATH = process.env.STORYBOOK_TEST_RUNNER_PATH || '@storybook/test-runner';

/**
* IMPORTANT NOTE:
Expand All @@ -25,11 +28,11 @@ const getJestPlaywrightConfig = () => {
);
return {
runner: path.join(presetBasePath, 'runner.js'),
globalSetup: '@storybook/test-runner/playwright/global-setup.js',
globalTeardown: '@storybook/test-runner/playwright/global-teardown.js',
testEnvironment: '@storybook/test-runner/playwright/custom-environment.js',
globalSetup: require.resolve(TEST_RUNNER_PATH + '/playwright/global-setup.js'),
globalTeardown: require.resolve(TEST_RUNNER_PATH + '/playwright/global-teardown.js'),
testEnvironment: require.resolve(TEST_RUNNER_PATH + '/playwright/custom-environment.js'),
setupFilesAfterEnv: [
'@storybook/test-runner/playwright/jest-setup.js',
require.resolve(TEST_RUNNER_PATH + '/playwright/jest-setup.js'),
expectPlaywrightPath,
path.join(presetBasePath, 'lib', 'extends.js'),
],
Expand Down Expand Up @@ -66,13 +69,15 @@ export const getJestConfig = () => {

const reporters = STORYBOOK_JUNIT ? ['default', jestJunitPath] : ['default'];

const testMatch = (STORYBOOK_STORIES_PATTERN && STORYBOOK_STORIES_PATTERN.split(';')) || [];

let config = {
rootDir: process.cwd(),
rootDir: getProjectRoot(),
roots: TEST_ROOT ? [TEST_ROOT] : undefined,
reporters,
testMatch: STORYBOOK_STORIES_PATTERN && STORYBOOK_STORIES_PATTERN.split(';'),
testMatch,
transform: {
'^.+\\.stories\\.[jt]sx?$': '@storybook/test-runner/playwright/transform',
'^.+\\.stories\\.[jt]sx?$': require.resolve(TEST_RUNNER_PATH + '/playwright/transform'),
'^.+\\.[jt]sx?$': swcJestPath,
},
snapshotSerializers: [jestSerializerHtmlPath],
Expand Down
24 changes: 13 additions & 11 deletions src/playwright/transformPlaywright.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import dedent from 'ts-dedent';
import path from 'path';
import * as coreCommon from '@storybook/core-common';
import * as storybookMain from '../util/getStorybookMain';

import { transformPlaywright } from './transformPlaywright';

jest.mock('@storybook/core-common');
jest.mock('@storybook/core-common', () => ({
...jest.requireActual('@storybook/core-common'),
getProjectRoot: jest.fn(() => '/foo/bar'),
normalizeStories: jest.fn(() => [
{
titlePrefix: 'Example',
files: '**/*.stories.@(mdx|tsx|ts|jsx|js)',
directory: './stories/basic',
importPathMatcher:
/^\.[\\/](?:stories\/basic(?:\/(?!\.)(?:(?:(?!(?:^|\/)\.).)*?)\/|\/|$)(?!\.)(?=.)[^/]*?\.stories\.(mdx|tsx|ts|jsx|js))$/,
},
]),
}));

expect.addSnapshotSerializer({
print: (val: any) => val.trim(),
Expand All @@ -24,15 +35,6 @@ describe('Playwright', () => {
},
],
}));
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';
Expand Down
15 changes: 14 additions & 1 deletion src/setup-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const sanitizeURL = (url: string) => {

export const setupPage = async (page: Page, browserContext: BrowserContext) => {
const targetURL = process.env.TARGET_URL;
const failOnConsole = process.env.TEST_CHECK_CONSOLE;

const viewMode = process.env.VIEW_MODE || 'story';
const renderedEvent = viewMode === 'docs' ? 'docsRendered' : 'storyRendered';
Expand Down Expand Up @@ -215,6 +216,9 @@ export const setupPage = async (page: Page, browserContext: BrowserContext) => {
// end of fast-safe-stringify code
function composeMessage(args) {
if (args instanceof Error) {
return \`\${args.name}: \${args.message}\\n\${args.stack}\`;
}
if (typeof args === 'undefined') return "undefined";
if (typeof args === 'string') return args;
return stringify(args, null, null, { depthLimit: 5, edgesLimit: 100 });
Expand Down Expand Up @@ -306,10 +310,14 @@ export const setupPage = async (page: Page, browserContext: BrowserContext) => {
// collect logs to show upon test error
let logs = [];
let hasErrors = false;
const spyOnConsole = (method, name) => {
const originalFn = console[method];
return function () {
if (\`${failOnConsole}\`==='true' && method==='error') {
hasErrors = true;
}
const message = [...arguments].map(composeMessage).join(', ');
const prefix = \`\${bold(name)}: \`;
logs.push(prefix + message);
Expand All @@ -332,7 +340,12 @@ export const setupPage = async (page: Page, browserContext: BrowserContext) => {
})
return new Promise((resolve, reject) => {
channel.on('${renderedEvent}', () => resolve(document.getElementById('root')));
channel.on('${renderedEvent}', () => {
if (hasErrors) {
return reject(new StorybookTestRunnerError(storyId, 'Browser console errors', logs));
}
return resolve(document.getElementById('root'));
});
channel.on('storyUnchanged', () => resolve(document.getElementById('root')));
channel.on('storyErrored', ({ description }) => reject(
new StorybookTestRunnerError(storyId, description, logs))
Expand Down
13 changes: 12 additions & 1 deletion src/test-storybook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ const cleanup = () => {

async function reportCoverage() {
const coverageFolderE2E = path.resolve(process.cwd(), '.nyc_output');
const coverageFolder = path.resolve(process.cwd(), 'coverage/storybook');
const coverageFolder = path.resolve(
process.cwd(),
process.env.STORYBOOK_COVERAGE_DIRECTORY ?? 'coverage/storybook'
);

// in case something goes wrong and .nyc_output does not exist, bail
if (!fs.existsSync(coverageFolderE2E)) {
Expand Down Expand Up @@ -260,6 +263,10 @@ const main = async () => {
process.env.STORYBOOK_COLLECT_COVERAGE = 'true';
}

if (runnerOptions.coverageDirectory) {
process.env.STORYBOOK_COVERAGE_DIRECTORY = runnerOptions.coverageDirectory;
}

if (runnerOptions.junit) {
process.env.STORYBOOK_JUNIT = 'true';
}
Expand Down Expand Up @@ -297,6 +304,10 @@ const main = async () => {
const { storiesPaths, lazyCompilation } = getStorybookMetadata();
process.env.STORYBOOK_STORIES_PATTERN = storiesPaths;

if (runnerOptions.failOnConsole) {
process.env.TEST_CHECK_CONSOLE = 'true';
}

if (lazyCompilation && isLocalStorybookIp) {
log(
`You're running Storybook with lazy compilation enabled, and will likely cause issues with the test runner locally. Consider disabling 'lazyCompilation' in ${runnerOptions.configDir}/main.js when running 'test-storybook' locally.`
Expand Down
9 changes: 9 additions & 0 deletions src/util/getCliOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ describe('getCliOptions', () => {
expect(opts.runnerOptions).toMatchObject(customConfig);
});

it('returns failOnConsole option if passed', () => {
const customConfig = { failOnConsole: true };
jest
.spyOn(cliHelper, 'getParsedCliOptions')
.mockReturnValue({ options: customConfig, extraArgs: [] });
const opts = getCliOptions();
expect(opts.runnerOptions).toMatchObject(customConfig);
});

it('returns extra args if passed', () => {
const extraArgs = ['TestName', 'AnotherTestName'];
// mock argv to avoid side effect from running tests e.g. jest --coverage,
Expand Down
4 changes: 4 additions & 0 deletions src/util/getCliOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ export type CliOptions = {
configDir?: string;
eject?: boolean;
coverage?: boolean;
coverageDirectory?: string;
junit?: boolean;
browsers?: BrowserType | BrowserType[];
failOnConsole?: boolean;
};
jestOptions: JestOptions;
};
Expand All @@ -25,7 +27,9 @@ const STORYBOOK_RUNNER_COMMANDS: StorybookRunnerCommand[] = [
'eject',
'url',
'coverage',
'coverageDirectory',
'junit',
'failOnConsole',
];

function copyOption<ObjType extends object, KeyType extends keyof ObjType>(
Expand Down
8 changes: 7 additions & 1 deletion src/util/getParsedCliOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ export const getParsedCliOptions = (): ParsedCliOptions => {
'--coverage',
'Indicates that test coverage information should be collected and reported in the output'
)
.option(
'--coverageDirectory <directory>',
'Directory where to write coverage report output',
'coverage/storybook'
)
.option('--junit', 'Indicates that test information should be reported in a junit file')
.option(
'--eject',
Expand All @@ -70,7 +75,8 @@ export const getParsedCliOptions = (): ParsedCliOptions => {
.option(
'--shard <shardIndex/shardCount>',
'Splits your test suite across different machines to run in CI.'
);
)
.option('--failOnConsole', 'Makes tests fail on browser console errors');

program.exitOverride();

Expand Down
22 changes: 19 additions & 3 deletions src/util/getStorybookMetadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ import * as storybookMain from './getStorybookMain';

import { getStorybookMetadata } from './getStorybookMetadata';

jest.mock('@storybook/core-common', () => ({
...jest.requireActual('@storybook/core-common'),
getProjectRoot: jest.fn(() => '/foo/bar'),
normalizeStories: jest.fn(() => [
{
titlePrefix: 'Example',
files: '**/*.stories.@(mdx|tsx|ts|jsx|js)',
directory: './stories/basic',
importPathMatcher:
/^\.[\\/](?:stories\/basic(?:\/(?!\.)(?:(?:(?!(?:^|\/)\.).)*?)\/|\/|$)(?!\.)(?=.)[^/]*?\.stories\.(mdx|tsx|ts|jsx|js))$/,
},
]),
}));

describe('getStorybookMetadata', () => {
afterAll(() => {
process.env.STORYBOOK_CONFIG_DIR = undefined;
Expand Down Expand Up @@ -32,7 +46,7 @@ describe('getStorybookMetadata', () => {
process.env.STORYBOOK_CONFIG_DIR = '.storybook';
const { storiesPaths } = getStorybookMetadata();
expect(storiesPaths).toMatchInlineSnapshot(
`"<rootDir>/stories/basic/**/*.@(mdx|stories.@(tsx|ts|jsx|js))"`
`"/foo/bar/stories/basic/**/*.stories.@(mdx|tsx|ts|jsx|js)"`
);
});

Expand All @@ -44,7 +58,9 @@ describe('getStorybookMetadata', () => {
jest.spyOn(storybookMain, 'getStorybookMain').mockReturnValueOnce(mockedMain);
process.env.STORYBOOK_CONFIG_DIR = '.storybook';
const { storiesPaths } = getStorybookMetadata();
expect(storiesPaths).toMatchInlineSnapshot(`"<rootDir>/**/stories/*.stories.@(js|ts)"`);
expect(storiesPaths).toMatchInlineSnapshot(
`"/foo/bar/stories/basic/**/*.stories.@(mdx|tsx|ts|jsx|js)"`
);
});

it('should return storiesPath from mixed CSF2 and CSF3 style config', () => {
Expand All @@ -62,7 +78,7 @@ describe('getStorybookMetadata', () => {
process.env.STORYBOOK_CONFIG_DIR = '.storybook';
const { storiesPaths } = getStorybookMetadata();
expect(storiesPaths).toMatchInlineSnapshot(
`"<rootDir>/stories/basic/**/*.@(mdx|stories.@(tsx|ts|jsx|js));<rootDir>/stories/complex/*.stories.@(js|ts)"`
`"/foo/bar/stories/basic/**/*.stories.@(mdx|tsx|ts|jsx|js)"`
);
});

Expand Down
Loading

0 comments on commit f7bd91a

Please sign in to comment.