Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addon Test: Refactor test addon to include stories automatically #29367

Merged
merged 12 commits into from
Dec 4, 2024
11 changes: 2 additions & 9 deletions code/.storybook/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,13 @@ export default mergeConfig(
],
test: {
name: 'storybook-ui',
include: [
'../addons/**/*.{story,stories}.?(c|m)[jt]s?(x)',
// '../core/template/stories/**/*.{story,stories}.?(c|m)[jt]s?(x)',
'../core/src/manager/**/*.{story,stories}.?(c|m)[jt]s?(x)',
'../core/src/preview-api/**/*.{story,stories}.?(c|m)[jt]s?(x)',
'../core/src/components/{brand,components}/**/*.{story,stories}.?(c|m)[jt]s?(x)',
],
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
exclude: [
...defaultExclude,
'../node_modules/**',
'**/__mockdata__/**',
'../**/__mockdata__/**',
// expected to fail in Vitest because of fetching /iframe.html to cause ECONNREFUSED
'**/Zoom.stories.tsx',
'**/Zoom.stories.tsx', // expected to fail in Vitest because of fetching /iframe.html to cause ECONNREFUSED
'**/lib/blocks/src/**', // won't work because of https://github.com/storybookjs/storybook/issues/29783
],
// TODO: bring this back once portable stories support @storybook/core/preview-api hooks
// @ts-expect-error this type does not exist but the property does!
Expand Down
10 changes: 3 additions & 7 deletions code/addons/test/src/postinstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,6 @@ export default async function postInstall(options: PostinstallOptions) {
// If there's an existing config, we create a workspace file so we can run Storybook tests alongside.
const extension = extname(rootConfig);
const browserWorkspaceFile = resolve(dirname(rootConfig), `vitest.workspace${extension}`);
// to be set in vitest config
const vitestSetupFilePath = relative(dirname(browserWorkspaceFile), vitestSetupFile);

logger.line(1);
logger.plain(`${step} Creating a Vitest project workspace file:`);
Expand All @@ -355,6 +353,7 @@ export default async function postInstall(options: PostinstallOptions) {
{
extends: '${viteConfigFile ? relative(dirname(browserWorkspaceFile), viteConfigFile) : ''}',
plugins: [
// The plugin will run tests in the stories defined in your Storybook config
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
// See options at: https://storybook.js.org/docs/writing-tests/vitest-plugin#storybooktest
storybookTest({ configDir: '${options.configDir}' }),${vitestInfo.frameworkPluginDocs + vitestInfo.frameworkPluginCall}
],
Expand All @@ -366,9 +365,7 @@ export default async function postInstall(options: PostinstallOptions) {
name: 'chromium',
provider: 'playwright',
},
// Make sure to adjust this pattern to match your stories files.
include: ['**/*.stories.?(m)[jt]s?(x)'],
setupFiles: ['${vitestSetupFilePath}'],
setupFiles: ['./.storybook/vitest.setup.ts'],
},
},
]);
Expand All @@ -393,6 +390,7 @@ export default async function postInstall(options: PostinstallOptions) {
// More info at: https://storybook.js.org/docs/writing-tests/vitest-plugin
export default defineConfig({
plugins: [
// The plugin will run tests in the stories defined in your Storybook config
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
// See options at: https://storybook.js.org/docs/writing-tests/vitest-plugin#storybooktest
storybookTest({ configDir: '${options.configDir}' }),${vitestInfo.frameworkPluginDocs + vitestInfo.frameworkPluginCall}
],
Expand All @@ -404,8 +402,6 @@ export default async function postInstall(options: PostinstallOptions) {
name: 'chromium',
provider: 'playwright',
},
// Make sure to adjust this pattern to match your stories files.
include: ['**/*.stories.?(m)[jt]s?(x)'],
setupFiles: ['${vitestSetupFilePath}'],
},
});
Expand Down
41 changes: 35 additions & 6 deletions code/addons/test/src/vitest-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import type { Plugin } from 'vitest/config';
import {
getInterpretedFile,
loadAllPresets,
normalizeStories,
validateConfigurationFiles,
} from 'storybook/internal/common';
import { StoryIndexGenerator } from 'storybook/internal/core-server';
import { readConfig, vitestTransform } from 'storybook/internal/csf-tools';
import { MainFileMissingError } from 'storybook/internal/server-errors';
import type { StoriesEntry } from 'storybook/internal/types';
import type { DocsOptions, StoriesEntry } from 'storybook/internal/types';

import { join, resolve } from 'pathe';

Expand Down Expand Up @@ -51,15 +53,15 @@ export const storybookTest = (options?: UserOptions): Plugin => {
process.env.__STORYBOOK_URL__ = storybookUrl;
process.env.__STORYBOOK_SCRIPT__ = finalOptions.storybookScript;

let stories: StoriesEntry[];

if (!finalOptions.configDir) {
finalOptions.configDir = resolve(join(process.cwd(), '.storybook'));
} else {
finalOptions.configDir = resolve(process.cwd(), finalOptions.configDir);
}

let previewLevelTags: string[];
let storiesGlobs: StoriesEntry[];
let storiesFiles: string[];

return {
name: 'vite-plugin-storybook-test',
Expand All @@ -82,7 +84,27 @@ export const storybookTest = (options?: UserOptions): Plugin => {
packageJson: {},
});

stories = await presets.apply('stories', []);
const workingDir = process.cwd();
const directories = {
configDir,
workingDir,
};
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
storiesGlobs = await presets.apply('stories');
const indexers = await presets.apply('experimental_indexers', []);
const docsOptions = await presets.apply<DocsOptions>('docs', {});
const normalizedStories = normalizeStories(await storiesGlobs, directories);

const generator = new StoryIndexGenerator(normalizedStories, {
...directories,
indexers: indexers,
docs: docsOptions,
workingDir,
});

await generator.initialize();

storiesFiles = generator.storyFileNames();

previewLevelTags = await extractTagsFromPreview(configDir);

const framework = await presets.apply('framework', undefined);
Expand All @@ -92,8 +114,15 @@ export const storybookTest = (options?: UserOptions): Plugin => {
// const isRunningInBrowserMode = config.plugins.find((plugin: Plugin) =>
// plugin.name?.startsWith('vitest:browser')
// )

config.test ??= {};

config.test.include ??= [];
config.test.include.push(...storiesFiles);
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved

config.test.exclude ??= [];
config.test.exclude.push('**/*.mdx');

config.test.env ??= {};
config.test.env = {
...config.test.env,
Expand Down Expand Up @@ -163,13 +192,13 @@ export const storybookTest = (options?: UserOptions): Plugin => {
return code;
}

if (id.match(/(story|stories)\.[cm]?[jt]sx?$/)) {
if (storiesFiles.includes(id)) {
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
return vitestTransform({
code,
fileName: id,
configDir: finalOptions.configDir,
tagsFilter: finalOptions.tags,
stories,
stories: storiesGlobs,
previewLevelTags,
});
}
Expand Down
1 change: 1 addition & 0 deletions code/core/src/core-server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './build-static';
export * from './build-dev';
export * from './withTelemetry';
export { default as build } from './standalone';
export { StoryIndexGenerator } from './utils/StoryIndexGenerator';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Exposing internal utilities like StoryIndexGenerator could make it harder to refactor internals in the future. Consider creating a dedicated public API for story file discovery instead.

5 changes: 1 addition & 4 deletions scripts/tasks/sandbox-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,14 +498,11 @@ export async function setupVitest(details: TemplateDetails, options: PassedOptio
test: {
name: "storybook",
pool: "threads",
include: [
"src/**/*.{story,stories}.?(c|m)[jt]s?(x)",
"template-stories/**/*.{story,stories}.?(c|m)[jt]s?(x)",
],
exclude: [
...defaultExclude,
// TODO: investigate TypeError: Cannot read properties of null (reading 'useContext')
"**/*argtypes*",
${template.expected.renderer === '@storybook/svelte' ? '"**/*.stories.svelte",' : ''}
],
Comment on lines +505 to 506
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Svelte stories exclusion should be conditional on both renderer AND framework being Svelte to handle SvelteKit case

/**
* TODO: Either fix or acknowledge limitation of:
Expand Down
Loading