mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
Merge branch 'next' into issue-26056-fix-mixed-extends-import-problem
This commit is contained in:
commit
cda2e71f1f
@ -2,7 +2,6 @@ import { dirname, join, resolve } from 'path';
|
||||
import { DefinePlugin, HotModuleReplacementPlugin, ProgressPlugin, ProvidePlugin } from 'webpack';
|
||||
import type { Configuration } from 'webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
|
||||
// @ts-expect-error (I removed this on purpose, because it's incorrect)
|
||||
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
|
||||
import TerserWebpackPlugin from 'terser-webpack-plugin';
|
||||
@ -54,11 +53,7 @@ const storybookPaths: Record<string, string> = {
|
||||
};
|
||||
|
||||
export default async (
|
||||
options: Options & {
|
||||
typescriptOptions: TypescriptOptions;
|
||||
/* Build entries, which should not be linked in the iframe HTML file */
|
||||
excludeChunks?: string[];
|
||||
}
|
||||
options: Options & { typescriptOptions: TypescriptOptions }
|
||||
): Promise<Configuration> => {
|
||||
const {
|
||||
outputDir = join('.', 'public'),
|
||||
@ -69,7 +64,6 @@ export default async (
|
||||
previewUrl,
|
||||
typescriptOptions,
|
||||
features,
|
||||
excludeChunks = [],
|
||||
} = options;
|
||||
|
||||
const isProd = configType === 'PRODUCTION';
|
||||
@ -178,7 +172,6 @@ export default async (
|
||||
alwaysWriteToDisk: true,
|
||||
inject: false,
|
||||
template,
|
||||
excludeChunks,
|
||||
templateParameters: {
|
||||
version: packageJson.version,
|
||||
globals: {
|
||||
|
43
code/e2e-tests/composition.spec.ts
Normal file
43
code/e2e-tests/composition.spec.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { SbPage } from './util';
|
||||
|
||||
const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:6006';
|
||||
|
||||
// This is a slow test, and (presumably) framework independent, so only run it on one sandbox
|
||||
const skipTest = process.env.STORYBOOK_TEMPLATE_NAME !== 'react-vite/default-ts';
|
||||
|
||||
test.describe('composition', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
if (skipTest) return;
|
||||
await page.goto(storybookUrl);
|
||||
await new SbPage(page).waitUntilLoaded();
|
||||
});
|
||||
|
||||
test('should correctly filter composed stories', async ({ page }) => {
|
||||
if (skipTest) return;
|
||||
|
||||
// Expect that composed Storybooks are visible
|
||||
await expect(await page.getByTitle('Storybook 8.0.0')).toBeVisible();
|
||||
await expect(await page.getByTitle('Storybook 7.6.18')).toBeVisible();
|
||||
|
||||
// Expect composed stories to be available in the sidebar
|
||||
await page.locator('[id="storybook\\@8\\.0\\.0_components-badge"]').click();
|
||||
await expect(
|
||||
await page.locator('[id="storybook\\@8\\.0\\.0_components-badge--default"]')
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('[id="storybook\\@7\\.6\\.18_components-badge"]').click();
|
||||
await expect(
|
||||
await page.locator('[id="storybook\\@7\\.6\\.18_components-badge--default"]')
|
||||
).toBeVisible();
|
||||
|
||||
// Expect composed stories `to be available in the search
|
||||
await page.getByPlaceholder('Find components').fill('Button');
|
||||
await expect(
|
||||
await page.getByRole('option', { name: 'Button Storybook 8.0.0 / @blocks / examples' })
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
await page.getByRole('option', { name: 'Button Storybook 7.6.18 / @blocks / examples' })
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
@ -1,22 +1,36 @@
|
||||
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||
import {
|
||||
BuilderContext,
|
||||
BuilderHandlerFn,
|
||||
BuilderOutput,
|
||||
BuilderOutputLike,
|
||||
Target,
|
||||
createBuilder,
|
||||
targetFromTargetString,
|
||||
} from '@angular-devkit/architect';
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
import { from, of, throwError } from 'rxjs';
|
||||
import { catchError, map, mapTo, switchMap } from 'rxjs/operators';
|
||||
import { sync as findUpSync } from 'find-up';
|
||||
import { sync as readUpSync } from 'read-pkg-up';
|
||||
import { BrowserBuilderOptions, StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
||||
|
||||
import { CLIOptions } from '@storybook/types';
|
||||
import { getEnvConfig, versions } from '@storybook/core-common';
|
||||
import { addToGlobalContext } from '@storybook/telemetry';
|
||||
|
||||
import { buildStaticStandalone, withTelemetry } from '@storybook/core-server';
|
||||
import { StyleClass } from '@angular-devkit/build-angular/src/builders/browser/schema';
|
||||
import {
|
||||
AssetPattern,
|
||||
SourceMapUnion,
|
||||
StyleElement,
|
||||
} from '@angular-devkit/build-angular/src/builders/browser/schema';
|
||||
import { StandaloneOptions } from '../utils/standalone-options';
|
||||
import { runCompodoc } from '../utils/run-compodoc';
|
||||
import { errorSummary, printErrorDetails } from '../utils/error-handler';
|
||||
import { AngularBuilderOptions, setup } from '../utils/setup';
|
||||
|
||||
addToGlobalContext('cliVersion', versions.storybook);
|
||||
|
||||
export type StorybookBuilderOptions = AngularBuilderOptions & {
|
||||
export type StorybookBuilderOptions = JsonObject & {
|
||||
browserTarget?: string | null;
|
||||
tsConfig?: string;
|
||||
test: boolean;
|
||||
@ -24,6 +38,10 @@ export type StorybookBuilderOptions = AngularBuilderOptions & {
|
||||
compodoc: boolean;
|
||||
compodocArgs: string[];
|
||||
enableProdMode?: boolean;
|
||||
styles?: StyleElement[];
|
||||
stylePreprocessorOptions?: StylePreprocessorOptions;
|
||||
assets?: AssetPattern[];
|
||||
sourceMap?: SourceMapUnion;
|
||||
} & Pick<
|
||||
// makes sure the option exists
|
||||
CLIOptions,
|
||||
@ -41,77 +59,112 @@ export type StorybookBuilderOptions = AngularBuilderOptions & {
|
||||
|
||||
export type StorybookBuilderOutput = JsonObject & BuilderOutput & { [key: string]: any };
|
||||
|
||||
type StandaloneBuildOptions = StandaloneOptions & { outputDir: string; excludeChunks: string[] };
|
||||
type StandaloneBuildOptions = StandaloneOptions & { outputDir: string };
|
||||
|
||||
const commandBuilder = async (
|
||||
options: StorybookBuilderOptions,
|
||||
context: BuilderContext
|
||||
): Promise<BuilderOutput> => {
|
||||
const { tsConfig, angularBuilderContext, angularBuilderOptions } = await setup(options, context);
|
||||
const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (
|
||||
options,
|
||||
context
|
||||
): BuilderOutputLike => {
|
||||
const builder = from(setup(options, context)).pipe(
|
||||
switchMap(({ tsConfig }) => {
|
||||
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
||||
const runCompodoc$ = options.compodoc
|
||||
? runCompodoc(
|
||||
{ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig },
|
||||
context
|
||||
).pipe(mapTo({ tsConfig }))
|
||||
: of({});
|
||||
|
||||
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
||||
return runCompodoc$.pipe(mapTo({ tsConfig }));
|
||||
}),
|
||||
map(({ tsConfig }) => {
|
||||
getEnvConfig(options, {
|
||||
staticDir: 'SBCONFIG_STATIC_DIR',
|
||||
outputDir: 'SBCONFIG_OUTPUT_DIR',
|
||||
configDir: 'SBCONFIG_CONFIG_DIR',
|
||||
});
|
||||
|
||||
if (options.compodoc) {
|
||||
await runCompodoc(
|
||||
{ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig },
|
||||
context
|
||||
);
|
||||
}
|
||||
const {
|
||||
browserTarget,
|
||||
stylePreprocessorOptions,
|
||||
styles,
|
||||
configDir,
|
||||
docs,
|
||||
loglevel,
|
||||
test,
|
||||
outputDir,
|
||||
quiet,
|
||||
enableProdMode = true,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
debugWebpack,
|
||||
disableTelemetry,
|
||||
assets,
|
||||
previewUrl,
|
||||
sourceMap = false,
|
||||
} = options;
|
||||
|
||||
getEnvConfig(options, {
|
||||
staticDir: 'SBCONFIG_STATIC_DIR',
|
||||
outputDir: 'SBCONFIG_OUTPUT_DIR',
|
||||
configDir: 'SBCONFIG_CONFIG_DIR',
|
||||
});
|
||||
const standaloneOptions: StandaloneBuildOptions = {
|
||||
packageJson: readUpSync({ cwd: __dirname }).packageJson,
|
||||
configDir,
|
||||
...(docs ? { docs } : {}),
|
||||
loglevel,
|
||||
outputDir,
|
||||
test,
|
||||
quiet,
|
||||
enableProdMode,
|
||||
disableTelemetry,
|
||||
angularBrowserTarget: browserTarget,
|
||||
angularBuilderContext: context,
|
||||
angularBuilderOptions: {
|
||||
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
|
||||
...(styles ? { styles } : {}),
|
||||
...(assets ? { assets } : {}),
|
||||
sourceMap,
|
||||
},
|
||||
tsConfig,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
debugWebpack,
|
||||
previewUrl,
|
||||
};
|
||||
|
||||
const {
|
||||
configDir,
|
||||
docs,
|
||||
loglevel,
|
||||
test,
|
||||
outputDir,
|
||||
quiet,
|
||||
enableProdMode = true,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
debugWebpack,
|
||||
disableTelemetry,
|
||||
previewUrl,
|
||||
} = options;
|
||||
return standaloneOptions;
|
||||
}),
|
||||
switchMap((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })),
|
||||
map(() => {
|
||||
return { success: true };
|
||||
})
|
||||
);
|
||||
|
||||
const standaloneOptions: StandaloneBuildOptions = {
|
||||
packageJson: readUpSync({ cwd: __dirname }).packageJson,
|
||||
configDir,
|
||||
...(docs ? { docs } : {}),
|
||||
excludeChunks: angularBuilderOptions.styles
|
||||
?.filter((style) => typeof style !== 'string' && style.inject === false)
|
||||
.map((s: StyleClass) => s.bundleName),
|
||||
loglevel,
|
||||
outputDir,
|
||||
test,
|
||||
quiet,
|
||||
enableProdMode,
|
||||
disableTelemetry,
|
||||
angularBrowserTarget: options.browserTarget,
|
||||
angularBuilderContext,
|
||||
angularBuilderOptions,
|
||||
tsConfig,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
debugWebpack,
|
||||
previewUrl,
|
||||
};
|
||||
|
||||
await runInstance({ ...standaloneOptions, mode: 'static' });
|
||||
|
||||
return { success: true };
|
||||
return builder as any as BuilderOutput;
|
||||
};
|
||||
|
||||
export default createBuilder(commandBuilder);
|
||||
|
||||
async function runInstance(options: StandaloneBuildOptions) {
|
||||
try {
|
||||
await withTelemetry(
|
||||
async function setup(options: StorybookBuilderOptions, context: BuilderContext) {
|
||||
let browserOptions: (JsonObject & BrowserBuilderOptions) | undefined;
|
||||
let browserTarget: Target | undefined;
|
||||
|
||||
if (options.browserTarget) {
|
||||
browserTarget = targetFromTargetString(options.browserTarget);
|
||||
browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
|
||||
await context.getTargetOptions(browserTarget),
|
||||
await context.getBuilderNameForTarget(browserTarget)
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
tsConfig:
|
||||
options.tsConfig ??
|
||||
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
||||
browserOptions.tsConfig,
|
||||
};
|
||||
}
|
||||
|
||||
function runInstance(options: StandaloneBuildOptions) {
|
||||
return from(
|
||||
withTelemetry(
|
||||
'build',
|
||||
{
|
||||
cliOptions: options,
|
||||
@ -119,8 +172,6 @@ async function runInstance(options: StandaloneBuildOptions) {
|
||||
printError: printErrorDetails,
|
||||
},
|
||||
() => buildStaticStandalone(options)
|
||||
);
|
||||
} catch (error) {
|
||||
throw new Error(errorSummary(error));
|
||||
}
|
||||
)
|
||||
).pipe(catchError((error: any) => throwError(errorSummary(error))));
|
||||
}
|
||||
|
@ -1,6 +1,15 @@
|
||||
import { BuilderHandlerFn, BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||
import {
|
||||
BuilderContext,
|
||||
BuilderHandlerFn,
|
||||
BuilderOutput,
|
||||
Target,
|
||||
createBuilder,
|
||||
targetFromTargetString,
|
||||
} from '@angular-devkit/architect';
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
||||
import { BrowserBuilderOptions, StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
||||
import { from, Observable, of } from 'rxjs';
|
||||
import { map, switchMap, mapTo } from 'rxjs/operators';
|
||||
import { sync as findUpSync } from 'find-up';
|
||||
import { sync as readUpSync } from 'read-pkg-up';
|
||||
|
||||
@ -11,22 +20,24 @@ import { buildDevStandalone, withTelemetry } from '@storybook/core-server';
|
||||
import {
|
||||
AssetPattern,
|
||||
SourceMapUnion,
|
||||
StyleClass,
|
||||
StyleElement,
|
||||
} from '@angular-devkit/build-angular/src/builders/browser/schema';
|
||||
import { StandaloneOptions } from '../utils/standalone-options';
|
||||
import { runCompodoc } from '../utils/run-compodoc';
|
||||
import { printErrorDetails, errorSummary } from '../utils/error-handler';
|
||||
import { AngularBuilderOptions, setup } from '../utils/setup';
|
||||
|
||||
addToGlobalContext('cliVersion', versions.storybook);
|
||||
|
||||
export type StorybookBuilderOptions = AngularBuilderOptions & {
|
||||
export type StorybookBuilderOptions = JsonObject & {
|
||||
browserTarget?: string | null;
|
||||
tsConfig?: string;
|
||||
compodoc: boolean;
|
||||
compodocArgs: string[];
|
||||
enableProdMode?: boolean;
|
||||
styles?: StyleElement[];
|
||||
stylePreprocessorOptions?: StylePreprocessorOptions;
|
||||
assets?: AssetPattern[];
|
||||
sourceMap?: SourceMapUnion;
|
||||
} & Pick<
|
||||
// makes sure the option exists
|
||||
CLIOptions,
|
||||
@ -53,96 +64,131 @@ export type StorybookBuilderOptions = AngularBuilderOptions & {
|
||||
|
||||
export type StorybookBuilderOutput = JsonObject & BuilderOutput & {};
|
||||
|
||||
const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = async (options, context) => {
|
||||
const { tsConfig, angularBuilderContext, angularBuilderOptions } = await setup(options, context);
|
||||
const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (options, context) => {
|
||||
const builder = from(setup(options, context)).pipe(
|
||||
switchMap(({ tsConfig }) => {
|
||||
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
||||
|
||||
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
||||
const runCompodoc$ = options.compodoc
|
||||
? runCompodoc(
|
||||
{
|
||||
compodocArgs: [...options.compodocArgs, ...(options.quiet ? ['--silent'] : [])],
|
||||
tsconfig: docTSConfig ?? tsConfig,
|
||||
},
|
||||
context
|
||||
).pipe(mapTo({ tsConfig }))
|
||||
: of({});
|
||||
|
||||
if (options.compodoc) {
|
||||
await runCompodoc(
|
||||
{
|
||||
compodocArgs: [...options.compodocArgs, ...(options.quiet ? ['--silent'] : [])],
|
||||
tsconfig: docTSConfig ?? tsConfig,
|
||||
},
|
||||
context
|
||||
);
|
||||
}
|
||||
return runCompodoc$.pipe(mapTo({ tsConfig }));
|
||||
}),
|
||||
map(({ tsConfig }) => {
|
||||
getEnvConfig(options, {
|
||||
port: 'SBCONFIG_PORT',
|
||||
host: 'SBCONFIG_HOSTNAME',
|
||||
staticDir: 'SBCONFIG_STATIC_DIR',
|
||||
configDir: 'SBCONFIG_CONFIG_DIR',
|
||||
ci: 'CI',
|
||||
});
|
||||
|
||||
getEnvConfig(options, {
|
||||
port: 'SBCONFIG_PORT',
|
||||
host: 'SBCONFIG_HOSTNAME',
|
||||
staticDir: 'SBCONFIG_STATIC_DIR',
|
||||
configDir: 'SBCONFIG_CONFIG_DIR',
|
||||
ci: 'CI',
|
||||
});
|
||||
options.port = parseInt(`${options.port}`, 10);
|
||||
|
||||
options.port = parseInt(`${options.port}`, 10);
|
||||
const {
|
||||
browserTarget,
|
||||
stylePreprocessorOptions,
|
||||
styles,
|
||||
ci,
|
||||
configDir,
|
||||
docs,
|
||||
host,
|
||||
https,
|
||||
port,
|
||||
quiet,
|
||||
enableProdMode = false,
|
||||
smokeTest,
|
||||
sslCa,
|
||||
sslCert,
|
||||
sslKey,
|
||||
disableTelemetry,
|
||||
assets,
|
||||
initialPath,
|
||||
open,
|
||||
debugWebpack,
|
||||
loglevel,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
previewUrl,
|
||||
sourceMap = false,
|
||||
} = options;
|
||||
|
||||
const {
|
||||
browserTarget,
|
||||
ci,
|
||||
configDir,
|
||||
docs,
|
||||
host,
|
||||
https,
|
||||
port,
|
||||
quiet,
|
||||
enableProdMode = false,
|
||||
smokeTest,
|
||||
sslCa,
|
||||
sslCert,
|
||||
sslKey,
|
||||
disableTelemetry,
|
||||
initialPath,
|
||||
open,
|
||||
debugWebpack,
|
||||
loglevel,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
previewUrl,
|
||||
} = options;
|
||||
const standaloneOptions: StandaloneOptions = {
|
||||
packageJson: readUpSync({ cwd: __dirname }).packageJson,
|
||||
ci,
|
||||
configDir,
|
||||
...(docs ? { docs } : {}),
|
||||
host,
|
||||
https,
|
||||
port,
|
||||
quiet,
|
||||
enableProdMode,
|
||||
smokeTest,
|
||||
sslCa,
|
||||
sslCert,
|
||||
sslKey,
|
||||
disableTelemetry,
|
||||
angularBrowserTarget: browserTarget,
|
||||
angularBuilderContext: context,
|
||||
angularBuilderOptions: {
|
||||
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
|
||||
...(styles ? { styles } : {}),
|
||||
...(assets ? { assets } : {}),
|
||||
sourceMap,
|
||||
},
|
||||
tsConfig,
|
||||
initialPath,
|
||||
open,
|
||||
debugWebpack,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
loglevel,
|
||||
previewUrl,
|
||||
};
|
||||
|
||||
const standaloneOptions: StandaloneOptions = {
|
||||
packageJson: readUpSync({ cwd: __dirname }).packageJson,
|
||||
ci,
|
||||
configDir,
|
||||
...(docs ? { docs } : {}),
|
||||
excludeChunks: angularBuilderOptions.styles
|
||||
?.filter((style) => typeof style !== 'string' && style.inject === false)
|
||||
.map((s: StyleClass) => s.bundleName),
|
||||
host,
|
||||
https,
|
||||
port,
|
||||
quiet,
|
||||
enableProdMode,
|
||||
smokeTest,
|
||||
sslCa,
|
||||
sslCert,
|
||||
sslKey,
|
||||
disableTelemetry,
|
||||
angularBrowserTarget: browserTarget,
|
||||
angularBuilderContext,
|
||||
angularBuilderOptions,
|
||||
tsConfig,
|
||||
initialPath,
|
||||
open,
|
||||
debugWebpack,
|
||||
webpackStatsJson,
|
||||
statsJson,
|
||||
loglevel,
|
||||
previewUrl,
|
||||
};
|
||||
return standaloneOptions;
|
||||
}),
|
||||
switchMap((standaloneOptions) => runInstance(standaloneOptions)),
|
||||
map((port: number) => {
|
||||
return { success: true, info: { port } };
|
||||
})
|
||||
);
|
||||
|
||||
const devPort = await runInstance(standaloneOptions);
|
||||
|
||||
return { success: true, info: { port: devPort } };
|
||||
return builder as any as BuilderOutput;
|
||||
};
|
||||
|
||||
export default createBuilder(commandBuilder);
|
||||
|
||||
async function runInstance(options: StandaloneOptions): Promise<number> {
|
||||
try {
|
||||
const { port } = await withTelemetry(
|
||||
async function setup(options: StorybookBuilderOptions, context: BuilderContext) {
|
||||
let browserOptions: (JsonObject & BrowserBuilderOptions) | undefined;
|
||||
let browserTarget: Target | undefined;
|
||||
|
||||
if (options.browserTarget) {
|
||||
browserTarget = targetFromTargetString(options.browserTarget);
|
||||
browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
|
||||
await context.getTargetOptions(browserTarget),
|
||||
await context.getBuilderNameForTarget(browserTarget)
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
tsConfig:
|
||||
options.tsConfig ??
|
||||
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
||||
browserOptions.tsConfig,
|
||||
};
|
||||
}
|
||||
function runInstance(options: StandaloneOptions) {
|
||||
return new Observable<number>((observer) => {
|
||||
// This Observable intentionally never complete, leaving the process running ;)
|
||||
withTelemetry(
|
||||
'dev',
|
||||
{
|
||||
cliOptions: options,
|
||||
@ -150,9 +196,10 @@ async function runInstance(options: StandaloneOptions): Promise<number> {
|
||||
printError: printErrorDetails,
|
||||
},
|
||||
() => buildDevStandalone(options)
|
||||
);
|
||||
return port;
|
||||
} catch (error) {
|
||||
throw new Error(errorSummary(error));
|
||||
}
|
||||
)
|
||||
.then(({ port }) => observer.next(port))
|
||||
.catch((error) => {
|
||||
observer.error(errorSummary(error));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { vi, describe, afterEach, it, expect } from 'vitest';
|
||||
import { LoggerApi } from '@angular-devkit/core/src/logger';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
|
||||
import { runCompodoc } from './run-compodoc';
|
||||
@ -36,13 +37,15 @@ describe('runCompodoc', () => {
|
||||
} as BuilderContext;
|
||||
|
||||
it('should run compodoc with tsconfig from context', async () => {
|
||||
await runCompodoc(
|
||||
runCompodoc(
|
||||
{
|
||||
compodocArgs: [],
|
||||
tsconfig: 'path/to/tsconfig.json',
|
||||
},
|
||||
builderContextMock
|
||||
);
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe();
|
||||
|
||||
expect(mockRunScript).toHaveBeenCalledWith(
|
||||
'compodoc',
|
||||
@ -53,13 +56,15 @@ describe('runCompodoc', () => {
|
||||
});
|
||||
|
||||
it('should run compodoc with tsconfig from compodocArgs', async () => {
|
||||
await runCompodoc(
|
||||
runCompodoc(
|
||||
{
|
||||
compodocArgs: ['-p', 'path/to/tsconfig.stories.json'],
|
||||
tsconfig: 'path/to/tsconfig.json',
|
||||
},
|
||||
builderContextMock
|
||||
);
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe();
|
||||
|
||||
expect(mockRunScript).toHaveBeenCalledWith(
|
||||
'compodoc',
|
||||
@ -70,13 +75,15 @@ describe('runCompodoc', () => {
|
||||
});
|
||||
|
||||
it('should run compodoc with default output folder.', async () => {
|
||||
await runCompodoc(
|
||||
runCompodoc(
|
||||
{
|
||||
compodocArgs: [],
|
||||
tsconfig: 'path/to/tsconfig.json',
|
||||
},
|
||||
builderContextMock
|
||||
);
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe();
|
||||
|
||||
expect(mockRunScript).toHaveBeenCalledWith(
|
||||
'compodoc',
|
||||
@ -87,13 +94,15 @@ describe('runCompodoc', () => {
|
||||
});
|
||||
|
||||
it('should run with custom output folder specified with --output compodocArgs', async () => {
|
||||
await runCompodoc(
|
||||
runCompodoc(
|
||||
{
|
||||
compodocArgs: ['--output', 'path/to/customFolder'],
|
||||
tsconfig: 'path/to/tsconfig.json',
|
||||
},
|
||||
builderContextMock
|
||||
);
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe();
|
||||
|
||||
expect(mockRunScript).toHaveBeenCalledWith(
|
||||
'compodoc',
|
||||
@ -104,13 +113,15 @@ describe('runCompodoc', () => {
|
||||
});
|
||||
|
||||
it('should run with custom output folder specified with -d compodocArgs', async () => {
|
||||
await runCompodoc(
|
||||
runCompodoc(
|
||||
{
|
||||
compodocArgs: ['-d', 'path/to/customFolder'],
|
||||
tsconfig: 'path/to/tsconfig.json',
|
||||
},
|
||||
builderContextMock
|
||||
);
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe();
|
||||
|
||||
expect(mockRunScript).toHaveBeenCalledWith(
|
||||
'compodoc',
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
import { Observable } from 'rxjs';
|
||||
import * as path from 'path';
|
||||
import { JsPackageManagerFactory } from '@storybook/core-common';
|
||||
|
||||
@ -12,30 +13,34 @@ const toRelativePath = (pathToTsConfig: string) => {
|
||||
return path.isAbsolute(pathToTsConfig) ? path.relative('.', pathToTsConfig) : pathToTsConfig;
|
||||
};
|
||||
|
||||
export const runCompodoc = async (
|
||||
export const runCompodoc = (
|
||||
{ compodocArgs, tsconfig }: { compodocArgs: string[]; tsconfig: string },
|
||||
context: BuilderContext
|
||||
): Promise<void> => {
|
||||
const tsConfigPath = toRelativePath(tsconfig);
|
||||
const finalCompodocArgs = [
|
||||
...(hasTsConfigArg(compodocArgs) ? [] : ['-p', tsConfigPath]),
|
||||
...(hasOutputArg(compodocArgs) ? [] : ['-d', `${context.workspaceRoot || '.'}`]),
|
||||
...compodocArgs,
|
||||
];
|
||||
): Observable<void> => {
|
||||
return new Observable<void>((observer) => {
|
||||
const tsConfigPath = toRelativePath(tsconfig);
|
||||
const finalCompodocArgs = [
|
||||
...(hasTsConfigArg(compodocArgs) ? [] : ['-p', tsConfigPath]),
|
||||
...(hasOutputArg(compodocArgs) ? [] : ['-d', `${context.workspaceRoot || '.'}`]),
|
||||
...compodocArgs,
|
||||
];
|
||||
|
||||
const packageManager = JsPackageManagerFactory.getPackageManager();
|
||||
const packageManager = JsPackageManagerFactory.getPackageManager();
|
||||
|
||||
try {
|
||||
const stdout = packageManager.runPackageCommandSync(
|
||||
'compodoc',
|
||||
finalCompodocArgs,
|
||||
context.workspaceRoot,
|
||||
'inherit'
|
||||
);
|
||||
try {
|
||||
const stdout = packageManager.runPackageCommandSync(
|
||||
'compodoc',
|
||||
finalCompodocArgs,
|
||||
context.workspaceRoot,
|
||||
'inherit'
|
||||
);
|
||||
|
||||
context.logger.info(stdout);
|
||||
} catch (e) {
|
||||
context.logger.error(e);
|
||||
throw e;
|
||||
}
|
||||
context.logger.info(stdout);
|
||||
observer.next();
|
||||
observer.complete();
|
||||
} catch (e) {
|
||||
context.logger.error(e);
|
||||
observer.error();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,109 +0,0 @@
|
||||
import { Target, targetFromTargetString } from '@angular-devkit/architect';
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
import { JsonObject, logging } from '@angular-devkit/core';
|
||||
import { sync as findUpSync } from 'find-up';
|
||||
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
|
||||
export type AngularBuilderOptions = BrowserBuilderOptions & {
|
||||
browserTarget?: string | null;
|
||||
configDir?: string;
|
||||
};
|
||||
|
||||
export async function setup(
|
||||
{ stylePreprocessorOptions, styles, assets, sourceMap, ...options }: AngularBuilderOptions,
|
||||
context: BuilderContext
|
||||
) {
|
||||
let browserOptions: BrowserBuilderOptions | undefined;
|
||||
let browserTarget: Target | undefined;
|
||||
|
||||
if (options.browserTarget) {
|
||||
browserTarget = targetFromTargetString(options.browserTarget);
|
||||
browserOptions = await context.validateOptions<any>(
|
||||
await context.getTargetOptions(browserTarget),
|
||||
await context.getBuilderNameForTarget(browserTarget)
|
||||
);
|
||||
}
|
||||
|
||||
const tsConfig =
|
||||
options.tsConfig ??
|
||||
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
||||
browserOptions.tsConfig;
|
||||
|
||||
const angularBuilderContext = getBuilderContext(context);
|
||||
|
||||
const angularBuilderOptions = await getBuilderOptions(
|
||||
options.browserTarget,
|
||||
{
|
||||
...options,
|
||||
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
|
||||
...(styles ? { styles } : {}),
|
||||
...(assets ? { assets } : {}),
|
||||
sourceMap: sourceMap ?? false,
|
||||
},
|
||||
tsConfig,
|
||||
options.configDir,
|
||||
angularBuilderContext
|
||||
);
|
||||
|
||||
return {
|
||||
tsConfig,
|
||||
angularBuilderContext,
|
||||
angularBuilderOptions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Builder Context
|
||||
* If storybook is not start by angular builder create dumb BuilderContext
|
||||
*/
|
||||
function getBuilderContext(builderContext: BuilderContext): BuilderContext {
|
||||
return (
|
||||
builderContext ??
|
||||
({
|
||||
target: { project: 'noop-project', builder: '', options: {} },
|
||||
workspaceRoot: process.cwd(),
|
||||
getProjectMetadata: () => ({}),
|
||||
getTargetOptions: () => ({}),
|
||||
logger: new logging.Logger('Storybook'),
|
||||
} as unknown as BuilderContext)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get builder options
|
||||
* Merge target options from browser target and from storybook options
|
||||
*/
|
||||
async function getBuilderOptions(
|
||||
angularBrowserTarget: string,
|
||||
angularBuilderOptions: AngularBuilderOptions,
|
||||
tsConfig: string,
|
||||
configDir: string,
|
||||
builderContext: BuilderContext
|
||||
): Promise<BrowserBuilderOptions> {
|
||||
/**
|
||||
* Get Browser Target options
|
||||
*/
|
||||
let browserTargetOptions: JsonObject = {};
|
||||
|
||||
if (angularBrowserTarget) {
|
||||
const browserTarget = targetFromTargetString(angularBrowserTarget);
|
||||
|
||||
browserTargetOptions = await builderContext.getTargetOptions(browserTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge target options from browser target options and from storybook options
|
||||
*/
|
||||
const builderOptions = {
|
||||
...browserTargetOptions,
|
||||
...angularBuilderOptions,
|
||||
tsConfig:
|
||||
tsConfig ??
|
||||
findUpSync('tsconfig.json', { cwd: configDir }) ??
|
||||
(browserTargetOptions.tsConfig as string),
|
||||
};
|
||||
logger.info(`=> Using angular project with "tsConfig:${builderOptions.tsConfig}"`);
|
||||
|
||||
return builderOptions;
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
|
||||
import {
|
||||
AssetPattern,
|
||||
SourceMapUnion,
|
||||
StyleElement,
|
||||
StylePreprocessorOptions,
|
||||
} from '@angular-devkit/build-angular/src/builders/browser/schema';
|
||||
import { LoadOptions, CLIOptions, BuilderOptions } from '@storybook/types';
|
||||
import { AngularBuilderOptions } from './setup';
|
||||
|
||||
export type StandaloneOptions = CLIOptions &
|
||||
LoadOptions &
|
||||
@ -9,8 +13,12 @@ export type StandaloneOptions = CLIOptions &
|
||||
mode?: 'static' | 'dev';
|
||||
enableProdMode: boolean;
|
||||
angularBrowserTarget?: string | null;
|
||||
angularBuilderOptions?: AngularBuilderOptions;
|
||||
angularBuilderOptions?: Record<string, any> & {
|
||||
styles?: StyleElement[];
|
||||
stylePreprocessorOptions?: StylePreprocessorOptions;
|
||||
assets?: AssetPattern[];
|
||||
sourceMap?: SourceMapUnion;
|
||||
};
|
||||
angularBuilderContext?: BuilderContext | null;
|
||||
tsConfig?: string;
|
||||
excludeChunks?: string[];
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
import { AngularBuilderOptions } from '../builders/utils/setup';
|
||||
|
||||
export declare function getWebpackConfig(
|
||||
baseConfig: any,
|
||||
options: { builderOptions: AngularBuilderOptions; builderContext: BuilderContext }
|
||||
options: { builderOptions: JsonObject; builderContext: BuilderContext }
|
||||
): any;
|
||||
|
@ -56,7 +56,6 @@ exports.getWebpackConfig = async (baseConfig, { builderOptions, builderContext }
|
||||
*/
|
||||
const { getCommonConfig, getStylesConfig, getDevServerConfig, getTypeScriptConfig } =
|
||||
getAngularWebpackUtils();
|
||||
|
||||
const { config: cliConfig } = await generateI18nBrowserWebpackConfigFromContext(
|
||||
{
|
||||
// Default options
|
||||
@ -66,15 +65,10 @@ exports.getWebpackConfig = async (baseConfig, { builderOptions, builderContext }
|
||||
|
||||
// Options provided by user
|
||||
...builderOptions,
|
||||
styles: builderOptions.styles?.map((style) =>
|
||||
typeof style === 'string'
|
||||
? {
|
||||
input: style,
|
||||
inject: true,
|
||||
bundleName: style.split('/').pop(),
|
||||
}
|
||||
: style
|
||||
),
|
||||
styles: builderOptions.styles
|
||||
?.map((style) => (typeof style === 'string' ? style : style.input))
|
||||
.filter((style) => typeof style === 'string' || style.inject !== false),
|
||||
|
||||
// Fixed options
|
||||
optimization: false,
|
||||
namedChunks: false,
|
||||
|
@ -1,6 +1,9 @@
|
||||
import webpack from 'webpack';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { AngularLegacyBuildOptionsError } from '@storybook/core-events/server-errors';
|
||||
import { BuilderContext, targetFromTargetString } from '@angular-devkit/architect';
|
||||
import { sync as findUpSync } from 'find-up';
|
||||
import { JsonObject, logging } from '@angular-devkit/core';
|
||||
|
||||
import { getWebpackConfig as getCustomWebpackConfig } from './angular-cli-webpack';
|
||||
import { moduleIsAvailable } from './utils/module-is-available';
|
||||
@ -14,15 +17,74 @@ export async function webpackFinal(baseConfig: webpack.Configuration, options: P
|
||||
|
||||
checkForLegacyBuildOptions(options);
|
||||
|
||||
const builderContext = getBuilderContext(options);
|
||||
const builderOptions = await getBuilderOptions(options, builderContext);
|
||||
|
||||
return getCustomWebpackConfig(baseConfig, {
|
||||
builderOptions: {
|
||||
watch: options.configType === 'DEVELOPMENT',
|
||||
...options.angularBuilderOptions,
|
||||
...builderOptions,
|
||||
},
|
||||
builderContext: options.angularBuilderContext,
|
||||
builderContext,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Builder Context
|
||||
* If storybook is not start by angular builder create dumb BuilderContext
|
||||
*/
|
||||
function getBuilderContext(options: PresetOptions): BuilderContext {
|
||||
return (
|
||||
options.angularBuilderContext ??
|
||||
({
|
||||
target: { project: 'noop-project', builder: '', options: {} },
|
||||
workspaceRoot: process.cwd(),
|
||||
getProjectMetadata: () => ({}),
|
||||
getTargetOptions: () => ({}),
|
||||
logger: new logging.Logger('Storybook'),
|
||||
} as unknown as BuilderContext)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get builder options
|
||||
* Merge target options from browser target and from storybook options
|
||||
*/
|
||||
async function getBuilderOptions(
|
||||
options: PresetOptions,
|
||||
builderContext: BuilderContext
|
||||
): Promise<JsonObject> {
|
||||
/**
|
||||
* Get Browser Target options
|
||||
*/
|
||||
let browserTargetOptions: JsonObject = {};
|
||||
if (options.angularBrowserTarget) {
|
||||
const browserTarget = targetFromTargetString(options.angularBrowserTarget);
|
||||
|
||||
logger.info(
|
||||
`=> Using angular browser target options from "${browserTarget.project}:${
|
||||
browserTarget.target
|
||||
}${browserTarget.configuration ? `:${browserTarget.configuration}` : ''}"`
|
||||
);
|
||||
browserTargetOptions = await builderContext.getTargetOptions(browserTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge target options from browser target options and from storybook options
|
||||
*/
|
||||
const builderOptions = {
|
||||
...browserTargetOptions,
|
||||
...(options.angularBuilderOptions as JsonObject),
|
||||
tsConfig:
|
||||
options.tsConfig ??
|
||||
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
||||
browserTargetOptions.tsConfig,
|
||||
};
|
||||
logger.info(`=> Using angular project with "tsConfig:${builderOptions.tsConfig}"`);
|
||||
|
||||
return builderOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if using legacy configuration that doesn't use builder and logs message referring to migration docs.
|
||||
*/
|
||||
|
@ -1,13 +1,17 @@
|
||||
import { Options as CoreOptions } from '@storybook/types';
|
||||
|
||||
import { BuilderContext } from '@angular-devkit/architect';
|
||||
import { AngularBuilderOptions } from '../builders/utils/setup';
|
||||
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
||||
import { StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
|
||||
|
||||
export type PresetOptions = CoreOptions & {
|
||||
/* Allow to get the options of a targeted "browser builder" */
|
||||
angularBrowserTarget?: string | null;
|
||||
/* Defined set of options. These will take over priority from angularBrowserTarget options */
|
||||
angularBuilderOptions?: AngularBuilderOptions;
|
||||
angularBuilderOptions?: {
|
||||
styles?: StyleElement[];
|
||||
stylePreprocessorOptions?: StylePreprocessorOptions;
|
||||
};
|
||||
/* Angular context from builder */
|
||||
angularBuilderContext?: BuilderContext | null;
|
||||
tsConfig?: string;
|
||||
|
@ -88,7 +88,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -119,7 +119,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -150,7 +150,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -192,7 +192,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -294,7 +294,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -440,7 +440,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -593,7 +593,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -656,7 +656,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -714,7 +714,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -771,7 +771,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -789,7 +789,7 @@ describe('StoryIndexGenerator', () => {
|
||||
expect(await generator.getIndex()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -832,7 +832,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -933,7 +933,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "docs",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -1066,7 +1066,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "docs",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -1127,7 +1127,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "docs",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
@ -1176,7 +1176,7 @@ describe('StoryIndexGenerator', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -592,7 +592,7 @@ export class StoryIndexGenerator {
|
||||
);
|
||||
|
||||
this.lastIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: sorted,
|
||||
};
|
||||
|
||||
|
@ -263,7 +263,7 @@ describe('useStoriesJson', () => {
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
}, 20_000);
|
||||
|
@ -38,7 +38,7 @@ describe('summarizeIndex', () => {
|
||||
it('example stories', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'example-introduction--docs': {
|
||||
id: 'example-introduction--docs',
|
||||
@ -146,14 +146,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 0,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('onboarding stories', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'example-introduction--docs': {
|
||||
id: 'example-introduction--docs',
|
||||
@ -204,14 +204,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 0,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('user stories', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'stories-renderers-react-errors--story-contains-unrenderable': {
|
||||
id: 'stories-renderers-react-errors--story-contains-unrenderable',
|
||||
@ -260,14 +260,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 4,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('pages', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'example-page--logged-out': {
|
||||
id: 'example-page--logged-out',
|
||||
@ -317,14 +317,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 1,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 1,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('storiesMdx', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'stories-renderers-react-react-mdx--docs': {
|
||||
id: 'stories-renderers-react-react-mdx--docs',
|
||||
@ -374,14 +374,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 1,
|
||||
"storyCount": 3,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('autodocs', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'example-button--docs': {
|
||||
id: 'example-button--docs',
|
||||
@ -432,14 +432,14 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 0,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('mdx', () => {
|
||||
expect(
|
||||
summarizeIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'example-introduction--docs': {
|
||||
id: 'example-introduction--docs',
|
||||
@ -483,7 +483,7 @@ describe('summarizeIndex', () => {
|
||||
"playStoryCount": 0,
|
||||
"storiesMdxCount": 0,
|
||||
"storyCount": 0,
|
||||
"version": 4,
|
||||
"version": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import type { StoryIndexV2, StoryIndexV3 } from '@storybook/types';
|
||||
import { transformStoryIndexV2toV3, transformStoryIndexV3toV4 } from './stories';
|
||||
import type { StoryIndexV2, StoryIndexV3, API_PreparedStoryIndex } from '@storybook/types';
|
||||
import {
|
||||
transformStoryIndexV2toV3,
|
||||
transformStoryIndexV3toV4,
|
||||
transformStoryIndexV4toV5,
|
||||
} from './stories';
|
||||
import { mockEntries } from '../tests/mockStoriesEntries';
|
||||
|
||||
const baseV2: StoryIndexV2['stories'][0] = {
|
||||
id: '1',
|
||||
@ -151,3 +156,61 @@ describe('transformStoryIndexV3toV4', () => {
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformStoryIndexV4toV5', () => {
|
||||
it('transforms a StoryIndexV4 to an API_PreparedStoryIndex correctly', () => {
|
||||
const indexV4: API_PreparedStoryIndex = {
|
||||
v: 4,
|
||||
entries: mockEntries,
|
||||
};
|
||||
|
||||
expect(transformStoryIndexV4toV5(indexV4)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"entries": {
|
||||
"component-a--docs": {
|
||||
"id": "component-a--docs",
|
||||
"importPath": "./path/to/component-a.ts",
|
||||
"name": "Docs",
|
||||
"storiesImports": [],
|
||||
"tags": [
|
||||
"dev",
|
||||
],
|
||||
"title": "Component A",
|
||||
"type": "docs",
|
||||
},
|
||||
"component-a--story-1": {
|
||||
"id": "component-a--story-1",
|
||||
"importPath": "./path/to/component-a.ts",
|
||||
"name": "Story 1",
|
||||
"tags": [
|
||||
"dev",
|
||||
],
|
||||
"title": "Component A",
|
||||
"type": "story",
|
||||
},
|
||||
"component-a--story-2": {
|
||||
"id": "component-a--story-2",
|
||||
"importPath": "./path/to/component-a.ts",
|
||||
"name": "Story 2",
|
||||
"tags": [
|
||||
"dev",
|
||||
],
|
||||
"title": "Component A",
|
||||
"type": "story",
|
||||
},
|
||||
"component-b--story-3": {
|
||||
"id": "component-b--story-3",
|
||||
"importPath": "./path/to/component-b.ts",
|
||||
"name": "Story 3",
|
||||
"tags": [
|
||||
"dev",
|
||||
],
|
||||
"title": "Component B",
|
||||
"type": "story",
|
||||
},
|
||||
},
|
||||
"v": 5,
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
@ -86,7 +86,7 @@ export const transformSetStoriesStoryDataToPreparedStoryIndex = (
|
||||
{} as API_PreparedStoryIndex['entries']
|
||||
);
|
||||
|
||||
return { v: 4, entries };
|
||||
return { v: 5, entries };
|
||||
};
|
||||
|
||||
export const transformStoryIndexV2toV3 = (index: StoryIndexV2): StoryIndexV3 => {
|
||||
@ -139,6 +139,30 @@ export const transformStoryIndexV3toV4 = (index: StoryIndexV3): API_PreparedStor
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Storybook 8.0 and below did not automatically tag stories with 'dev'.
|
||||
* Therefore Storybook 8.1 and above would not show composed 8.0 stories by default.
|
||||
* This function adds the 'dev' tag to all stories in the index to workaround this issue.
|
||||
*/
|
||||
export const transformStoryIndexV4toV5 = (
|
||||
index: API_PreparedStoryIndex
|
||||
): API_PreparedStoryIndex => {
|
||||
return {
|
||||
v: 5,
|
||||
entries: Object.values(index.entries).reduce(
|
||||
(acc, entry) => {
|
||||
acc[entry.id] = {
|
||||
...entry,
|
||||
tags: entry.tags ? [...entry.tags, 'dev'] : ['dev'],
|
||||
};
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as API_PreparedStoryIndex['entries']
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
type ToStoriesHashOptions = {
|
||||
provider: API_Provider<API>;
|
||||
docsOptions: DocsOptions;
|
||||
@ -157,6 +181,7 @@ export const transformStoryIndexToStoriesHash = (
|
||||
let index = input;
|
||||
index = index.v === 2 ? transformStoryIndexV2toV3(index as any) : index;
|
||||
index = index.v === 3 ? transformStoryIndexV3toV4(index as any) : index;
|
||||
index = index.v === 4 ? transformStoryIndexV4toV5(index as any) : index;
|
||||
index = index as API_PreparedStoryIndex;
|
||||
|
||||
const entryValues = Object.values(index.entries).filter((entry: any) => {
|
||||
|
@ -448,7 +448,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPrivate: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPrivate: {
|
||||
ok: true,
|
||||
@ -506,7 +506,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -524,7 +524,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -542,7 +542,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPrivate: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPrivate: {
|
||||
ok: true,
|
||||
@ -603,7 +603,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -622,7 +622,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPrivate: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPrivate: {
|
||||
ok: true,
|
||||
@ -684,7 +684,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -781,7 +781,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPrivate: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPrivate: {
|
||||
ok: true,
|
||||
@ -927,7 +927,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPublic: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPublic: {
|
||||
ok: true,
|
||||
@ -989,7 +989,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -1008,7 +1008,7 @@ describe('Refs API', () => {
|
||||
setupResponses({
|
||||
indexPrivate: {
|
||||
ok: true,
|
||||
response: async () => ({ v: 4, entries: {} }),
|
||||
response: async () => ({ v: 5, entries: {} }),
|
||||
},
|
||||
storiesPrivate: {
|
||||
ok: true,
|
||||
@ -1070,7 +1070,7 @@ describe('Refs API', () => {
|
||||
"index": {},
|
||||
"internal_index": {
|
||||
"entries": {},
|
||||
"v": 4,
|
||||
"v": 5,
|
||||
},
|
||||
"title": "Fake",
|
||||
"type": "lazy",
|
||||
@ -1206,7 +1206,7 @@ describe('Refs API', () => {
|
||||
describe('setRef', () => {
|
||||
it('can filter', async () => {
|
||||
const index: StoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'a--1': {
|
||||
id: 'a--1',
|
||||
|
@ -38,7 +38,7 @@ vi.mock('../lib/events', () => ({
|
||||
vi.mock('@storybook/global', () => ({
|
||||
global: {
|
||||
...globalThis,
|
||||
fetch: vi.fn(() => ({ json: () => ({ v: 4, entries: mockGetEntries() }) })),
|
||||
fetch: vi.fn(() => ({ json: () => ({ v: 5, entries: mockGetEntries() }) })),
|
||||
CONFIG_TYPE: 'DEVELOPMENT',
|
||||
},
|
||||
}));
|
||||
@ -97,7 +97,7 @@ describe('stories API', () => {
|
||||
const moduleArgs = createMockModuleArgs({});
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
const { index } = store.getState();
|
||||
// We need exact key ordering, even if in theory JS doesn't guarantee it
|
||||
expect(Object.keys(index!)).toEqual([
|
||||
@ -139,7 +139,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'design-system-some-component--my-story': {
|
||||
type: 'story',
|
||||
@ -176,7 +176,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'root-first--story-1': {
|
||||
type: 'story',
|
||||
@ -213,7 +213,7 @@ describe('stories API', () => {
|
||||
const { store, provider } = moduleArgs;
|
||||
provider.getConfig.mockReturnValue({ sidebar: { showRoots: true } });
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'a-b--1': {
|
||||
type: 'story',
|
||||
@ -252,7 +252,7 @@ describe('stories API', () => {
|
||||
const { store, provider } = moduleArgs;
|
||||
provider.getConfig.mockReturnValue({ sidebar: { showRoots: true } });
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'a--1': {
|
||||
type: 'story',
|
||||
@ -287,7 +287,7 @@ describe('stories API', () => {
|
||||
const { store, provider } = moduleArgs;
|
||||
provider.getConfig.mockReturnValue({ sidebar: { showRoots: true } });
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'a--1': { type: 'story', title: 'a', name: '1', id: 'a--1', importPath: './a.ts' },
|
||||
'b--1': { type: 'story', title: 'b', name: '1', id: 'b--1', importPath: './b.ts' },
|
||||
@ -314,7 +314,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'prepared--story': {
|
||||
type: 'story',
|
||||
@ -344,7 +344,7 @@ describe('stories API', () => {
|
||||
const moduleArgs = createMockModuleArgs({ fullAPI });
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store, provider } = moduleArgs;
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
provider.channel.emit(STORY_PREPARED, {
|
||||
id: 'component-a--story-1',
|
||||
parameters: { a: 'b' },
|
||||
@ -357,7 +357,7 @@ describe('stories API', () => {
|
||||
parameters: { a: 'b' },
|
||||
args: { c: 'd' },
|
||||
});
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
// Let the promise/await chain resolve
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
expect(store.getState().index!['component-a--story-1'] as API_StoryEntry).toMatchObject({
|
||||
@ -373,7 +373,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: docsEntries });
|
||||
api.setIndex({ v: 5, entries: docsEntries });
|
||||
const { index } = store.getState();
|
||||
// We need exact key ordering, even if in theory JS doesn't guarantee it
|
||||
expect(Object.keys(index!)).toEqual([
|
||||
@ -398,7 +398,7 @@ describe('stories API', () => {
|
||||
docsOptions: { docsMode: true },
|
||||
});
|
||||
const { store } = moduleArgs;
|
||||
api.setIndex({ v: 4, entries: docsEntries });
|
||||
api.setIndex({ v: 5, entries: docsEntries });
|
||||
const { index } = store.getState();
|
||||
expect(Object.keys(index!)).toEqual(['component-b', 'component-b--docs']);
|
||||
});
|
||||
@ -413,7 +413,7 @@ describe('stories API', () => {
|
||||
initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store, provider } = moduleArgs;
|
||||
|
||||
provider.channel.emit(SET_INDEX, { v: 4, entries: mockEntries });
|
||||
provider.channel.emit(SET_INDEX, { v: 5, entries: mockEntries });
|
||||
expect(store.getState().index).toEqual(
|
||||
expect.objectContaining({
|
||||
'component-a': expect.any(Object),
|
||||
@ -433,7 +433,7 @@ describe('stories API', () => {
|
||||
getCurrentParameter: vi.fn().mockReturnValue('options'),
|
||||
});
|
||||
|
||||
provider.channel.emit(SET_INDEX, { v: 4, entries: mockEntries });
|
||||
provider.channel.emit(SET_INDEX, { v: 5, entries: mockEntries });
|
||||
expect(fullAPI.setOptions).toHaveBeenCalledWith('options');
|
||||
});
|
||||
});
|
||||
@ -461,7 +461,7 @@ describe('stories API', () => {
|
||||
status: 200,
|
||||
ok: true,
|
||||
json: () => ({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-a--story-1': {
|
||||
type: 'story',
|
||||
@ -512,7 +512,7 @@ describe('stories API', () => {
|
||||
status: 200,
|
||||
ok: true,
|
||||
json: () => ({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-a--story-1': {
|
||||
type: 'story',
|
||||
@ -616,7 +616,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider, store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: preparedEntries });
|
||||
api.setIndex({ v: 5, entries: preparedEntries });
|
||||
const { index } = store.getState();
|
||||
expect((index!['a--1'] as API_StoryEntry).args).toEqual({ a: 'b' });
|
||||
expect((index!['b--1'] as API_StoryEntry).args).toEqual({ x: 'y' });
|
||||
@ -653,7 +653,7 @@ describe('stories API', () => {
|
||||
const listener = vi.fn();
|
||||
provider.channel.on(UPDATE_STORY_ARGS, listener);
|
||||
|
||||
api.setIndex({ v: 4, entries: preparedEntries });
|
||||
api.setIndex({ v: 5, entries: preparedEntries });
|
||||
api.updateStoryArgs({ id: 'a--1' } as API_StoryEntry, { foo: 'bar' });
|
||||
|
||||
expect(listener).toHaveBeenCalledWith({
|
||||
@ -677,7 +677,7 @@ describe('stories API', () => {
|
||||
const listener = vi.fn();
|
||||
provider.channel.on(UPDATE_STORY_ARGS, listener);
|
||||
|
||||
api.setIndex({ v: 4, entries: preparedEntries });
|
||||
api.setIndex({ v: 5, entries: preparedEntries });
|
||||
api.updateStoryArgs({ id: 'a--1', refId: 'refId' } as API_StoryEntry, { foo: 'bar' });
|
||||
expect(listener).toHaveBeenCalledWith({
|
||||
storyId: 'a--1',
|
||||
@ -695,7 +695,7 @@ describe('stories API', () => {
|
||||
const listener = vi.fn();
|
||||
provider.channel.on(RESET_STORY_ARGS, listener);
|
||||
|
||||
api.setIndex({ v: 4, entries: preparedEntries });
|
||||
api.setIndex({ v: 5, entries: preparedEntries });
|
||||
api.resetStoryArgs({ id: 'a--1' } as API_StoryEntry, ['foo']);
|
||||
|
||||
expect(listener).toHaveBeenCalledWith({
|
||||
@ -719,7 +719,7 @@ describe('stories API', () => {
|
||||
const listener = vi.fn();
|
||||
provider.channel.on(RESET_STORY_ARGS, listener);
|
||||
|
||||
api.setIndex({ v: 4, entries: preparedEntries });
|
||||
api.setIndex({ v: 5, entries: preparedEntries });
|
||||
api.resetStoryArgs({ id: 'a--1', refId: 'refId' } as API_StoryEntry, ['foo']);
|
||||
expect(listener).toHaveBeenCalledWith({
|
||||
storyId: 'a--1',
|
||||
@ -738,7 +738,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToStory(1);
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--2');
|
||||
@ -749,7 +749,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToStory(-1);
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--1');
|
||||
@ -764,7 +764,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToStory(1);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -774,7 +774,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToStory(-1);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -784,7 +784,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToStory(1);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -797,7 +797,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
const result = api.findSiblingStoryId('a--1', store.getState().index!, 1, false);
|
||||
expect(result).toBe('a--2');
|
||||
});
|
||||
@ -807,7 +807,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
const result = api.findSiblingStoryId('a--1', store.getState().index!, 1, true);
|
||||
expect(result).toBe('b-c--1');
|
||||
});
|
||||
@ -819,7 +819,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToComponent(1);
|
||||
expect(navigate).toHaveBeenCalledWith('/story/b-c--1');
|
||||
});
|
||||
@ -833,7 +833,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToComponent(-1);
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--1');
|
||||
});
|
||||
@ -847,7 +847,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToComponent(1);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -857,7 +857,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.jumpToComponent(-1);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -869,7 +869,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('a--2');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--2');
|
||||
});
|
||||
@ -880,7 +880,7 @@ describe('stories API', () => {
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...navigationEntries,
|
||||
'intro--docs': {
|
||||
@ -902,7 +902,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('a--1');
|
||||
expect(store.getState().settings.lastTrackedStoryId).toBe('a--1');
|
||||
});
|
||||
@ -913,7 +913,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('a', '2');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--2');
|
||||
});
|
||||
@ -923,7 +923,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory(undefined, '2');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--2');
|
||||
});
|
||||
@ -934,7 +934,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('a--2');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--2');
|
||||
});
|
||||
@ -944,7 +944,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('a');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--1');
|
||||
});
|
||||
@ -954,7 +954,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('b');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/b-c--1');
|
||||
});
|
||||
@ -964,7 +964,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('A');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--1');
|
||||
});
|
||||
@ -974,7 +974,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory();
|
||||
expect(navigate).toHaveBeenCalledWith('/story/a--1');
|
||||
});
|
||||
@ -985,7 +985,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('b/e', '1');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/custom-id--1');
|
||||
});
|
||||
@ -995,7 +995,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('custom-id', '1');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/custom-id--1');
|
||||
});
|
||||
@ -1005,7 +1005,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { navigate } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: navigationEntries });
|
||||
api.setIndex({ v: 5, entries: navigationEntries });
|
||||
api.selectStory('b/e');
|
||||
expect(navigate).toHaveBeenCalledWith('/story/custom-id--1');
|
||||
});
|
||||
@ -1019,7 +1019,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider, store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
provider.channel.emit(STORY_PREPARED, {
|
||||
id: 'component-a--story-1',
|
||||
@ -1045,7 +1045,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
provider.channel.emit(STORY_PREPARED, {
|
||||
id: 'component-a--story-1',
|
||||
@ -1068,7 +1068,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider, store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
provider.channel.emit(DOCS_PREPARED, {
|
||||
id: 'component-a--docs',
|
||||
@ -1092,7 +1092,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider, store } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
provider.channel.emit(CONFIG_ERROR, { message: 'Failed to run configure' });
|
||||
const { previewInitialized } = store.getState();
|
||||
@ -1104,7 +1104,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { provider } = moduleArgs;
|
||||
|
||||
api.setIndex({ v: 4, entries: mockEntries });
|
||||
api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
getEventMetadata.mockReturnValueOnce({
|
||||
sourceType: 'external',
|
||||
@ -1225,7 +1225,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
await expect(
|
||||
api.experimental_updateStatus('a-addon-id', {
|
||||
@ -1279,7 +1279,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
await expect(
|
||||
api.experimental_updateStatus('a-addon-id', {
|
||||
@ -1315,7 +1315,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
await expect(
|
||||
api.experimental_updateStatus('a-addon-id', {
|
||||
@ -1353,7 +1353,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
// setup initial state
|
||||
await expect(
|
||||
@ -1403,7 +1403,7 @@ describe('stories API', () => {
|
||||
const moduleArgs = createMockModuleArgs({});
|
||||
const { state, api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
expect(state).toEqual(
|
||||
expect.objectContaining({
|
||||
@ -1416,7 +1416,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: mockEntries });
|
||||
await api.setIndex({ v: 5, entries: mockEntries });
|
||||
|
||||
api.experimental_setFilter('myCustomFilter', () => true);
|
||||
|
||||
@ -1434,7 +1434,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: navigationEntries });
|
||||
await api.setIndex({ v: 5, entries: navigationEntries });
|
||||
await api.experimental_setFilter('myCustomFilter', (item: any) => item.id.startsWith('a'));
|
||||
|
||||
const { index } = store.getState();
|
||||
@ -1484,7 +1484,7 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: navigationEntries });
|
||||
await api.setIndex({ v: 5, entries: navigationEntries });
|
||||
await api.experimental_setFilter(
|
||||
'myCustomFilter',
|
||||
(item: any) =>
|
||||
@ -1538,10 +1538,10 @@ describe('stories API', () => {
|
||||
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
|
||||
const { store } = moduleArgs;
|
||||
|
||||
await api.setIndex({ v: 4, entries: navigationEntries });
|
||||
await api.setIndex({ v: 5, entries: navigationEntries });
|
||||
await api.experimental_setFilter('myCustomFilter', (item: any) => item.id.startsWith('a'));
|
||||
|
||||
await api.setIndex({ v: 4, entries: navigationEntries });
|
||||
await api.setIndex({ v: 5, entries: navigationEntries });
|
||||
|
||||
const { index } = store.getState();
|
||||
|
||||
|
@ -76,7 +76,7 @@ export const projectAnnotations = {
|
||||
export const getProjectAnnotations = vi.fn(() => projectAnnotations as any);
|
||||
|
||||
export const storyIndex: StoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--docs': {
|
||||
type: 'docs',
|
||||
|
@ -314,7 +314,7 @@ describe('PreviewWeb', () => {
|
||||
preview.onStoriesChanged({
|
||||
importFn: newImportFn,
|
||||
storyIndex: {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...storyIndex.entries,
|
||||
'component-one--missing': {
|
||||
@ -369,7 +369,7 @@ describe('PreviewWeb', () => {
|
||||
preview.onStoriesChanged({
|
||||
importFn: newImportFn,
|
||||
storyIndex: {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...storyIndex.entries,
|
||||
'component-one--missing': {
|
||||
@ -2977,7 +2977,7 @@ describe('PreviewWeb', () => {
|
||||
const newImportFn = vi.fn(async (path) => ({ ...componentOneExports }));
|
||||
|
||||
const newStoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...storyIndex.entries,
|
||||
'component-one--a': {
|
||||
@ -3174,7 +3174,7 @@ describe('PreviewWeb', () => {
|
||||
});
|
||||
|
||||
const newStoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--b': storyIndex.entries['component-one--b'],
|
||||
},
|
||||
|
@ -6,7 +6,7 @@ import { StoryIndexStore } from './StoryIndexStore';
|
||||
vi.mock('@storybook/channel-websocket', () => () => ({ on: vi.fn() }));
|
||||
|
||||
const storyIndex: StoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--a': {
|
||||
type: 'story',
|
||||
@ -34,7 +34,7 @@ const storyIndex: StoryIndex = {
|
||||
|
||||
const makeStoryIndex = (titlesAndNames: any) => {
|
||||
return {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: Object.fromEntries(
|
||||
titlesAndNames.map(([title, name]: [any, any]) => {
|
||||
const id = `${title}--${name}`.replace('/', '-');
|
||||
|
@ -24,7 +24,7 @@ const getImportPathMap = memoize(1)((entries: StoryIndex['entries']) =>
|
||||
export class StoryIndexStore {
|
||||
entries: StoryIndex['entries'];
|
||||
|
||||
constructor({ entries }: StoryIndex = { v: 4, entries: {} }) {
|
||||
constructor({ entries }: StoryIndex = { v: 5, entries: {} }) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ const projectAnnotations: ProjectAnnotations<any> = {
|
||||
};
|
||||
|
||||
const storyIndex: StoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--a': {
|
||||
type: 'story',
|
||||
@ -183,7 +183,7 @@ describe('StoryStore', () => {
|
||||
expect(prepareStory).toHaveBeenCalledTimes(1);
|
||||
|
||||
// The stories are no longer in the index
|
||||
await store.onStoriesChanged({ storyIndex: { v: 4, entries: {} } });
|
||||
await store.onStoriesChanged({ storyIndex: { v: 5, entries: {} } });
|
||||
|
||||
await expect(store.loadStory({ storyId: 'component-one--a' })).rejects.toThrow();
|
||||
|
||||
@ -202,7 +202,7 @@ describe('StoryStore', () => {
|
||||
// Add a new story to the index that isn't different
|
||||
await store.onStoriesChanged({
|
||||
storyIndex: {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...storyIndex.entries,
|
||||
'new-component--story': {
|
||||
@ -233,7 +233,7 @@ describe('StoryStore', () => {
|
||||
await store.onStoriesChanged({
|
||||
importFn: newImportFn,
|
||||
storyIndex: {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--a': {
|
||||
type: 'story',
|
||||
@ -262,7 +262,7 @@ describe('StoryStore', () => {
|
||||
await store.onStoriesChanged({
|
||||
importFn: newImportFn,
|
||||
storyIndex: {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--a': {
|
||||
type: 'story',
|
||||
@ -334,7 +334,7 @@ describe('StoryStore', () => {
|
||||
|
||||
it('returns them in the order they are in the index, not the file', async () => {
|
||||
const reversedIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
'component-one--b': storyIndex.entries['component-one--b'],
|
||||
'component-one--a': storyIndex.entries['component-one--a'],
|
||||
@ -587,7 +587,7 @@ describe('StoryStore', () => {
|
||||
|
||||
it('does not include (modern) docs entries ever', async () => {
|
||||
const unnattachedStoryIndex: StoryIndex = {
|
||||
v: 4,
|
||||
v: 5,
|
||||
entries: {
|
||||
...storyIndex.entries,
|
||||
'introduction--docs': {
|
||||
|
@ -31,7 +31,7 @@ export class ExternalPreview<TRenderer extends Renderer = Renderer> extends Prev
|
||||
|
||||
private titles = new ConstantMap<MetaExports, ComponentTitle>('title-');
|
||||
|
||||
private storyIndex: StoryIndex = { v: 4, entries: {} };
|
||||
private storyIndex: StoryIndex = { v: 5, entries: {} };
|
||||
|
||||
private moduleExportsByImportPath: Record<Path, ModuleExports> = {};
|
||||
|
||||
|
@ -94,6 +94,7 @@ If you're already using any of those flags in your project, you should be able t
|
||||
| `--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` |
|
||||
| `--testTimeout [amount]` | Defines the maximum time in milliseconds that a test can run before it is automatically marked as failed. Useful for long-running tests <br/> `test-storybook --testTimeout=60000` |
|
||||
| `--no-cache` | Disable the cache <br/>`test-storybook --no-cache` |
|
||||
| `--clearCache` | Deletes the Jest cache directory and then exits without running tests <br/>`test-storybook --clearCache` |
|
||||
| `--verbose` | Display individual test results with the test suite hierarchy <br/>`test-storybook --verbose` |
|
||||
@ -202,12 +203,12 @@ The test-runner renders a story and executes its [play function](../writing-stor
|
||||
The test-runner exports test hooks that can be overridden globally to enable use cases like visual or DOM snapshots. These hooks give you access to the test lifecycle _before_ and _after_ the story is rendered.
|
||||
Listed below are the available hooks and an overview of how to use them.
|
||||
|
||||
| Hook | Description |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `prepare` | Prepares the browser for tests<br/>`async prepare({ page, browserContext, testRunnerConfig }) {}` |
|
||||
| `setup` | Executes once before all the tests run<br/>`setup() {}` |
|
||||
| Hook | Description |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| `prepare` | Prepares the browser for tests<br/>`async prepare({ page, browserContext, testRunnerConfig }) {}` |
|
||||
| `setup` | Executes once before all the tests run<br/>`setup() {}` |
|
||||
| `preVisit` | Executes before a story is initially visited and rendered in the browser<br/>`async preVisit(page, context) {}` |
|
||||
| `postVisit` | Executes after the story is visited and fully rendered<br/>`async postVisit(page, context) {}` |
|
||||
| `postVisit` | Executes after the story is visited and fully rendered<br/>`async postVisit(page, context) {}` |
|
||||
|
||||
<Callout variant="info" icon="💡">
|
||||
|
||||
|
@ -282,6 +282,23 @@ function addStoriesEntry(mainConfig: ConfigFile, path: string, disableDocs: bool
|
||||
mainConfig.setFieldValue(['stories'], [...stories, entry]);
|
||||
}
|
||||
|
||||
// Add refs to older versions of storybook to test out composition
|
||||
function addRefs(mainConfig: ConfigFile) {
|
||||
const refs = mainConfig.getFieldValue(['refs']) as Record<string, string>;
|
||||
|
||||
mainConfig.setFieldValue(['refs'], {
|
||||
...refs,
|
||||
'storybook@8.0.0': {
|
||||
title: 'Storybook 8.0.0',
|
||||
url: 'https://635781f3500dd2c49e189caf-gckybvsekn.chromatic.com/',
|
||||
},
|
||||
'storybook@7.6.18': {
|
||||
title: 'Storybook 7.6.18',
|
||||
url: 'https://635781f3500dd2c49e189caf-oljwjdrftz.chromatic.com/',
|
||||
},
|
||||
} as Record<string, any>);
|
||||
}
|
||||
|
||||
function getStoriesFolderWithVariant(variant?: string, folder = 'stories') {
|
||||
return variant ? `${folder}_${variant}` : folder;
|
||||
}
|
||||
@ -516,9 +533,14 @@ export const addStories: Task['run'] = async (
|
||||
await writeConfig(mainConfig);
|
||||
};
|
||||
|
||||
export const extendMain: Task['run'] = async ({ template, sandboxDir }, { disableDocs }) => {
|
||||
export const extendMain: Task['run'] = async ({ template, sandboxDir, key }, { disableDocs }) => {
|
||||
logger.log('📝 Extending main.js');
|
||||
const mainConfig = await readMainConfig({ cwd: sandboxDir });
|
||||
|
||||
if (key === 'react-vite/default-ts') {
|
||||
addRefs(mainConfig);
|
||||
}
|
||||
|
||||
const templateConfig = template.modifications?.mainConfig || {};
|
||||
const configToAdd = {
|
||||
...templateConfig,
|
||||
|
Loading…
x
Reference in New Issue
Block a user