Skip to content

Commit

Permalink
Merge pull request #30214 from storybookjs/version-non-patch-from-8.5…
Browse files Browse the repository at this point in the history
….0-beta.8

Release: Prerelease 8.5.0-beta.9
  • Loading branch information
JReinhold authored Jan 13, 2025
2 parents 3b979ee + 0851568 commit 1b3538c
Show file tree
Hide file tree
Showing 24 changed files with 344 additions and 352 deletions.
2 changes: 0 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@ jobs:
yarn bench-packages --upload
- store_artifacts:
path: bench/packages/results.json
- store_artifacts:
path: bench/packages/compare-with-<< pipeline.parameters.ghBaseBranch >>.json
- report-workflow-on-failure
- cancel-workflow-on-failure
check:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 8.5.0-beta.9

- Addon Test: Add prerequisite check for MSW - [#30193](https://github.com/storybookjs/storybook/pull/30193), thanks @yannbf!
- Addon Test: Improve support for mono-repos - [#30216](https://github.com/storybookjs/storybook/pull/30216), thanks @valentinpalkovic!
- Vitest: Add plugins from `viteFinal` - [#30105](https://github.com/storybookjs/storybook/pull/30105), thanks @JReinhold!

## 8.5.0-beta.8

- Automigrations: Skip vite config file migration for react native web - [#30190](https://github.com/storybookjs/storybook/pull/30190), thanks @dannyhw!
Expand Down
11 changes: 9 additions & 2 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
- [Added source code panel to docs](#added-source-code-panel-to-docs)
- [Addon-a11y: Component test integration](#addon-a11y-component-test-integration)
- [Addon-a11y: Deprecated `parameters.a11y.manual`](#addon-a11y-deprecated-parametersa11ymanual)
- [Indexing behavior of @storybook/experimental-addon-test is changed](#indexing-behavior-of-storybookexperimental-addon-test-is-changed)
- [Addon-test: You should no longer copy the content of `viteFinal` to your configuration](#addon-test-you-should-no-longer-copy-the-content-of-vitefinal-to-your-configuration)
- [Addon-test: Indexing behavior of @storybook/experimental-addon-test is changed](#addon-test-indexing-behavior-of-storybookexperimental-addon-test-is-changed)
- [From version 8.2.x to 8.3.x](#from-version-82x-to-83x)
- [Removed `experimental_SIDEBAR_BOTTOM` and deprecated `experimental_SIDEBAR_TOP` addon types](#removed-experimental_sidebar_bottom-and-deprecated-experimental_sidebar_top-addon-types)
- [New parameters format for addon backgrounds](#new-parameters-format-for-addon-backgrounds)
Expand Down Expand Up @@ -484,7 +485,13 @@ beforeAll(annotations.beforeAll);

We have deprecated `parameters.a11y.manual` in 8.5. Please use `globals.a11y.manual` instead.

### Indexing behavior of @storybook/experimental-addon-test is changed
### Addon-test: You should no longer copy the content of `viteFinal` to your configuration

In version 8.4 of `@storybook/experimental-addon-test`, it was required to copy any custom configuration you had in `viteFinal` in `main.ts`, to the Vitest Storybook project. This is no longer necessary, as the Storybook Test plugin will automatically include your `viteFinal` configuration. You should remove any configurations you might already have in `viteFinal` to remove duplicates.

This is especially the case for any plugins you might have, as they could now end up being loaded twice, which is likely to cause errors when running tests. In 8.4 we documented and automatically added some Vite plugins from Storybook frameworks like `@storybook/experimental-nextjs-vite` and `@storybook/sveltekit` - **these needs to be removed as well**.

### Addon-test: Indexing behavior of @storybook/experimental-addon-test is changed

The Storybook test addon used to index stories based on the `test.include` field in the Vitest config file. This caused indexing issues with Storybook, because stories could have been indexed by Storybook and not Vitest, and vice versa. Starting in Storybook 8.5.0-alpha.18, we changed the indexing behavior so that it always uses the globs defined in the `stories` field in `.storybook/main.js` for a more consistent experience. It is now discouraged to use `test.include`, please remove it.

Expand Down
6 changes: 6 additions & 0 deletions code/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ const config: StorybookConfig = {
// disable sourcemaps in CI to not run out of memory
sourcemap: process.env.CI !== 'true',
},
server: {
watch: {
// Something odd happens with tsconfig and nx which causes Storybook to keep reloading, so we ignore them
ignored: ['**/.nx/cache/**', '**/tsconfig.json'],
},
},
} satisfies typeof viteConfig);
},
// logLevel: 'debug',
Expand Down
39 changes: 35 additions & 4 deletions code/addons/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
"!dist/dummy.*",
"README.md",
"*.mjs",
"*.js",
Expand Down Expand Up @@ -151,11 +152,41 @@
],
"nodeEntries": [
"./src/preset.ts",
"./src/vitest-plugin/index.ts",
"./src/vitest-plugin/global-setup.ts",
"./src/postinstall.ts",
"./src/node/vitest.ts",
"./src/node/coverage-reporter.ts"
{
"file": "./src/dummy.ts",
"formats": [
"esm"
]
},
{
"file": "./src/node/vitest.ts",
"formats": [
"esm",
"cjs"
]
},
{
"file": "./src/node/coverage-reporter.ts",
"formats": [
"esm",
"cjs"
]
},
{
"file": "./src/vitest-plugin/index.ts",
"formats": [
"cjs",
"esm"
]
},
{
"file": "./src/vitest-plugin/global-setup.ts",
"formats": [
"cjs",
"esm"
]
}
]
},
"storybook": {
Expand Down
4 changes: 4 additions & 0 deletions code/addons/test/src/dummy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Due to a bug in tsup, this file is necessary because otherwise if for a certain build step a root file isn't given
// tsup will flatten the directory structure and the output will be in the root of the dist output directory
// https://github.com/egoist/tsup/issues/728
export default {};
10 changes: 10 additions & 0 deletions code/addons/test/src/node/vitest-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { TestingModuleRunRequestPayload } from 'storybook/internal/core-eve

import type { DocsIndexEntry, StoryIndex, StoryIndexEntry } from '@storybook/types';

import { findUp } from 'find-up';
import path, { dirname, join, normalize } from 'pathe';
import slash from 'slash';

Expand All @@ -23,6 +24,9 @@ import type { StorybookCoverageReporterOptions } from './coverage-reporter';
import { StorybookReporter } from './reporter';
import type { TestManager } from './test-manager';

const VITEST_CONFIG_FILE_EXTENSIONS = ['mts', 'mjs', 'cts', 'cjs', 'ts', 'tsx', 'js', 'jsx'];
const VITEST_WORKSPACE_FILE_EXTENSION = ['ts', 'js', 'json'];

type TagsFilter = {
include: string[];
exclude: string[];
Expand Down Expand Up @@ -68,7 +72,13 @@ export class VitestManager {
: { enabled: false }
) as CoverageOptions;

const vitestWorkspaceConfig = await findUp([
...VITEST_WORKSPACE_FILE_EXTENSION.map((ext) => `vitest.workspace.${ext}`),
...VITEST_CONFIG_FILE_EXTENSIONS.map((ext) => `vitest.config.${ext}`),
]);

this.vitest = await createVitest('test', {
root: vitestWorkspaceConfig ? dirname(vitestWorkspaceConfig) : process.cwd(),
watch: true,
passWithNoTests: false,
// TODO:
Expand Down
72 changes: 27 additions & 45 deletions code/addons/test/src/postinstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ export default async function postInstall(options: PostinstallOptions) {
`);
}

const mswVersionSpecifier = await packageManager.getInstalledVersion('msw');
const coercedMswVersion = mswVersionSpecifier ? coerce(mswVersionSpecifier) : null;

if (coercedMswVersion && !satisfies(coercedMswVersion, '>=2.0.0')) {
reasons.push(dedent`
• The addon uses Vitest behind the scenes, which supports only version 2 and above of MSW. However, we have detected version ${picocolors.bold(coercedMswVersion.version)} in this project.
Please update the 'msw' package and try again.
`);
}

if (info.frameworkPackageName === '@storybook/nextjs') {
const nextVersion = await packageManager.getInstalledVersion('next');
if (!nextVersion) {
Expand All @@ -159,6 +169,7 @@ export default async function postInstall(options: PostinstallOptions) {
reasons.unshift(
`Storybook Test's automated setup failed due to the following package incompatibilities:`
);
reasons.push('--------------------------------');
reasons.push(
dedent`
You can fix these issues and rerun the command to reinstall. If you wish to roll back the installation, remove ${picocolors.bold(colors.pink(ADDON_NAME))} from the "addons" array
Expand Down Expand Up @@ -226,8 +237,6 @@ export default async function postInstall(options: PostinstallOptions) {
}
}

const vitestInfo = getVitestPluginInfo(info.frameworkPackageName);

if (info.frameworkPackageName === '@storybook/nextjs') {
printInfo(
'🍿 Just so you know...',
Expand Down Expand Up @@ -407,7 +416,13 @@ export default async function postInstall(options: PostinstallOptions) {
browserWorkspaceFile,
dedent`
import { defineWorkspace } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';${vitestInfo.frameworkPluginImport}
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const dirname = typeof __dirname !== 'undefined'
? __dirname
: path.dirname(fileURLToPath(import.meta.url));
// More info at: https://storybook.js.org/docs/writing-tests/test-addon
export default defineWorkspace([
Expand All @@ -417,7 +432,7 @@ export default async function postInstall(options: PostinstallOptions) {
plugins: [
// The plugin will run tests for the stories defined in your Storybook config
// See options at: https://storybook.js.org/docs/writing-tests/test-addon#storybooktest
storybookTest({ configDir: '${options.configDir}' }),${vitestInfo.frameworkPluginDocs + vitestInfo.frameworkPluginCall}
storybookTest({ configDir: path.join(dirname, '${options.configDir}') })
],
test: {
name: 'storybook',
Expand Down Expand Up @@ -447,14 +462,20 @@ export default async function postInstall(options: PostinstallOptions) {
newVitestConfigFile,
dedent`
import { defineConfig } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';${vitestInfo.frameworkPluginImport}
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const dirname = typeof __dirname !== 'undefined'
? __dirname
: path.dirname(fileURLToPath(import.meta.url));
// More info at: https://storybook.js.org/docs/writing-tests/test-addon
export default defineConfig({
plugins: [
// The plugin will run tests for the stories defined in your Storybook config
// See options at: https://storybook.js.org/docs/writing-tests/test-addon#storybooktest
storybookTest({ configDir: '${options.configDir}' }),${vitestInfo.frameworkPluginDocs + vitestInfo.frameworkPluginCall}
storybookTest({ configDir: path.join(dirname, '${options.configDir}') })
],
test: {
name: 'storybook',
Expand Down Expand Up @@ -489,45 +510,6 @@ export default async function postInstall(options: PostinstallOptions) {
logger.line(1);
}

const getVitestPluginInfo = (framework: string) => {
let frameworkPluginImport = '';
let frameworkPluginCall = '';
let frameworkPluginDocs = '';

if (framework === '@storybook/nextjs' || framework === '@storybook/experimental-nextjs-vite') {
frameworkPluginImport =
"import { storybookNextJsPlugin } from '@storybook/experimental-nextjs-vite/vite-plugin';";
frameworkPluginDocs =
'// More info at: https://github.com/storybookjs/vite-plugin-storybook-nextjs';
frameworkPluginCall = 'storybookNextJsPlugin()';
}

if (framework === '@storybook/sveltekit') {
frameworkPluginImport =
"import { storybookSveltekitPlugin } from '@storybook/sveltekit/vite-plugin';";
frameworkPluginCall = 'storybookSveltekitPlugin()';
}

if (framework === '@storybook/vue3-vite') {
frameworkPluginImport =
"import { storybookVuePlugin } from '@storybook/vue3-vite/vite-plugin';";
frameworkPluginCall = 'storybookVuePlugin()';
}

if (framework === '@storybook/react-native-web-vite') {
frameworkPluginImport =
"import { storybookReactNativeWeb } from '@storybook/react-native-web-vite/vite-plugin';";
frameworkPluginCall = 'storybookReactNativeWeb()';
}

// spaces for file indentation
frameworkPluginImport = `\n${frameworkPluginImport}`;
frameworkPluginDocs = frameworkPluginDocs ? `\n ${frameworkPluginDocs}` : '';
frameworkPluginCall = frameworkPluginCall ? `\n ${frameworkPluginCall},` : '';

return { frameworkPluginImport, frameworkPluginCall, frameworkPluginDocs };
};

async function getStorybookInfo({ configDir, packageManager: pkgMgr }: PostinstallOptions) {
const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr });
const packageJson = await packageManager.retrievePackageJson();
Expand Down
37 changes: 29 additions & 8 deletions code/addons/test/src/vitest-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import picocolors from 'picocolors';
import sirv from 'sirv';
import { convertPathToPattern } from 'tinyglobby';
import { dedent } from 'ts-dedent';
import type { PluginOption } from 'vite';

// ! Relative import to prebundle it without needing to depend on the Vite builder
import { withoutVitePlugins } from '../../../../builders/builder-vite/src/utils/without-vite-plugins';
import type { InternalOptions, UserOptions } from './types';

const WORKING_DIR = process.cwd();
Expand Down Expand Up @@ -64,9 +67,9 @@ const getStoryGlobsAndFiles = async (
};
};

const packageDir = dirname(require.resolve('@storybook/experimental-addon-test/package.json'));
const PACKAGE_DIR = dirname(require.resolve('@storybook/experimental-addon-test/package.json'));

export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
export const storybookTest = async (options?: UserOptions): Promise<Plugin[]> => {
const finalOptions = {
...defaultOptions,
...options,
Expand Down Expand Up @@ -109,14 +112,27 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
getStoryGlobsAndFiles(presets, directories),
presets.apply('framework', undefined),
presets.apply('env', {}),
presets.apply('viteFinal', {}),
presets.apply<{ plugins?: Plugin[] }>('viteFinal', {}),
presets.apply('staticDirs', []),
extractTagsFromPreview(finalOptions.configDir),
]);

return {
// filter out plugins that we know are unnecesary for tests, eg. docgen plugins
const plugins = (await withoutVitePlugins(
(viteConfigFromStorybook.plugins as unknown as PluginOption[]) ?? [],
[
'storybook:package-deduplication', // addon-docs
'storybook:mdx-plugin', // addon-docs
'storybook:react-docgen-plugin',
'vite:react-docgen-typescript', // aka @joshwooding/vite-plugin-react-docgen-typescript
'storybook:svelte-docgen-plugin',
'storybook:vue-component-meta-plugin',
'storybook:vue-docgen-plugin',
]
)) as unknown as Plugin[];

const storybookTestPlugin: Plugin = {
name: 'vite-plugin-storybook-test',
enforce: 'pre',
async transformIndexHtml(html) {
const [headHtmlSnippet, bodyHtmlSnippet] = await Promise.all([
presets.apply('previewHead'),
Expand Down Expand Up @@ -153,7 +169,7 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
const baseConfig: Omit<ViteUserConfig, 'plugins'> = {
test: {
setupFiles: [
join(packageDir, 'dist/vitest-plugin/setup-file.mjs'),
join(PACKAGE_DIR, 'dist/vitest-plugin/setup-file.mjs'),
// if the existing setupFiles is a string, we have to include it otherwise we're overwriting it
typeof inputConfig_ONLY_MUTATE_WHEN_STRICTLY_NEEDED_OR_YOU_WILL_BE_FIRED.test
?.setupFiles === 'string' &&
Expand All @@ -162,7 +178,7 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {

...(finalOptions.storybookScript
? {
globalSetup: [join(packageDir, 'dist/vitest-plugin/global-setup.mjs')],
globalSetup: [join(PACKAGE_DIR, 'dist/vitest-plugin/global-setup.mjs')],
}
: {}),

Expand Down Expand Up @@ -245,7 +261,9 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {

optimizeDeps: {
include: [
'@storybook/experimental-addon-test/**',
'@storybook/experimental-addon-test/internal/setup-file',
'@storybook/experimental-addon-test/internal/global-setup',
'@storybook/experimental-addon-test/internal/test-utils',
...(frameworkName?.includes('react') || frameworkName?.includes('nextjs')
? ['react-dom/test-utils']
: []),
Expand Down Expand Up @@ -323,6 +341,9 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
}
},
};

plugins.push(storybookTestPlugin);
return plugins;
};

export default storybookTest;
7 changes: 4 additions & 3 deletions code/frameworks/experimental-nextjs-vite/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry =

export const viteFinal: StorybookConfigVite['viteFinal'] = async (config, options) => {
const reactConfig = await reactViteFinal(config, options);
const { plugins = [] } = reactConfig;

const { nextConfigPath } = await options.presets.apply<FrameworkOptions>('frameworkOptions');

const nextDir = nextConfigPath ? path.dirname(nextConfigPath) : undefined;
plugins.push(vitePluginStorybookNextjs({ dir: nextDir }));

return reactConfig;
return {
...reactConfig,
plugins: [...(reactConfig?.plugins ?? []), vitePluginStorybookNextjs({ dir: nextDir })],
};
};
Loading

0 comments on commit 1b3538c

Please sign in to comment.