diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index d83e71323f92..217d74b01133 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,23 @@ +## 8.5.0-beta.2 + +- Addon Test: Clear coverage data when starting or watching - [#30072](https://github.com/storybookjs/storybook/pull/30072), thanks @ghengeveld! +- Addon Test: Improve error message on missing coverage package - [#30088](https://github.com/storybookjs/storybook/pull/30088), thanks @JReinhold! +- UI: Fix test provider event handling on startup - [#30083](https://github.com/storybookjs/storybook/pull/30083), thanks @ghengeveld! +- UI: Keep failing stories in the sidebar, disregarding filters - [#30086](https://github.com/storybookjs/storybook/pull/30086), thanks @JReinhold! + +## 8.5.0-beta.1 + +- Addon A11y: Add conditional rendering for a11y violation number in Testing Module - [#30073](https://github.com/storybookjs/storybook/pull/30073), thanks @valentinpalkovic! +- Addon A11y: Remove warnings API - [#30049](https://github.com/storybookjs/storybook/pull/30049), thanks @kasperpeulen! +- Addon A11y: Show errors of axe properly - [#30050](https://github.com/storybookjs/storybook/pull/30050), thanks @kasperpeulen! +- Addon Test: Fix printing null% for coverage - [#30061](https://github.com/storybookjs/storybook/pull/30061), thanks @ghengeveld! +- Telemetry: Add metadata distinguishing "apps" from "design systems" - [#30070](https://github.com/storybookjs/storybook/pull/30070), thanks @tmeasday! + +## 8.5.0-beta.0 + +- Automigration: Improve setup file transformation and version range handling for a11y migration - [#30060](https://github.com/storybookjs/storybook/pull/30060), thanks @valentinpalkovic! +- Next.js: Support v15.1.1 - [#30068](https://github.com/storybookjs/storybook/pull/30068), thanks @valentinpalkovic! + ## 8.5.0-alpha.22 - Addon Docs: Dynamically import rehype - [#29544](https://github.com/storybookjs/storybook/pull/29544), thanks @valentinpalkovic! diff --git a/code/.storybook/preview.tsx b/code/.storybook/preview.tsx index 017419318b0a..23f95a0c5d5e 100644 --- a/code/.storybook/preview.tsx +++ b/code/.storybook/preview.tsx @@ -358,9 +358,6 @@ export const parameters = { opacity: 0.4, }, }, - a11y: { - warnings: ['minor', 'moderate', 'serious', 'critical'], - }, }; -export const tags = ['test', 'vitest']; +export const tags = ['test', 'vitest', '!a11ytest']; diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 871521c0bbb5..ca38d1848b6c 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/a11y/src/components/A11YPanel.tsx b/code/addons/a11y/src/components/A11YPanel.tsx index dc048d97b941..61ea9a663af4 100644 --- a/code/addons/a11y/src/components/A11YPanel.tsx +++ b/code/addons/a11y/src/components/A11YPanel.tsx @@ -133,7 +133,11 @@ export const A11YPanel: React.FC = () => { <> The accessibility scan encountered an error.
- {typeof error === 'string' ? error : JSON.stringify(error)} + {typeof error === 'string' + ? error + : error instanceof Error + ? error.toString() + : JSON.stringify(error)} )} diff --git a/code/addons/a11y/src/params.ts b/code/addons/a11y/src/params.ts index dd4357687340..e66a0813a42c 100644 --- a/code/addons/a11y/src/params.ts +++ b/code/addons/a11y/src/params.ts @@ -6,8 +6,6 @@ export interface Setup { options: RunOptions; } -type Impact = NonNullable; - export interface A11yParameters { element?: ElementContext; config?: Spec; @@ -15,5 +13,4 @@ export interface A11yParameters { /** @deprecated Use globals.a11y.manual instead */ manual?: boolean; disable?: boolean; - warnings?: Impact[]; } diff --git a/code/addons/a11y/src/preview.test.tsx b/code/addons/a11y/src/preview.test.tsx index 334f7f924aeb..d09ba89462ed 100644 --- a/code/addons/a11y/src/preview.test.tsx +++ b/code/addons/a11y/src/preview.test.tsx @@ -156,60 +156,6 @@ describe('afterEach', () => { }); }); - it('should report warning status when there are only warnings', async () => { - const context = createContext({ - parameters: { - a11y: { - warnings: ['minor'], - }, - }, - }); - const result = { - violations: [ - { impact: 'minor', nodes: [] }, - { impact: 'critical', nodes: [] }, - ], - }; - mockedRun.mockResolvedValue(result as any); - - await expect(async () => experimental_afterEach(context)).rejects.toThrow(); - - expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y); - expect(context.reporting.addReport).toHaveBeenCalledWith({ - type: 'a11y', - version: 1, - result, - status: 'failed', - }); - }); - - it('should report error status when there are warnings and errors', async () => { - const context = createContext({ - parameters: { - a11y: { - warnings: ['minor'], - }, - }, - }); - const result = { - violations: [ - { impact: 'minor', nodes: [] }, - { impact: 'critical', nodes: [] }, - ], - }; - mockedRun.mockResolvedValue(result as any); - - await expect(async () => experimental_afterEach(context)).rejects.toThrow(); - - expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y); - expect(context.reporting.addReport).toHaveBeenCalledWith({ - type: 'a11y', - version: 1, - result, - status: 'failed', - }); - }); - it('should run accessibility checks if "a11ytest" flag is not available and is not running in Vitest', async () => { const context = createContext({ tags: [], diff --git a/code/addons/a11y/src/preview.tsx b/code/addons/a11y/src/preview.tsx index f7d2f9aa43ff..e496894cb113 100644 --- a/code/addons/a11y/src/preview.tsx +++ b/code/addons/a11y/src/preview.tsx @@ -21,7 +21,6 @@ export const experimental_afterEach: AfterEach = async ({ }) => { const a11yParameter: A11yParameters | undefined = parameters.a11y; const a11yGlobals = globals.a11y; - const warnings = a11yParameter?.warnings ?? []; const shouldRunEnvironmentIndependent = a11yParameter?.manual !== true && @@ -38,15 +37,11 @@ export const experimental_afterEach: AfterEach = async ({ if (result) { const hasViolations = (result?.violations.length ?? 0) > 0; - const hasErrors = result?.violations.some( - (violation) => !warnings.includes(violation.impact!) - ); - reporting.addReport({ type: 'a11y', version: 1, result: result, - status: hasErrors ? 'failed' : hasViolations ? 'warning' : 'passed', + status: hasViolations ? 'failed' : 'passed', }); /** @@ -58,7 +53,7 @@ export const experimental_afterEach: AfterEach = async ({ * implement proper try catch handling. */ if (getIsVitestStandaloneRun()) { - if (hasErrors) { + if (hasViolations) { // @ts-expect-error - todo - fix type extension of expect from @storybook/test expect(result).toHaveNoViolations(); } diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index cd465addf3f5..0fd1b8a2f8c5 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 64ddf7cbe09b..8b0a68e80997 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index d7837a6dbb59..6076ae2b0695 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 4e2a84bfd70a..c6edb3f14308 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 3fde9eab3744..7bb91e8bb960 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index c4042cd7690a..79438d40133c 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index f84dfd1ed338..4f9a269b034c 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index b584e70801c4..86cf84e46183 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 05197566dd86..d80862cf4d59 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index a5068e439214..cdb3a91bb48e 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "storybook-addons", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 036809014573..4e6cfa9efb7a 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index 496fdf643e76..4964c7a3a4ba 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index 404c69cb7c1d..6ea09d403517 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index 46db49209197..6f016e3e02a5 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/test/package.json b/code/addons/test/package.json index 9c96805ede79..94246c0704de 100644 --- a/code/addons/test/package.json +++ b/code/addons/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/experimental-addon-test", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Integrate Vitest with Storybook", "keywords": [ "storybook-addons", diff --git a/code/addons/test/src/components/TestProviderRender.stories.tsx b/code/addons/test/src/components/TestProviderRender.stories.tsx index dead913949cf..1189248f3d53 100644 --- a/code/addons/test/src/components/TestProviderRender.stories.tsx +++ b/code/addons/test/src/components/TestProviderRender.stories.tsx @@ -52,6 +52,10 @@ const baseState: TestProviderState = { coverage: false, }, details: { + config: { + a11y: false, + coverage: false, + }, testResults: [ { endTime: 0, @@ -141,6 +145,10 @@ export const WithCoverageNegative: Story = { ...config, ...baseState, details: { + config: { + a11y: false, + coverage: true, + }, testResults: [], coverageSummary: { percentage: 20, @@ -162,6 +170,10 @@ export const WithCoverageWarning: Story = { ...baseState, details: { testResults: [], + config: { + a11y: false, + coverage: true, + }, coverageSummary: { percentage: 50, status: 'warning', @@ -182,6 +194,10 @@ export const WithCoveragePositive: Story = { ...baseState, details: { testResults: [], + config: { + a11y: false, + coverage: true, + }, coverageSummary: { percentage: 80, status: 'positive', @@ -206,6 +222,10 @@ export const Editing: Story = { }, details: { testResults: [], + config: { + a11y: false, + coverage: false, + }, }, }, }, @@ -229,6 +249,10 @@ export const EditingAndWatching: Story = { }, details: { testResults: [], + config: { + a11y: true, + coverage: true, // should be automatically disabled in the UI + }, }, }, }, diff --git a/code/addons/test/src/components/TestProviderRender.tsx b/code/addons/test/src/components/TestProviderRender.tsx index 0c1185ab6f2a..29b0f950da8c 100644 --- a/code/addons/test/src/components/TestProviderRender.tsx +++ b/code/addons/test/src/components/TestProviderRender.tsx @@ -114,6 +114,8 @@ export const TestProviderRender: FC< state.config || { a11y: false, coverage: false } ); + const isStoryEntry = entryId?.includes('--') ?? false; + const a11yResults = useMemo(() => { if (!isA11yAddon) { return []; @@ -136,12 +138,14 @@ export const TestProviderRender: FC< return 'unknown'; } - if (!a11yResults) { + const definedA11yResults = a11yResults?.filter(Boolean) ?? []; + + if (!definedA11yResults || definedA11yResults.length === 0) { return 'unknown'; } - const failed = a11yResults.some((result) => result?.status === 'failed'); - const warning = a11yResults.some((result) => result?.status === 'warning'); + const failed = definedA11yResults.some((result) => result?.status === 'failed'); + const warning = definedA11yResults.some((result) => result?.status === 'warning'); if (failed) { return 'negative'; @@ -152,11 +156,24 @@ export const TestProviderRender: FC< return 'positive'; }, [state.running, isA11yAddon, config.a11y, a11yResults]); - const a11yNotPassedAmount = a11yResults?.filter( - (result) => result?.status === 'failed' || result?.status === 'warning' - ).length; + const a11yNotPassedAmount = state.config?.a11y + ? a11yResults?.filter((result) => result?.status === 'failed' || result?.status === 'warning') + .length + : undefined; + + const a11ySkippedAmount = + state.running || !state?.details.config?.a11y || !state.config.a11y + ? null + : a11yResults?.filter((result) => !result).length; + + const a11ySkippedLabel = a11ySkippedAmount + ? a11ySkippedAmount === 1 && isStoryEntry + ? '(skipped)' + : `(${a11ySkippedAmount} skipped)` + : ''; + + const storyId = isStoryEntry ? entryId : undefined; - const storyId = entryId?.includes('--') ? entryId : undefined; const results = (state.details?.testResults || []) .flatMap((test) => { if (!entryId) { @@ -307,6 +324,7 @@ export const TestProviderRender: FC< href={'/coverage/index.html'} // @ts-expect-error ListItem doesn't include all anchor attributes in types, but it is an achor element target="_blank" + aria-label="Open coverage report" icon={ } - right={`${coverageSummary.percentage}%`} + right={ + coverageSummary.percentage ? ( + + {coverageSummary.percentage} % + + ) : null + } /> ) : ( Accessibility} + title={Accessibility {a11ySkippedLabel}} onClick={ (a11yStatus === 'negative' || a11yStatus === 'warning') && a11yResults.length ? () => { @@ -340,7 +364,7 @@ export const TestProviderRender: FC< : null } icon={} - right={a11yNotPassedAmount || null} + right={isStoryEntry ? null : a11yNotPassedAmount || null} /> )} diff --git a/code/addons/test/src/constants.ts b/code/addons/test/src/constants.ts index 0453930e3758..d57ff1b1da8a 100644 --- a/code/addons/test/src/constants.ts +++ b/code/addons/test/src/constants.ts @@ -19,6 +19,7 @@ export interface Config { export type Details = { testResults: TestResult[]; + config: Config; coverageSummary?: { status: 'positive' | 'warning' | 'negative' | 'unknown'; percentage: number; diff --git a/code/addons/test/src/manager.tsx b/code/addons/test/src/manager.tsx index 4db0c5defcbd..26a8c8f42cd7 100644 --- a/code/addons/test/src/manager.tsx +++ b/code/addons/test/src/manager.tsx @@ -73,64 +73,75 @@ addons.register(ADDON_ID, (api) => { }, stateUpdater: (state, update) => { - if (!update.details?.testResults) { - return; + const updated = { + ...state, + ...update, + details: { ...state.details, ...update.details }, + }; + + if ((!state.running && update.running) || (!state.watching && update.watching)) { + // Clear coverage data when starting test run or enabling watch mode + delete updated.details.coverageSummary; } - (async () => { - await api.experimental_updateStatus( - TEST_PROVIDER_ID, - Object.fromEntries( - update.details.testResults.flatMap((testResult) => - testResult.results - .filter(({ storyId }) => storyId) - .map(({ storyId, status, testRunId, ...rest }) => [ - storyId, - { - title: 'Component tests', - status: statusMap[status], - description: - 'failureMessages' in rest && rest.failureMessages - ? rest.failureMessages.join('\n') - : '', - data: { testRunId }, - onClick: openTestsPanel, - sidebarContextMenu: false, - } satisfies API_StatusObject, - ]) + if (update.details?.testResults) { + (async () => { + await api.experimental_updateStatus( + TEST_PROVIDER_ID, + Object.fromEntries( + update.details.testResults.flatMap((testResult) => + testResult.results + .filter(({ storyId }) => storyId) + .map(({ storyId, status, testRunId, ...rest }) => [ + storyId, + { + title: 'Component tests', + status: statusMap[status], + description: + 'failureMessages' in rest && rest.failureMessages + ? rest.failureMessages.join('\n') + : '', + data: { testRunId }, + onClick: openTestsPanel, + sidebarContextMenu: false, + } satisfies API_StatusObject, + ]) + ) ) - ) - ); + ); - await api.experimental_updateStatus( - 'storybook/addon-a11y/test-provider', - Object.fromEntries( - update.details.testResults.flatMap((testResult) => - testResult.results - .filter(({ storyId }) => storyId) - .map(({ storyId, testRunId, reports }) => { - const a11yReport = reports.find((r: any) => r.type === 'a11y'); - return [ - storyId, - a11yReport - ? ({ - title: 'Accessibility tests', - description: '', - status: statusMap[a11yReport.status], - data: { testRunId }, - onClick: () => { - api.setSelectedPanel('storybook/a11y/panel'); - api.togglePanel(true); - }, - sidebarContextMenu: false, - } satisfies API_StatusObject) - : null, - ]; - }) + await api.experimental_updateStatus( + 'storybook/addon-a11y/test-provider', + Object.fromEntries( + update.details.testResults.flatMap((testResult) => + testResult.results + .filter(({ storyId }) => storyId) + .map(({ storyId, testRunId, reports }) => { + const a11yReport = reports.find((r: any) => r.type === 'a11y'); + return [ + storyId, + a11yReport + ? ({ + title: 'Accessibility tests', + description: '', + status: statusMap[a11yReport.status], + data: { testRunId }, + onClick: () => { + api.setSelectedPanel('storybook/a11y/panel'); + api.togglePanel(true); + }, + sidebarContextMenu: false, + } satisfies API_StatusObject) + : null, + ]; + }) + ) ) - ) - ); - })(); + ); + })(); + } + + return updated; }, } as Addon_TestProviderType); } diff --git a/code/addons/test/src/node/coverage-reporter.ts b/code/addons/test/src/node/coverage-reporter.ts index 452643cd9d60..cc1dd548000f 100644 --- a/code/addons/test/src/node/coverage-reporter.ts +++ b/code/addons/test/src/node/coverage-reporter.ts @@ -8,7 +8,7 @@ import type { TestManager } from './test-manager'; export type StorybookCoverageReporterOptions = { testManager: TestManager; - coverageOptions: ResolvedCoverageOptions<'v8'>; + coverageOptions: ResolvedCoverageOptions<'v8'> | undefined; }; export default class StorybookCoverageReporter extends ReportBase implements Partial { @@ -32,7 +32,7 @@ export default class StorybookCoverageReporter extends ReportBase implements Par // Fallback to Vitest's default watermarks https://vitest.dev/config/#coverage-watermarks const [lowWatermark = 50, highWatermark = 80] = - this.#coverageOptions.watermarks?.statements ?? []; + this.#coverageOptions?.watermarks?.statements ?? []; const coverageDetails: Details['coverageSummary'] = { percentage, diff --git a/code/addons/test/src/node/reporter.ts b/code/addons/test/src/node/reporter.ts index 43191cbc2fdc..ecda9ab4a672 100644 --- a/code/addons/test/src/node/reporter.ts +++ b/code/addons/test/src/node/reporter.ts @@ -173,6 +173,7 @@ export class StorybookReporter implements Reporter { } as TestingModuleProgressReportProgress, details: { testResults, + config: this.testManager.config, }, }; } diff --git a/code/addons/test/src/node/test-manager.test.ts b/code/addons/test/src/node/test-manager.test.ts index db77ab2f3e2e..7056aee5666b 100644 --- a/code/addons/test/src/node/test-manager.test.ts +++ b/code/addons/test/src/node/test-manager.test.ts @@ -105,11 +105,11 @@ describe('TestManager', () => { it('should handle watch mode request', async () => { const testManager = await TestManager.start(mockChannel, options); - expect(testManager.watchMode).toBe(false); + expect(testManager.config.watchMode).toBe(false); expect(createVitest).toHaveBeenCalledTimes(1); await testManager.handleWatchModeRequest({ providerId: TEST_PROVIDER_ID, watchMode: true }); - expect(testManager.watchMode).toBe(true); + expect(testManager.config.watchMode).toBe(true); expect(createVitest).toHaveBeenCalledTimes(1); // shouldn't restart vitest }); @@ -149,7 +149,7 @@ describe('TestManager', () => { it('should handle coverage toggling', async () => { const testManager = await TestManager.start(mockChannel, options); - expect(testManager.coverage).toBe(false); + expect(testManager.config.coverage).toBe(false); expect(createVitest).toHaveBeenCalledTimes(1); createVitest.mockClear(); @@ -157,7 +157,7 @@ describe('TestManager', () => { providerId: TEST_PROVIDER_ID, config: { coverage: true, a11y: false }, }); - expect(testManager.coverage).toBe(true); + expect(testManager.config.coverage).toBe(true); expect(createVitest).toHaveBeenCalledTimes(1); createVitest.mockClear(); @@ -165,21 +165,21 @@ describe('TestManager', () => { providerId: TEST_PROVIDER_ID, config: { coverage: false, a11y: false }, }); - expect(testManager.coverage).toBe(false); + expect(testManager.config.coverage).toBe(false); expect(createVitest).toHaveBeenCalledTimes(1); }); it('should temporarily disable coverage on focused tests', async () => { vitest.globTestSpecs.mockImplementation(() => tests); const testManager = await TestManager.start(mockChannel, options); - expect(testManager.coverage).toBe(false); + expect(testManager.config.coverage).toBe(false); expect(createVitest).toHaveBeenCalledTimes(1); await testManager.handleConfigChange({ providerId: TEST_PROVIDER_ID, config: { coverage: true, a11y: false }, }); - expect(testManager.coverage).toBe(true); + expect(testManager.config.coverage).toBe(true); expect(createVitest).toHaveBeenCalledTimes(2); await testManager.handleRunRequest({ diff --git a/code/addons/test/src/node/test-manager.ts b/code/addons/test/src/node/test-manager.ts index 4770f2b5a174..1a19e587eeea 100644 --- a/code/addons/test/src/node/test-manager.ts +++ b/code/addons/test/src/node/test-manager.ts @@ -18,9 +18,11 @@ import { VitestManager } from './vitest-manager'; export class TestManager { vitestManager: VitestManager; - watchMode = false; - - coverage = false; + config = { + watchMode: false, + coverage: false, + a11y: false, + }; constructor( private channel: Channel, @@ -44,23 +46,22 @@ export class TestManager { return; } + const previousConfig = this.config; + + this.config = { + ...this.config, + ...payload.config, + } satisfies Config; + process.env.VITEST_STORYBOOK_CONFIG = JSON.stringify(payload.config); - if (this.coverage !== payload.config.coverage) { - this.coverage = payload.config.coverage; + if (previousConfig.coverage !== payload.config.coverage) { try { await this.vitestManager.restartVitest({ - coverage: this.coverage, + coverage: this.config.coverage, }); } catch (e) { - const isV8 = e.message?.includes('@vitest/coverage-v8'); - const isIstanbul = e.message?.includes('@vitest/coverage-istanbul'); - - if (e.message?.includes('Error: Failed to load url') && (isIstanbul || isV8)) { - const coveragePackage = isIstanbul ? 'coverage-istanbul' : 'coverage-v8'; - e.message = `Please install the @vitest/${coveragePackage} package to run with coverage`; - } - this.reportFatalError('Failed to change coverage mode', e); + this.reportFatalError('Failed to change coverage configuration', e); } } } @@ -69,7 +70,7 @@ export class TestManager { if (payload.providerId !== TEST_PROVIDER_ID) { return; } - this.watchMode = payload.watchMode; + this.config.watchMode = payload.watchMode; if (payload.config) { this.handleConfigChange({ @@ -78,14 +79,14 @@ export class TestManager { }); } - if (this.coverage) { + if (this.config.coverage) { try { if (payload.watchMode) { // if watch mode is toggled on and coverage is already enabled, restart vitest without coverage to automatically disable it await this.vitestManager.restartVitest({ coverage: false }); } else { // if watch mode is toggled off and coverage is already enabled, restart vitest with coverage to automatically re-enable it - await this.vitestManager.restartVitest({ coverage: this.coverage }); + await this.vitestManager.restartVitest({ coverage: this.config.coverage }); } } catch (e) { this.reportFatalError('Failed to change watch mode while coverage was enabled', e); @@ -111,7 +112,7 @@ export class TestManager { as a coverage report for a subset of stories is not useful. */ const temporarilyDisableCoverage = - this.coverage && !this.watchMode && (payload.storyIds ?? []).length > 0; + this.config.coverage && !this.config.watchMode && (payload.storyIds ?? []).length > 0; if (temporarilyDisableCoverage) { await this.vitestManager.restartVitest({ coverage: false, @@ -124,7 +125,7 @@ export class TestManager { if (temporarilyDisableCoverage) { // Re-enable coverage if it was temporarily disabled because of a subset of stories was run - await this.vitestManager.restartVitest({ coverage: this.coverage }); + await this.vitestManager.restartVitest({ coverage: this.config.coverage }); } } catch (e) { this.reportFatalError('Failed to run tests', e); diff --git a/code/addons/test/src/node/vitest-manager.ts b/code/addons/test/src/node/vitest-manager.ts index d55d3bc6d5b1..0a5ff8ab0b4e 100644 --- a/code/addons/test/src/node/vitest-manager.ts +++ b/code/addons/test/src/node/vitest-manager.ts @@ -52,7 +52,7 @@ export class VitestManager { join(packageDir, 'dist/node/coverage-reporter.js'), { testManager: this.testManager, - coverageOptions: this.vitest?.config?.coverage as ResolvedCoverageOptions<'v8'>, + coverageOptions: this.vitest?.config?.coverage as ResolvedCoverageOptions<'v8'> | undefined, }, ]; const coverageOptions = ( @@ -89,15 +89,21 @@ export class VitestManager { try { await this.vitest.init(); } catch (e) { + let message = 'Failed to initialize Vitest'; const isV8 = e.message?.includes('@vitest/coverage-v8'); const isIstanbul = e.message?.includes('@vitest/coverage-istanbul'); - if (e.message?.includes('Error: Failed to load url') && (isIstanbul || isV8)) { + if ( + (e.message?.includes('Failed to load url') && (isIstanbul || isV8)) || + // Vitest will sometimes not throw the correct missing-package-detection error, so we have to check for this as well + (e instanceof TypeError && + e?.message === "Cannot read properties of undefined (reading 'name')") + ) { const coveragePackage = isIstanbul ? 'coverage-istanbul' : 'coverage-v8'; - e.message = `Please install the @vitest/${coveragePackage} package to run with coverage`; + message += `\n\nPlease install the @vitest/${coveragePackage} package to collect coverage\n`; } - - this.testManager.reportFatalError('Failed to init Vitest', e); + this.testManager.reportFatalError(message, e); + return; } await this.setupWatchers(); @@ -193,7 +199,7 @@ export class VitestManager { this.filterStories(story, spec.moduleId, { include, exclude, skip }) ); if (matches.length) { - if (!this.testManager.watchMode) { + if (!this.testManager.config.watchMode) { // Clear the file cache if watch mode is not enabled this.updateLastChanged(spec.moduleId); } @@ -314,7 +320,7 @@ export class VitestManager { // when watch mode is disabled, don't trigger any tests (below) // but still invalidate the cache for the changed file, which is handled above - if (!this.testManager.watchMode) { + if (!this.testManager.config.watchMode) { return; } await this.runAffectedTests(file); diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index 9e788efc90cf..203ff96d62f6 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 21716863b7b6..bddd8a73c217 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index dfe78a2799b1..7aeb1ea7d640 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 1a19730107ca..e5d76e019f82 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index 8dca343bbc1f..3db13f0231cb 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/core/package.json b/code/core/package.json index c0a6b170ff23..1744d188499f 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/core/src/__mocks__/page.ts b/code/core/src/__mocks__/page.ts new file mode 100644 index 000000000000..fb87bbd306b8 --- /dev/null +++ b/code/core/src/__mocks__/page.ts @@ -0,0 +1 @@ +// empty file only matched on path diff --git a/code/core/src/__mocks__/path/to/Screens/index.jsx b/code/core/src/__mocks__/path/to/Screens/index.jsx new file mode 100644 index 000000000000..fb87bbd306b8 --- /dev/null +++ b/code/core/src/__mocks__/path/to/Screens/index.jsx @@ -0,0 +1 @@ +// empty file only matched on path diff --git a/code/core/src/common/versions.ts b/code/core/src/common/versions.ts index cd5bdcc85a13..cdb250c9cd8d 100644 --- a/code/core/src/common/versions.ts +++ b/code/core/src/common/versions.ts @@ -1,88 +1,88 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.5.0-alpha.22', - '@storybook/addon-actions': '8.5.0-alpha.22', - '@storybook/addon-backgrounds': '8.5.0-alpha.22', - '@storybook/addon-controls': '8.5.0-alpha.22', - '@storybook/addon-docs': '8.5.0-alpha.22', - '@storybook/addon-essentials': '8.5.0-alpha.22', - '@storybook/addon-mdx-gfm': '8.5.0-alpha.22', - '@storybook/addon-highlight': '8.5.0-alpha.22', - '@storybook/addon-interactions': '8.5.0-alpha.22', - '@storybook/addon-jest': '8.5.0-alpha.22', - '@storybook/addon-links': '8.5.0-alpha.22', - '@storybook/addon-measure': '8.5.0-alpha.22', - '@storybook/addon-onboarding': '8.5.0-alpha.22', - '@storybook/addon-outline': '8.5.0-alpha.22', - '@storybook/addon-storysource': '8.5.0-alpha.22', - '@storybook/experimental-addon-test': '8.5.0-alpha.22', - '@storybook/addon-themes': '8.5.0-alpha.22', - '@storybook/addon-toolbars': '8.5.0-alpha.22', - '@storybook/addon-viewport': '8.5.0-alpha.22', - '@storybook/builder-vite': '8.5.0-alpha.22', - '@storybook/builder-webpack5': '8.5.0-alpha.22', - '@storybook/core': '8.5.0-alpha.22', - '@storybook/builder-manager': '8.5.0-alpha.22', - '@storybook/channels': '8.5.0-alpha.22', - '@storybook/client-logger': '8.5.0-alpha.22', - '@storybook/components': '8.5.0-alpha.22', - '@storybook/core-common': '8.5.0-alpha.22', - '@storybook/core-events': '8.5.0-alpha.22', - '@storybook/core-server': '8.5.0-alpha.22', - '@storybook/csf-tools': '8.5.0-alpha.22', - '@storybook/docs-tools': '8.5.0-alpha.22', - '@storybook/manager': '8.5.0-alpha.22', - '@storybook/manager-api': '8.5.0-alpha.22', - '@storybook/node-logger': '8.5.0-alpha.22', - '@storybook/preview': '8.5.0-alpha.22', - '@storybook/preview-api': '8.5.0-alpha.22', - '@storybook/router': '8.5.0-alpha.22', - '@storybook/telemetry': '8.5.0-alpha.22', - '@storybook/theming': '8.5.0-alpha.22', - '@storybook/types': '8.5.0-alpha.22', - '@storybook/angular': '8.5.0-alpha.22', - '@storybook/ember': '8.5.0-alpha.22', - '@storybook/experimental-nextjs-vite': '8.5.0-alpha.22', - '@storybook/html-vite': '8.5.0-alpha.22', - '@storybook/html-webpack5': '8.5.0-alpha.22', - '@storybook/nextjs': '8.5.0-alpha.22', - '@storybook/preact-vite': '8.5.0-alpha.22', - '@storybook/preact-webpack5': '8.5.0-alpha.22', - '@storybook/react-native-web-vite': '8.5.0-alpha.22', - '@storybook/react-vite': '8.5.0-alpha.22', - '@storybook/react-webpack5': '8.5.0-alpha.22', - '@storybook/server-webpack5': '8.5.0-alpha.22', - '@storybook/svelte-vite': '8.5.0-alpha.22', - '@storybook/svelte-webpack5': '8.5.0-alpha.22', - '@storybook/sveltekit': '8.5.0-alpha.22', - '@storybook/vue3-vite': '8.5.0-alpha.22', - '@storybook/vue3-webpack5': '8.5.0-alpha.22', - '@storybook/web-components-vite': '8.5.0-alpha.22', - '@storybook/web-components-webpack5': '8.5.0-alpha.22', - '@storybook/blocks': '8.5.0-alpha.22', - storybook: '8.5.0-alpha.22', - sb: '8.5.0-alpha.22', - '@storybook/cli': '8.5.0-alpha.22', - '@storybook/codemod': '8.5.0-alpha.22', - '@storybook/core-webpack': '8.5.0-alpha.22', - 'create-storybook': '8.5.0-alpha.22', - '@storybook/csf-plugin': '8.5.0-alpha.22', - '@storybook/instrumenter': '8.5.0-alpha.22', - '@storybook/react-dom-shim': '8.5.0-alpha.22', - '@storybook/source-loader': '8.5.0-alpha.22', - '@storybook/test': '8.5.0-alpha.22', - '@storybook/preset-create-react-app': '8.5.0-alpha.22', - '@storybook/preset-html-webpack': '8.5.0-alpha.22', - '@storybook/preset-preact-webpack': '8.5.0-alpha.22', - '@storybook/preset-react-webpack': '8.5.0-alpha.22', - '@storybook/preset-server-webpack': '8.5.0-alpha.22', - '@storybook/preset-svelte-webpack': '8.5.0-alpha.22', - '@storybook/preset-vue3-webpack': '8.5.0-alpha.22', - '@storybook/html': '8.5.0-alpha.22', - '@storybook/preact': '8.5.0-alpha.22', - '@storybook/react': '8.5.0-alpha.22', - '@storybook/server': '8.5.0-alpha.22', - '@storybook/svelte': '8.5.0-alpha.22', - '@storybook/vue3': '8.5.0-alpha.22', - '@storybook/web-components': '8.5.0-alpha.22', + '@storybook/addon-a11y': '8.5.0-beta.2', + '@storybook/addon-actions': '8.5.0-beta.2', + '@storybook/addon-backgrounds': '8.5.0-beta.2', + '@storybook/addon-controls': '8.5.0-beta.2', + '@storybook/addon-docs': '8.5.0-beta.2', + '@storybook/addon-essentials': '8.5.0-beta.2', + '@storybook/addon-mdx-gfm': '8.5.0-beta.2', + '@storybook/addon-highlight': '8.5.0-beta.2', + '@storybook/addon-interactions': '8.5.0-beta.2', + '@storybook/addon-jest': '8.5.0-beta.2', + '@storybook/addon-links': '8.5.0-beta.2', + '@storybook/addon-measure': '8.5.0-beta.2', + '@storybook/addon-onboarding': '8.5.0-beta.2', + '@storybook/addon-outline': '8.5.0-beta.2', + '@storybook/addon-storysource': '8.5.0-beta.2', + '@storybook/experimental-addon-test': '8.5.0-beta.2', + '@storybook/addon-themes': '8.5.0-beta.2', + '@storybook/addon-toolbars': '8.5.0-beta.2', + '@storybook/addon-viewport': '8.5.0-beta.2', + '@storybook/builder-vite': '8.5.0-beta.2', + '@storybook/builder-webpack5': '8.5.0-beta.2', + '@storybook/core': '8.5.0-beta.2', + '@storybook/builder-manager': '8.5.0-beta.2', + '@storybook/channels': '8.5.0-beta.2', + '@storybook/client-logger': '8.5.0-beta.2', + '@storybook/components': '8.5.0-beta.2', + '@storybook/core-common': '8.5.0-beta.2', + '@storybook/core-events': '8.5.0-beta.2', + '@storybook/core-server': '8.5.0-beta.2', + '@storybook/csf-tools': '8.5.0-beta.2', + '@storybook/docs-tools': '8.5.0-beta.2', + '@storybook/manager': '8.5.0-beta.2', + '@storybook/manager-api': '8.5.0-beta.2', + '@storybook/node-logger': '8.5.0-beta.2', + '@storybook/preview': '8.5.0-beta.2', + '@storybook/preview-api': '8.5.0-beta.2', + '@storybook/router': '8.5.0-beta.2', + '@storybook/telemetry': '8.5.0-beta.2', + '@storybook/theming': '8.5.0-beta.2', + '@storybook/types': '8.5.0-beta.2', + '@storybook/angular': '8.5.0-beta.2', + '@storybook/ember': '8.5.0-beta.2', + '@storybook/experimental-nextjs-vite': '8.5.0-beta.2', + '@storybook/html-vite': '8.5.0-beta.2', + '@storybook/html-webpack5': '8.5.0-beta.2', + '@storybook/nextjs': '8.5.0-beta.2', + '@storybook/preact-vite': '8.5.0-beta.2', + '@storybook/preact-webpack5': '8.5.0-beta.2', + '@storybook/react-native-web-vite': '8.5.0-beta.2', + '@storybook/react-vite': '8.5.0-beta.2', + '@storybook/react-webpack5': '8.5.0-beta.2', + '@storybook/server-webpack5': '8.5.0-beta.2', + '@storybook/svelte-vite': '8.5.0-beta.2', + '@storybook/svelte-webpack5': '8.5.0-beta.2', + '@storybook/sveltekit': '8.5.0-beta.2', + '@storybook/vue3-vite': '8.5.0-beta.2', + '@storybook/vue3-webpack5': '8.5.0-beta.2', + '@storybook/web-components-vite': '8.5.0-beta.2', + '@storybook/web-components-webpack5': '8.5.0-beta.2', + '@storybook/blocks': '8.5.0-beta.2', + storybook: '8.5.0-beta.2', + sb: '8.5.0-beta.2', + '@storybook/cli': '8.5.0-beta.2', + '@storybook/codemod': '8.5.0-beta.2', + '@storybook/core-webpack': '8.5.0-beta.2', + 'create-storybook': '8.5.0-beta.2', + '@storybook/csf-plugin': '8.5.0-beta.2', + '@storybook/instrumenter': '8.5.0-beta.2', + '@storybook/react-dom-shim': '8.5.0-beta.2', + '@storybook/source-loader': '8.5.0-beta.2', + '@storybook/test': '8.5.0-beta.2', + '@storybook/preset-create-react-app': '8.5.0-beta.2', + '@storybook/preset-html-webpack': '8.5.0-beta.2', + '@storybook/preset-preact-webpack': '8.5.0-beta.2', + '@storybook/preset-react-webpack': '8.5.0-beta.2', + '@storybook/preset-server-webpack': '8.5.0-beta.2', + '@storybook/preset-svelte-webpack': '8.5.0-beta.2', + '@storybook/preset-vue3-webpack': '8.5.0-beta.2', + '@storybook/html': '8.5.0-beta.2', + '@storybook/preact': '8.5.0-beta.2', + '@storybook/react': '8.5.0-beta.2', + '@storybook/server': '8.5.0-beta.2', + '@storybook/svelte': '8.5.0-beta.2', + '@storybook/vue3': '8.5.0-beta.2', + '@storybook/web-components': '8.5.0-beta.2', }; diff --git a/code/core/src/manager-api/lib/stories.test.ts b/code/core/src/manager-api/lib/stories.test.ts index 76aaadd7f99d..3f0cbe63b5be 100644 --- a/code/core/src/manager-api/lib/stories.test.ts +++ b/code/core/src/manager-api/lib/stories.test.ts @@ -2,8 +2,10 @@ import { describe, expect, it } from 'vitest'; import type { API_PreparedStoryIndex, StoryIndexV2, StoryIndexV3 } from '@storybook/core/types'; +import type { State } from '../root'; import { mockEntries } from '../tests/mockStoriesEntries'; import { + transformStoryIndexToStoriesHash, transformStoryIndexV2toV3, transformStoryIndexV3toV4, transformStoryIndexV4toV5, @@ -216,3 +218,60 @@ describe('transformStoryIndexV4toV5', () => { `); }); }); + +describe('transformStoryIndexToStoriesHash', () => { + it('does not apply filters to failing stories', () => { + // Arrange - set up an index with two stories, one of which has a failing status + const indexV5: API_PreparedStoryIndex = { + v: 5, + entries: { + '1': { + id: '1', + type: 'story', + title: 'Story 1', + name: 'Story 1', + importPath: './path/to/story-1.ts', + parameters: {}, + tags: [], + }, + '2': { + id: '2', + type: 'story', + title: 'Story 2', + name: 'Story 2', + importPath: './path/to/story-2.ts', + parameters: {}, + tags: [], + }, + }, + }; + + const filters: State['filters'] = { + someFilter: () => false, + }; + + const status: State['status'] = { + '1': { someStatus: { status: 'error', title: 'broken', description: 'very bad' } }, + '2': { someStatus: { status: 'success', title: 'perfect', description: 'nice' } }, + }; + + const options = { + provider: { + getConfig: () => ({ sidebar: {} }), + } as any, + docsOptions: { docsMode: false }, + filters, + status, + }; + + // Act - transform the index to hashes + const result = transformStoryIndexToStoriesHash(indexV5, options); + + // Assert - the failing story is still present in the result, even though the filters remove all stories + expect(Object.keys(result)).toHaveLength(2); + expect(result['story-1']).toBeTruthy(); + expect(result['1']).toBeTruthy(); + expect(result['story-2']).toBeUndefined(); + expect(result['2']).toBeUndefined(); + }); +}); diff --git a/code/core/src/manager-api/lib/stories.ts b/code/core/src/manager-api/lib/stories.ts index 28fbc190853b..b38d30000531 100644 --- a/code/core/src/manager-api/lib/stories.ts +++ b/code/core/src/manager-api/lib/stories.ts @@ -192,11 +192,17 @@ export const transformStoryIndexToStoriesHash = ( const entryValues = Object.values(index.entries).filter((entry: any) => { let result = true; + // All stories with a failing status should always show up, regardless of the applied filters + const storyStatus = status[entry.id]; + if (Object.values(storyStatus ?? {}).some(({ status: s }) => s === 'error')) { + return result; + } + Object.values(filters).forEach((filter: any) => { if (result === false) { return; } - result = filter({ ...entry, status: status[entry.id] }); + result = filter({ ...entry, status: storyStatus }); }); return result; diff --git a/code/core/src/manager-api/modules/layout.ts b/code/core/src/manager-api/modules/layout.ts index 468d51af1b8a..6687c36b1137 100644 --- a/code/core/src/manager-api/modules/layout.ts +++ b/code/core/src/manager-api/modules/layout.ts @@ -100,7 +100,7 @@ export const defaultLayoutState: SubState = { panelPosition: 'bottom', showTabs: true, }, - selectedPanel: undefined, + selectedPanel: 'chromaui/addon-visual-tests/panel', theme: create(), }; diff --git a/code/core/src/manager-api/version.ts b/code/core/src/manager-api/version.ts index 90c0bfd8e29f..c9d852d16745 100644 --- a/code/core/src/manager-api/version.ts +++ b/code/core/src/manager-api/version.ts @@ -1 +1 @@ -export const version = '8.5.0-alpha.22'; +export const version = '8.5.0-beta.2'; diff --git a/code/core/src/manager/components/panel/Panel.tsx b/code/core/src/manager/components/panel/Panel.tsx index 701cd94925e3..dc80c20949d2 100644 --- a/code/core/src/manager/components/panel/Panel.tsx +++ b/code/core/src/manager/components/panel/Panel.tsx @@ -60,7 +60,7 @@ export const AddonPanel = React.memo<{ return ( { + // Register listeners before the first render + useLayoutEffect(() => { const onCrashReport = ({ providerId, ...details }: TestingModuleCrashReportPayload) => { api.updateTestProviderState(providerId, { error: { name: 'Crashed!', message: details.error.message }, diff --git a/code/core/src/telemetry/exec-command-count-lines.test.ts b/code/core/src/telemetry/exec-command-count-lines.test.ts new file mode 100644 index 000000000000..eacfe9f72952 --- /dev/null +++ b/code/core/src/telemetry/exec-command-count-lines.test.ts @@ -0,0 +1,71 @@ +import type { Transform } from 'node:stream'; +import { PassThrough } from 'node:stream'; + +import { beforeEach, describe, expect, it, vitest } from 'vitest'; + +// eslint-disable-next-line depend/ban-dependencies +import { execaCommand as rawExecaCommand } from 'execa'; + +import { execCommandCountLines } from './exec-command-count-lines'; + +vitest.mock('execa'); + +const execaCommand = vitest.mocked(rawExecaCommand); +beforeEach(() => { + execaCommand.mockReset(); +}); + +type ExecaStreamer = typeof Promise & { + stdout: Transform; + kill: () => void; +}; + +function createExecaStreamer() { + let resolver: () => void; + const promiseLike: ExecaStreamer = new Promise((aResolver, aRejecter) => { + resolver = aResolver; + }) as any; + + promiseLike.stdout = new PassThrough(); + // @ts-expect-error technically it is invalid to use resolver "before" it is assigned (but not really) + promiseLike.kill = resolver; + return promiseLike; +} + +describe('execCommandCountLines', () => { + it('counts lines, many', async () => { + const streamer = createExecaStreamer(); + execaCommand.mockReturnValue(streamer as any); + + const promise = execCommandCountLines('some command'); + + streamer.stdout.write('First line\n'); + streamer.stdout.write('Second line\n'); + streamer.kill(); + + expect(await promise).toEqual(2); + }); + + it('counts lines, one', async () => { + const streamer = createExecaStreamer(); + execaCommand.mockReturnValue(streamer as any); + + const promise = execCommandCountLines('some command'); + + streamer.stdout.write('First line\n'); + streamer.kill(); + + expect(await promise).toEqual(1); + }); + + it('counts lines, none', async () => { + const streamer = createExecaStreamer(); + execaCommand.mockReturnValue(streamer as any); + + const promise = execCommandCountLines('some command'); + + streamer.kill(); + + expect(await promise).toEqual(0); + }); +}); diff --git a/code/core/src/telemetry/exec-command-count-lines.ts b/code/core/src/telemetry/exec-command-count-lines.ts new file mode 100644 index 000000000000..fdc4547ce464 --- /dev/null +++ b/code/core/src/telemetry/exec-command-count-lines.ts @@ -0,0 +1,35 @@ +import { createInterface } from 'node:readline'; + +// eslint-disable-next-line depend/ban-dependencies +import { execaCommand } from 'execa'; + +/** + * Execute a command in the local terminal and count the lines in the result + * + * @param command The command to execute. + * @param options Execa options + * @returns The number of lines the command returned + */ +export async function execCommandCountLines( + command: string, + options?: Parameters[1] +) { + const process = execaCommand(command, { shell: true, buffer: false, ...options }); + if (!process.stdout) { + // eslint-disable-next-line local-rules/no-uncategorized-errors + throw new Error('Unexpected missing stdout'); + } + + let lineCount = 0; + const rl = createInterface(process.stdout); + rl.on('line', () => { + lineCount += 1; + }); + + // If the process errors, this will throw + await process; + + rl.close(); + + return lineCount; +} diff --git a/code/core/src/telemetry/get-application-file-count.test.ts b/code/core/src/telemetry/get-application-file-count.test.ts new file mode 100644 index 000000000000..7fc570689147 --- /dev/null +++ b/code/core/src/telemetry/get-application-file-count.test.ts @@ -0,0 +1,14 @@ +import { join } from 'node:path'; + +import { describe, expect, it } from 'vitest'; + +import { getApplicationFilesCountUncached } from './get-application-file-count'; + +const mocksDir = join(__dirname, '..', '__mocks__'); + +describe('getApplicationFilesCount', () => { + it('should find files with correct names', async () => { + const files = await getApplicationFilesCountUncached(mocksDir); + expect(files).toMatchInlineSnapshot(`2`); + }); +}); diff --git a/code/core/src/telemetry/get-application-file-count.ts b/code/core/src/telemetry/get-application-file-count.ts new file mode 100644 index 000000000000..4f4807ddff00 --- /dev/null +++ b/code/core/src/telemetry/get-application-file-count.ts @@ -0,0 +1,32 @@ +import { sep } from 'node:path'; + +import { execCommandCountLines } from './exec-command-count-lines'; +import { runTelemetryOperation } from './run-telemetry-operation'; + +// We are looking for files with the word "page" or "screen" somewhere in them with these exts +const nameMatches = ['page', 'screen']; +const extensions = ['js', 'jsx', 'ts', 'tsx']; + +export const getApplicationFilesCountUncached = async (basePath: string) => { + const bothCasesNameMatches = nameMatches.flatMap((match) => [ + match, + [match[0].toUpperCase(), ...match.slice(1)].join(''), + ]); + + const globs = bothCasesNameMatches.flatMap((match) => + extensions.map((extension) => `"${basePath}${sep}*${match}*.${extension}"`) + ); + + try { + const command = `git ls-files -- ${globs.join(' ')}`; + return await execCommandCountLines(command); + } catch { + return undefined; + } +}; + +export const getApplicationFileCount = async (path: string) => { + return runTelemetryOperation('applicationFiles', async () => + getApplicationFilesCountUncached(path) + ); +}; diff --git a/code/core/src/telemetry/get-has-router-package.test.ts b/code/core/src/telemetry/get-has-router-package.test.ts new file mode 100644 index 000000000000..8504a5bc4d84 --- /dev/null +++ b/code/core/src/telemetry/get-has-router-package.test.ts @@ -0,0 +1,29 @@ +import { expect, it } from 'vitest'; + +import { getHasRouterPackage } from './get-has-router-package'; + +it('returns true if there is a routing package in package.json', () => { + expect( + getHasRouterPackage({ + dependencies: { + react: '^18', + 'react-dom': '^18', + 'react-router': '^6', + }, + }) + ).toBe(true); +}); + +it('returns false if there is a routing package in package.json dependencies', () => { + expect( + getHasRouterPackage({ + dependencies: { + react: '^18', + 'react-dom': '^18', + }, + devDependencies: { + 'react-router': '^6', + }, + }) + ).toBe(false); +}); diff --git a/code/core/src/telemetry/get-has-router-package.ts b/code/core/src/telemetry/get-has-router-package.ts new file mode 100644 index 000000000000..5873c3832d25 --- /dev/null +++ b/code/core/src/telemetry/get-has-router-package.ts @@ -0,0 +1,37 @@ +import type { PackageJson } from '../types'; + +const routerPackages = new Set([ + 'react-router', + 'react-router-dom', + 'remix', + '@tanstack/react-router', + 'expo-router', + '@reach/router', + 'react-easy-router', + '@remix-run/router', + 'wouter', + 'wouter-preact', + 'preact-router', + 'vue-router', + 'unplugin-vue-router', + '@angular/router', + '@solidjs/router', + + // metaframeworks that imply routing + 'next', + 'react-scripts', + 'gatsby', + 'nuxt', + '@sveltejs/kit', +]); + +/** + * @param packageJson The package JSON of the project + * @returns Boolean Does this project use a routing package? + */ +export function getHasRouterPackage(packageJson: PackageJson) { + // NOTE: we just check real dependencies; if it is in dev dependencies, it may just be an example + return Object.keys(packageJson?.dependencies ?? {}).some((depName) => + routerPackages.has(depName) + ); +} diff --git a/code/core/src/telemetry/get-portable-stories-usage.ts b/code/core/src/telemetry/get-portable-stories-usage.ts index cd9da7f4f589..0831b484ab69 100644 --- a/code/core/src/telemetry/get-portable-stories-usage.ts +++ b/code/core/src/telemetry/get-portable-stories-usage.ts @@ -1,37 +1,18 @@ -// eslint-disable-next-line depend/ban-dependencies -import { execaCommand } from 'execa'; - -import { createFileSystemCache, resolvePathInStorybookCache } from '../common'; - -const cache = createFileSystemCache({ - basePath: resolvePathInStorybookCache('portable-stories'), - ns: 'storybook', - ttl: 24 * 60 * 60 * 1000, // 24h -}); +import { execCommandCountLines } from './exec-command-count-lines'; +import { runTelemetryOperation } from './run-telemetry-operation'; export const getPortableStoriesFileCountUncached = async (path?: string) => { - const command = `git grep -l composeStor` + (path ? ` -- ${path}` : ''); - const { stdout } = await execaCommand(command, { - cwd: process.cwd(), - shell: true, - }); - - return stdout.split('\n').filter(Boolean).length; + try { + const command = `git grep -l composeStor` + (path ? ` -- ${path}` : ''); + return await execCommandCountLines(command); + } catch (err: any) { + // exit code 1 if no matches are found + return err.exitCode === 1 ? 0 : undefined; + } }; -const CACHE_KEY = 'portableStories'; export const getPortableStoriesFileCount = async (path?: string) => { - let cached = await cache.get(CACHE_KEY); - if (!cached) { - try { - const count = await getPortableStoriesFileCountUncached(); - cached = { count }; - await cache.set(CACHE_KEY, cached); - } catch (err: any) { - // exit code 1 if no matches are found - const count = err.exitCode === 1 ? 0 : null; - cached = { count }; - } - } - return cached.count; + return runTelemetryOperation('portableStories', async () => + getPortableStoriesFileCountUncached(path) + ); }; diff --git a/code/core/src/telemetry/run-telemetry-operation.ts b/code/core/src/telemetry/run-telemetry-operation.ts new file mode 100644 index 000000000000..29d2aee6c721 --- /dev/null +++ b/code/core/src/telemetry/run-telemetry-operation.ts @@ -0,0 +1,25 @@ +import { createFileSystemCache, resolvePathInStorybookCache } from '../common'; + +const cache = createFileSystemCache({ + basePath: resolvePathInStorybookCache('telemetry'), + ns: 'storybook', + ttl: 24 * 60 * 60 * 1000, // 24h +}); + +/** + * Run an (expensive) operation, caching the result in a FS cache for 24 hours. + * + * NOTE: if the operation returns `undefined` the value will not be cached. Use this to indicate + * that the operation failed. + */ +export const runTelemetryOperation = async (cacheKey: string, operation: () => Promise) => { + let cached = await cache.get(cacheKey); + if (cached === undefined) { + cached = await operation(); + // Undefined indicates an error, setting isn't really valuable. + if (cached !== undefined) { + await cache.set(cacheKey, cached); + } + } + return cached; +}; diff --git a/code/core/src/telemetry/storybook-metadata.test.ts b/code/core/src/telemetry/storybook-metadata.test.ts index 06bf355c0688..8d73ff7b437d 100644 --- a/code/core/src/telemetry/storybook-metadata.test.ts +++ b/code/core/src/telemetry/storybook-metadata.test.ts @@ -12,6 +12,8 @@ const packageJsonMock: PackageJson = { version: 'x.x.x', }; +const packageJsonPath = process.cwd(); + const mainJsMock: StorybookConfig = { stories: [], }; @@ -126,6 +128,7 @@ describe('storybook-metadata', () => { it('should parse pnp paths for known frameworks', async () => { const unixResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -144,6 +147,7 @@ describe('storybook-metadata', () => { const windowsResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -164,6 +168,7 @@ describe('storybook-metadata', () => { it('should parse pnp paths for unknown frameworks', async () => { const unixResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -178,6 +183,7 @@ describe('storybook-metadata', () => { const windowsResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -198,6 +204,7 @@ describe('storybook-metadata', () => { const unixResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -215,6 +222,7 @@ describe('storybook-metadata', () => { cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue('C:\\Users\\foo\\my-project'); const windowsResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -232,6 +240,7 @@ describe('storybook-metadata', () => { it('should return frameworkOptions from mainjs', async () => { const reactResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -250,6 +259,7 @@ describe('storybook-metadata', () => { const angularResult = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: { @@ -279,6 +289,7 @@ describe('storybook-metadata', () => { 'storybook-addon-deprecated': 'x.x.z', }, } as PackageJson, + packageJsonPath, mainConfig: { ...mainJsMock, addons: [ @@ -319,6 +330,7 @@ describe('storybook-metadata', () => { const result = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, features, @@ -332,6 +344,7 @@ describe('storybook-metadata', () => { expect( await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, framework: '@storybook/react-vite', @@ -347,6 +360,7 @@ describe('storybook-metadata', () => { it('should return the number of refs', async () => { const res = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, refs: { @@ -361,6 +375,7 @@ describe('storybook-metadata', () => { it('only reports addon options for addon-essentials', async () => { const res = await computeStorybookMetadata({ packageJson: packageJsonMock, + packageJsonPath, mainConfig: { ...mainJsMock, addons: [ @@ -395,6 +410,7 @@ describe('storybook-metadata', () => { [metaFramework]: 'x.x.x', }, } as PackageJson, + packageJsonPath, mainConfig: mainJsMock, }); expect(res.metaFramework).toEqual({ diff --git a/code/core/src/telemetry/storybook-metadata.ts b/code/core/src/telemetry/storybook-metadata.ts index 75804b813fc2..5258eef0ffb7 100644 --- a/code/core/src/telemetry/storybook-metadata.ts +++ b/code/core/src/telemetry/storybook-metadata.ts @@ -1,3 +1,5 @@ +import { dirname } from 'node:path'; + import { getProjectRoot, getStorybookConfiguration, @@ -9,10 +11,12 @@ import type { PackageJson, StorybookConfig } from '@storybook/core/types'; import { readConfig } from '@storybook/core/csf-tools'; import { detect, getNpmVersion } from 'detect-package-manager'; -import { findPackage } from 'fd-package-json'; +import { findPackage, findPackagePath } from 'fd-package-json'; +import { getApplicationFileCount } from './get-application-file-count'; import { getChromaticVersionSpecifier } from './get-chromatic-version'; import { getFrameworkInfo } from './get-framework-info'; +import { getHasRouterPackage } from './get-has-router-package'; import { getMonorepoType } from './get-monorepo-type'; import { getPortableStoriesFileCount } from './get-portable-stories-usage'; import { getActualPackageVersion, getActualPackageVersions } from './package-json'; @@ -41,9 +45,11 @@ export const sanitizeAddonName = (name: string) => { // Analyze a combination of information from main.js and package.json // to provide telemetry over a Storybook project export const computeStorybookMetadata = async ({ + packageJsonPath, packageJson, mainConfig, }: { + packageJsonPath: string; packageJson: PackageJson; mainConfig: StorybookConfig & Record; }): Promise => { @@ -100,6 +106,8 @@ export const computeStorybookMetadata = async ({ ) ); + metadata.hasRouterPackage = getHasRouterPackage(packageJson); + const monorepoType = getMonorepoType(); if (monorepoType) { metadata.monorepo = monorepoType; @@ -209,11 +217,13 @@ export const computeStorybookMetadata = async ({ const storybookVersion = storybookPackages[storybookInfo.frameworkPackage]?.version; const portableStoriesFileCount = await getPortableStoriesFileCount(); + const applicationFileCount = await getApplicationFileCount(dirname(packageJsonPath)); return { ...metadata, ...frameworkInfo, portableStoriesFileCount, + applicationFileCount, storybookVersion, storybookVersionSpecifier: storybookInfo.version, language, @@ -223,13 +233,29 @@ export const computeStorybookMetadata = async ({ }; }; +async function getPackageJsonDetails() { + const packageJsonPath = await findPackagePath(process.cwd()); + if (packageJsonPath) { + return { + packageJsonPath, + packageJson: (await findPackage(packageJsonPath)) || {}, + }; + } + + // If we don't find a `package.json`, we assume it "would have" been in the current working directory + return { + packageJsonPath: process.cwd(), + packageJson: {}, + }; +} + let cachedMetadata: StorybookMetadata; export const getStorybookMetadata = async (_configDir?: string) => { if (cachedMetadata) { return cachedMetadata; } - const packageJson = (await findPackage(process.cwd())) || {}; + const { packageJson, packageJsonPath } = await getPackageJsonDetails(); // TODO: improve the way configDir is extracted, as a "storybook" script might not be present // Scenarios: // 1. user changed it to something else e.g. "storybook:dev" @@ -243,6 +269,6 @@ export const getStorybookMetadata = async (_configDir?: string) => { ) as string)) ?? '.storybook'; const mainConfig = await loadMainConfig({ configDir }); - cachedMetadata = await computeStorybookMetadata({ mainConfig, packageJson }); + cachedMetadata = await computeStorybookMetadata({ mainConfig, packageJson, packageJsonPath }); return cachedMetadata; }; diff --git a/code/core/src/telemetry/types.ts b/code/core/src/telemetry/types.ts index 757f5afc197e..e43373e5e61b 100644 --- a/code/core/src/telemetry/types.ts +++ b/code/core/src/telemetry/types.ts @@ -59,6 +59,7 @@ export type StorybookMetadata = { version: string; }; testPackages?: Record; + hasRouterPackage?: boolean; hasStorybookEslint?: boolean; hasStaticDirs?: boolean; hasCustomWebpack?: boolean; @@ -69,6 +70,7 @@ export type StorybookMetadata = { usesGlobals?: boolean; }; portableStoriesFileCount?: number; + applicationFileCount?: number; }; export interface Payload { diff --git a/code/deprecated/builder-manager/package.json b/code/deprecated/builder-manager/package.json index fd71436811d1..9998fd59a573 100644 --- a/code/deprecated/builder-manager/package.json +++ b/code/deprecated/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook manager builder", "keywords": [ "storybook" diff --git a/code/deprecated/channels/package.json b/code/deprecated/channels/package.json index e0f982ac028b..988ed72abb2c 100644 --- a/code/deprecated/channels/package.json +++ b/code/deprecated/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/client-logger/package.json b/code/deprecated/client-logger/package.json index d09c87e56926..f4de8eedbefa 100644 --- a/code/deprecated/client-logger/package.json +++ b/code/deprecated/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/components/package.json b/code/deprecated/components/package.json index 469a51d0ebb5..28de35eec46a 100644 --- a/code/deprecated/components/package.json +++ b/code/deprecated/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/core-common/package.json b/code/deprecated/core-common/package.json index fe28424bb50b..372be0dfea26 100644 --- a/code/deprecated/core-common/package.json +++ b/code/deprecated/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/core-events/package.json b/code/deprecated/core-events/package.json index 9f6b683c3320..bcf2157df22c 100644 --- a/code/deprecated/core-events/package.json +++ b/code/deprecated/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Event names used in storybook core", "keywords": [ "storybook" diff --git a/code/deprecated/core-server/package.json b/code/deprecated/core-server/package.json index 2ad77557ad53..9cf49f637df2 100644 --- a/code/deprecated/core-server/package.json +++ b/code/deprecated/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/csf-tools/package.json b/code/deprecated/csf-tools/package.json index 58acc248335c..3c0aa71c00c3 100644 --- a/code/deprecated/csf-tools/package.json +++ b/code/deprecated/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/deprecated/docs-tools/package.json b/code/deprecated/docs-tools/package.json index fe154c164db4..002c500c1cb0 100644 --- a/code/deprecated/docs-tools/package.json +++ b/code/deprecated/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/deprecated/manager-api/package.json b/code/deprecated/manager-api/package.json index a0cb5ac6f9b6..a203750e5675 100644 --- a/code/deprecated/manager-api/package.json +++ b/code/deprecated/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" diff --git a/code/deprecated/manager/package.json b/code/deprecated/manager/package.json index 941049b955b2..b8ad3dc9d18b 100644 --- a/code/deprecated/manager/package.json +++ b/code/deprecated/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook UI", "keywords": [ "storybook" diff --git a/code/deprecated/node-logger/package.json b/code/deprecated/node-logger/package.json index f1081b028213..9b854e1e73d8 100644 --- a/code/deprecated/node-logger/package.json +++ b/code/deprecated/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview-api/package.json b/code/deprecated/preview-api/package.json index 5c5d894f90af..682e0a595d1f 100644 --- a/code/deprecated/preview-api/package.json +++ b/code/deprecated/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview/package.json b/code/deprecated/preview/package.json index fa91ac524655..91cad5bc2737 100644 --- a/code/deprecated/preview/package.json +++ b/code/deprecated/preview/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/router/package.json b/code/deprecated/router/package.json index 3b2e0b23416e..f5c22b5ef835 100644 --- a/code/deprecated/router/package.json +++ b/code/deprecated/router/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/router", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook Router", "keywords": [ "storybook" diff --git a/code/deprecated/telemetry/package.json b/code/deprecated/telemetry/package.json index c2a12b4fd4a9..d5b569580464 100644 --- a/code/deprecated/telemetry/package.json +++ b/code/deprecated/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/telemetry", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Telemetry logging for crash reports and usage statistics", "keywords": [ "storybook" diff --git a/code/deprecated/theming/package.json b/code/deprecated/theming/package.json index 7d232d7d961a..e7078e2c55f3 100644 --- a/code/deprecated/theming/package.json +++ b/code/deprecated/theming/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/theming", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/types/package.json b/code/deprecated/types/package.json index d8aa8cf50e59..0bbcb006eae1 100644 --- a/code/deprecated/types/package.json +++ b/code/deprecated/types/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/types", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Core Storybook TS Types", "keywords": [ "storybook" diff --git a/code/e2e-tests/preview-api.spec.ts b/code/e2e-tests/preview-api.spec.ts index cfabaf89674c..31b566027fd9 100644 --- a/code/e2e-tests/preview-api.spec.ts +++ b/code/e2e-tests/preview-api.spec.ts @@ -65,6 +65,7 @@ test.describe('preview-api', () => { const root = sbPage.previewRoot(); + await sbPage.viewAddonPanel('Controls'); const labelControl = sbPage.page.locator('#control-label'); await expect(root.getByText('Loaded. Click me')).toBeVisible(); diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index 7ac17f6c5506..576788920f79 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index 9b63281d1e21..a397b8c1d5a6 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/experimental-nextjs-vite/package.json b/code/frameworks/experimental-nextjs-vite/package.json index c8beb6e37803..daf389813ec1 100644 --- a/code/frameworks/experimental-nextjs-vite/package.json +++ b/code/frameworks/experimental-nextjs-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/experimental-nextjs-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Next.js and Vite", "keywords": [ "storybook", diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index f6e7d96701f6..d60457db363a 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index c6597bb17a64..754cc9019674 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index fe21d56ea6b9..87a35ff52905 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Next.js", "keywords": [ "storybook", diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index 94c8152f6308..4fc5571a5f1b 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 22a6956d8142..c1404318b69e 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-native-web-vite/package.json b/code/frameworks/react-native-web-vite/package.json index b256cf70d1b6..147f1c243bed 100644 --- a/code/frameworks/react-native-web-vite/package.json +++ b/code/frameworks/react-native-web-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-native-web-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Develop react-native components an isolated web environment with hot reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index c6a45266f22b..a59dd55dd0d2 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 8e564dffa63f..7db983e04e07 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 58ed15954906..5a5a024bad2a 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 955e2206cfe9..c93bda611e59 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 6bc52a6b823c..458e2c9290bc 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 77fb37cc5f03..11ad71aaf0c2 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for SvelteKit", "keywords": [ "storybook", diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index 7bb0922259a9..c1f245b7514c 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index 4cc005ebf449..73e8c8033baf 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index e6fa38e1646a..7fe54f06d4ef 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 58dfcaa0738b..5db1d433cdf9 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index 12504b248173..02778aa210a0 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Doc Blocks", "keywords": [ "storybook" diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 3d9f74381e87..99d8537a512d 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index 7e0d04ac274a..8b7d3aae3a32 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index 765a06c1f3d6..c63ae7acdf82 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index b41d0290501c..ec3cad1f1fe0 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index bb490874f2ba..3224d7089b96 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/create-storybook/package.json b/code/lib/create-storybook/package.json index 8916f1e56826..5e5ee2a48bfc 100644 --- a/code/lib/create-storybook/package.json +++ b/code/lib/create-storybook/package.json @@ -1,6 +1,6 @@ { "name": "create-storybook", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Initialize Storybook into your project", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/create-storybook", "bugs": { diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index 21b0e8b1855f..dc49ef2e1913 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index a015da12f533..a4c16dcff69d 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index 75818dcef25d..8fa32975c148 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index a3073390d00d..60857a4d2170 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Source loader", "keywords": [ "lib", diff --git a/code/lib/test/package.json b/code/lib/test/package.json index e1d356bdb570..40202d1c5c3e 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/test", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "", "keywords": [ "storybook" diff --git a/code/nx.json b/code/nx.json index 085623d3b4de..eaaabd089ea4 100644 --- a/code/nx.json +++ b/code/nx.json @@ -3,7 +3,7 @@ "extends": "nx/presets/npm.json", "nxCloudAccessToken": "NGVmYTkxMmItYzY3OS00MjkxLTk1ZDktZDFmYTFmNmVlNGY4fHJlYWQ=", "defaultBase": "next", - "useLegacyCache": "true", + "useLegacyCache": true, "parallel": 8, "plugins": [ { diff --git a/code/package.json b/code/package.json index 91d2a03457f8..7b9fd27a6318 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -90,7 +90,7 @@ "type-fest": "~2.19" }, "dependencies": { - "@chromatic-com/storybook": "^3.2.0", + "@chromatic-com/storybook": "^3.2.2", "@happy-dom/global-registrator": "^14.12.0", "@nx/eslint": "20.2.2", "@nx/vite": "20.2.2", diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index f0b9550cd8e1..ea8849294e29 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 0187f6af1adc..9094d24589c5 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 45fe95cdc3c3..d87bfd54c980 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index 65bdb059fed4..48b04685bd43 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index e3e366850900..aaeb9c2dc159 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index 45448bf58dc0..1053d6ec17c7 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index aedd88aff477..2477b603d753 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index 817ba8045700..3726b3e2a2a1 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index b47e3cbd0164..411e0a72028d 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index a58ef3d8dde8..3a2bc736cfec 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index 232c064fbd58..484c3eb38f82 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Server renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index 0e084a61dd4f..7aa8fec6f5c9 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index c5a70b1bf71f..4aef83519c25 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook Vue 3 renderer", "keywords": [ "storybook" diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index 3365415dccca..c2f23a997864 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.5.0-alpha.22", + "version": "8.5.0-beta.2", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/sandbox/experimental-nextjs-vite-default-ts/project.json b/code/sandbox/experimental-nextjs-vite-default-ts/project.json new file mode 100644 index 000000000000..ae9d595865dd --- /dev/null +++ b/code/sandbox/experimental-nextjs-vite-default-ts/project.json @@ -0,0 +1,21 @@ +{ + "name": "experimental-nextjs-vite/default-ts", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "implicitDependencies": [ + "storybook", + "core", + "addon-essentials", + "addon-interactions", + "addon-links", + "addon-onboarding", + "blocks", + "experimental-nextjs-vite" + ], + "targets": { + "sandbox": {}, + "sb:dev": {}, + "sb:build": {} + }, + "tags": ["ci:normal", "ci:merged", "ci:daily"] +} diff --git a/code/yarn.lock b/code/yarn.lock index 87e41b6b5a15..2e83b8e16192 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -2532,21 +2532,18 @@ __metadata: languageName: node linkType: hard -"@chromatic-com/storybook@npm:^3.2.0": - version: 3.2.0 - resolution: "@chromatic-com/storybook@npm:3.2.0" +"@chromatic-com/storybook@npm:^3.2.2": + version: 3.2.2 + resolution: "@chromatic-com/storybook@npm:3.2.2" dependencies: - "@storybook/channels": "npm:^8.3.0" - "@storybook/telemetry": "npm:^8.3.0" - "@storybook/types": "npm:^8.3.0" chromatic: "npm:^11.15.0" filesize: "npm:^10.0.12" jsonfile: "npm:^6.1.0" react-confetti: "npm:^6.1.0" strip-ansi: "npm:^7.1.0" peerDependencies: - storybook: "*" - checksum: 10c0/59485e69a55df6b1998e19bf0e129fa1f9a86d3ae541f4dcb6f6dd945e7b9a6258ce75e244aaa73821039cef8c57424402a3c0bf63a66b4511a2ac0b5611103b + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 10c0/7b8da1ddb399c804337ff28a28594b548392b7bead52f66615b98e201cdeb4d31184b9e355791ba5d0d8cfdd2bea7d38355ecd0058f26f4790f9a887107bde0f languageName: node linkType: hard @@ -6037,15 +6034,6 @@ __metadata: languageName: unknown linkType: soft -"@storybook/channels@npm:^8.3.0": - version: 8.3.6 - resolution: "@storybook/channels@npm:8.3.6" - peerDependencies: - storybook: ^8.3.6 - checksum: 10c0/3c34ed2b03c60c6ed1160d9a0efdb836be892e333556848ff492c16ab6d92521207512670d42f69d681f521e50f130a00f692610a3ca63228a8d2b49be57f4fa - languageName: node - linkType: hard - "@storybook/channels@workspace:deprecated/channels": version: 0.0.0-use.local resolution: "@storybook/channels@workspace:deprecated/channels" @@ -7035,7 +7023,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/root@workspace:." dependencies: - "@chromatic-com/storybook": "npm:^3.2.0" + "@chromatic-com/storybook": "npm:^3.2.2" "@happy-dom/global-registrator": "npm:^14.12.0" "@nx/eslint": "npm:20.2.2" "@nx/vite": "npm:20.2.2" @@ -7325,15 +7313,6 @@ __metadata: languageName: unknown linkType: soft -"@storybook/telemetry@npm:^8.3.0": - version: 8.3.6 - resolution: "@storybook/telemetry@npm:8.3.6" - peerDependencies: - storybook: ^8.3.6 - checksum: 10c0/b4fd8d0e238335249aa82dea49bde56813e0c771e67dd7110fb9e038d1e2bd64aa03e76ee865ef6a7f0fd5220d02bd7bcf3273bb4c19403e3d527d9dd7a258d4 - languageName: node - linkType: hard - "@storybook/telemetry@workspace:deprecated/telemetry": version: 0.0.0-use.local resolution: "@storybook/telemetry@workspace:deprecated/telemetry" @@ -7383,15 +7362,6 @@ __metadata: languageName: unknown linkType: soft -"@storybook/types@npm:^8.3.0": - version: 8.3.6 - resolution: "@storybook/types@npm:8.3.6" - peerDependencies: - storybook: ^8.3.6 - checksum: 10c0/482f55e34877f9eb94a8ff4627a254f3b5442f91f13363e6837e3a9c220a369be1c6ce4652b870b7fa4e522c3365825651f9e04a21bda76b104a6c1f7435e274 - languageName: node - linkType: hard - "@storybook/types@workspace:*, @storybook/types@workspace:deprecated/types": version: 0.0.0-use.local resolution: "@storybook/types@workspace:deprecated/types" diff --git a/docs/_snippets/storybook-addon-a11y-test-override-warning-levels.md b/docs/_snippets/storybook-addon-a11y-test-override-warning-levels.md deleted file mode 100644 index 120a5ad6de8b..000000000000 --- a/docs/_snippets/storybook-addon-a11y-test-override-warning-levels.md +++ /dev/null @@ -1,32 +0,0 @@ -```js filename=".storybook/preview.js" renderer="common" language="js" -export default { - parameters: { - a11y: { - /* - * Configure the warning levels for a11y checks - * The available options are 'minor', 'moderate', 'serious', and 'critical' - */ - warnings: ['minor', 'moderate'], - }, - }, -}; -``` - -```ts filename=".storybook/preview.ts" renderer="common" language="ts" -// Replace your-framework with the framework you are using (e.g., react, vue3) -import { Preview } from '@storybook/your-framework'; - -const preview: Preview = { - parameters: { - a11y: { - /* - * Configure the warning levels for a11y checks - * The available options are 'minor', 'moderate', 'serious', and 'critical' - */ - warnings: ['minor', 'moderate'], - }, - }, -}; - -export default preview; -``` diff --git a/docs/versions/next.json b/docs/versions/next.json index 8ba437344971..7399d21ebb8d 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.5.0-alpha.22","info":{"plain":"- Addon Docs: Dynamically import rehype - [#29544](https://github.com/storybookjs/storybook/pull/29544), thanks @valentinpalkovic!\n- Addon Test: Fix duplicate `test.include` patterns - [#30029](https://github.com/storybookjs/storybook/pull/30029), thanks @JReinhold!\n- Addon Test: Fix environment variable for Vitest Storybook integration - [#30054](https://github.com/storybookjs/storybook/pull/30054), thanks @valentinpalkovic!\n- Addon Test: Use local storybook binary instead - [#30021](https://github.com/storybookjs/storybook/pull/30021), thanks @kasperpeulen!\n- Addon Test: Wait for 2 seconds before showing result mismatch warning - [#30002](https://github.com/storybookjs/storybook/pull/30002), thanks @ghengeveld!\n- Angular: Support statsJson in angular schemas - [#29233](https://github.com/storybookjs/storybook/pull/29233), thanks @yannbf!\n- Core: Fix `scrollIntoView` behavior and reimplement testing module time rendering - [#30044](https://github.com/storybookjs/storybook/pull/30044), thanks @ghengeveld!\n- Docs: Add code snippet to addons panel - [#29253](https://github.com/storybookjs/storybook/pull/29253), thanks @larsrickert!\n- Next.js: Fix webpack fsCache not working - [#29654](https://github.com/storybookjs/storybook/pull/29654), thanks @sentience!\n- Nextjs-Vite: Add TS docgen support - [#29824](https://github.com/storybookjs/storybook/pull/29824), thanks @yannbf!\n- Nextjs-Vite: Fix docgen types in main config - [#30042](https://github.com/storybookjs/storybook/pull/30042), thanks @yannbf!\n- React: Fix RSC compatibility with addon-themes and hooks - [#26243](https://github.com/storybookjs/storybook/pull/26243), thanks @shilman!\n- UI: Fix controls and parameters on tag-filtered stories - [#30038](https://github.com/storybookjs/storybook/pull/30038), thanks @shilman!"}} +{"version":"8.5.0-beta.2","info":{"plain":"- Addon Test: Clear coverage data when starting or watching - [#30072](https://github.com/storybookjs/storybook/pull/30072), thanks @ghengeveld!\n- Addon Test: Improve error message on missing coverage package - [#30088](https://github.com/storybookjs/storybook/pull/30088), thanks @JReinhold!\n- UI: Fix test provider event handling on startup - [#30083](https://github.com/storybookjs/storybook/pull/30083), thanks @ghengeveld!\n- UI: Keep failing stories in the sidebar, disregarding filters - [#30086](https://github.com/storybookjs/storybook/pull/30086), thanks @JReinhold!"}} diff --git a/docs/writing-tests/accessibility-testing.mdx b/docs/writing-tests/accessibility-testing.mdx index e8f3e5c00917..8fdbe571d9bc 100644 --- a/docs/writing-tests/accessibility-testing.mdx +++ b/docs/writing-tests/accessibility-testing.mdx @@ -100,7 +100,7 @@ Customize the a11y ruleset at the story level by updating your story to include If you are using Svelte CSF, you can turn off automated accessibility testing for stories or components by adding globals to your story or adjusting the `defineMeta` function with the required configuration. With a regular CSF story, you can add the following to your story's export or component's default export: - + @@ -143,13 +143,13 @@ You can use tags to progressively work toward a more accessible UI by enabling a ```ts title=".storybook/preview.ts" // Replace your-renderer with the renderer you are using (e.g., react, vue3) import { Preview } from '@storybook/your-renderer'; - + const preview: Preview = { // ... // 👇 Temporarily remove the a11ytest tag from all stories tags: ['!a11ytest'], }; - + export default preview; ``` @@ -163,18 +163,6 @@ You can use tags to progressively work toward a more accessible UI by enabling a 1. Pick another component and repeat the process until you've covered all your components and you're an accessibility hero! -### Override accessibility violation levels - -By default, when the accessibility addon runs with the test addon enabled, it interprets all violations as errors. This means that if a story has a minor accessibility violation, the test will fail. However, you can override this behavior by setting the `warnings` parameter in the `a11y` configuration object to define an array of impact levels that should be considered warnings. - -{/* prettier-ignore-start */} - - - -{/* prettier-ignore-end */} - -In the example above, we configured all the `minor` or `moderate` accessibility violations to be considered warnings. All other levels (i.e., `serious` or `critical`) will continue to be considered errors, fail the test, and report the results accordingly in the Storybook UI or CLI output. - ## Automate accessibility tests with test runner diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index ea99a566dbef..98f05c95f9d3 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -809,12 +809,7 @@ export const extendPreview: Task['run'] = async ({ template, sandboxDir }) => { const previewConfig = await readConfig({ cwd: sandboxDir, fileName: 'preview' }); if (template.expected.builder.includes('vite')) { - previewConfig.setFieldValue(['tags'], ['vitest']); - // TODO: Remove this once the starter components + test stories have proper accessibility - previewConfig.setFieldValue( - ['parameters', 'a11y', 'warnings'], - ['minor', 'moderate', 'serious', 'critical'] - ); + previewConfig.setFieldValue(['tags'], ['vitest', '!a11ytest']); } await writeConfig(previewConfig); diff --git a/test-storybooks/portable-stories-kitchen-sink/react/.storybook/aliased.ts b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/aliased.ts new file mode 100644 index 000000000000..030574bfd2a6 --- /dev/null +++ b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/aliased.ts @@ -0,0 +1,4 @@ +// This file is used to test that viteFinal is correctly loaded in Vitest +// main.ts defines this file as a resolve alias, which is used in the ViteFinalTest story + +export const aliasedFunction = () => true; diff --git a/test-storybooks/portable-stories-kitchen-sink/react/.storybook/main.ts b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/main.ts index 57b96d2e8d1e..fff0f008dd37 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/.storybook/main.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/main.ts @@ -1,4 +1,5 @@ import type { StorybookConfig } from "@storybook/react-vite"; +import { join } from 'path'; const config: StorybookConfig = { stories: ["../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"], @@ -32,5 +33,18 @@ const config: StorybookConfig = { border: 1px solid red; } `, + staticDirs: [{ from: './test-static-dirs', to:'test-static-dirs' }], + viteFinal: (config) => { + return { + ...config, + resolve: { + ...config.resolve, + alias: { + ...config.resolve?.alias, + 'test-alias': join(__dirname, 'aliased.ts'), + }, + } + }; + }, }; export default config; diff --git a/test-storybooks/portable-stories-kitchen-sink/react/.storybook/test-static-dirs/static.js b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/test-static-dirs/static.js new file mode 100644 index 000000000000..56ff9f9c7ad4 --- /dev/null +++ b/test-storybooks/portable-stories-kitchen-sink/react/.storybook/test-static-dirs/static.js @@ -0,0 +1,3 @@ +// This file is used to test that staticDirs are correctly loaded in Vitest + +export const staticFunction = () => true; diff --git a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts index ed3eebbbae59..9e88b7d0a579 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts @@ -6,16 +6,13 @@ import { expect, test } from "@playwright/test"; import { SbPage } from "../../../../code/e2e-tests/util"; -const storybookUrl = "http://localhost:6006"; -const testStoryPath = path.resolve( - __dirname, - "..", - "stories/AddonTest.stories.tsx" -); +const STORYBOOK_URL = "http://localhost:6006"; +const TEST_STORY_PATH = path.resolve(__dirname, "..", "stories", "AddonTest.stories.tsx"); +const BUTTON_COMPONENT_PATH = path.resolve(__dirname, "..", "stories", "Button.tsx"); const setForceFailureFlag = async (value: boolean) => { // Read the story file content asynchronously - const storyContent = (await fs.readFile(testStoryPath)).toString(); + const storyContent = (await fs.readFile(TEST_STORY_PATH)).toString(); // Create a regex to match 'forceFailure: true' or 'forceFailure: false' const forceFailureRegex = /forceFailure:\s*(true|false)/; @@ -27,7 +24,7 @@ const setForceFailureFlag = async (value: boolean) => { ); // Write the updated content back to the file asynchronously - await fs.writeFile(testStoryPath, updatedContent); + await fs.writeFile(TEST_STORY_PATH, updatedContent); // the file change causes a HMR event, which causes a browser reload,and that can take a few seconds await new Promise((resolve) => setTimeout(resolve, 2000)); @@ -38,7 +35,7 @@ test.describe("component testing", () => { test.beforeEach(async ({ page }) => { const sbPage = new SbPage(page, expect); - await page.goto(storybookUrl); + await page.goto(STORYBOOK_URL); await page.evaluate(() => window.sessionStorage.clear()); await sbPage.waitUntilLoaded(); }); @@ -48,9 +45,10 @@ test.describe("component testing", () => { browserName, }) => { test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + test.setTimeout(40_000) const sbPage = new SbPage(page, expect); - await sbPage.navigateToStory("addons/test", "Mismatch Failure"); + await sbPage.navigateToStory("addons/group/test", "Mismatch Failure"); const expandButton = await page.getByLabel('Expand testing module') await expandButton.click(); @@ -89,7 +87,7 @@ test.describe("component testing", () => { // Assert discrepancy: CLI pass + Browser fail const failingStoryElement = page.locator( - '[data-item-id="addons-test--mismatch-failure"] [role="status"]' + '[data-item-id="addons-group-test--mismatch-failure"] [role="status"]' ); await expect(failingStoryElement).toHaveAttribute( "aria-label", @@ -100,9 +98,9 @@ test.describe("component testing", () => { ); // Assert discrepancy: CLI fail + Browser pass - await sbPage.navigateToStory("addons/test", "Mismatch Success"); + await sbPage.navigateToStory("addons/group/test", "Mismatch Success"); const successfulStoryElement = page.locator( - '[data-item-id="addons-test--mismatch-success"] [role="status"]' + '[data-item-id="addons-group-test--mismatch-success"] [role="status"]' ); await expect(successfulStoryElement).toHaveAttribute( "aria-label", @@ -121,7 +119,7 @@ test.describe("component testing", () => { await setForceFailureFlag(true); const sbPage = new SbPage(page, expect); - await sbPage.navigateToStory("addons/test", "Expected Failure"); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); const expandButton = page.getByLabel('Expand testing module') await expandButton.click(); @@ -159,7 +157,7 @@ test.describe("component testing", () => { // Assert for expected success const successfulStoryElement = page.locator( - '[data-item-id="addons-test--expected-success"] [role="status"]' + '[data-item-id="addons-group-test--expected-success"] [role="status"]' ); await expect(successfulStoryElement).toHaveAttribute( "aria-label", @@ -168,7 +166,7 @@ test.describe("component testing", () => { // Assert for expected failure const failingStoryElement = page.locator( - '[data-item-id="addons-test--expected-failure"] [role="status"]' + '[data-item-id="addons-group-test--expected-failure"] [role="status"]' ); await expect(failingStoryElement).toHaveAttribute( "aria-label", @@ -181,7 +179,7 @@ test.describe("component testing", () => { const sidebarItems = page.locator( '.sidebar-item[data-ref-id="storybook_internal"][data-nodetype="component"]' ); - await expect(sidebarItems).toHaveCount(1); + await expect(sidebarItems).toHaveCount(2); }); test("should execute watch mode tests via testing module UI", async ({ @@ -192,7 +190,7 @@ test.describe("component testing", () => { await setForceFailureFlag(false); const sbPage = new SbPage(page, expect); - await sbPage.navigateToStory("addons/test", "Expected Failure"); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); const expandButton = await page.getByLabel('Expand testing module') await expandButton.click(); @@ -207,8 +205,11 @@ test.describe("component testing", () => { // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(8000); - await setForceFailureFlag(true); + await page.waitForTimeout(500); + + // Cleanup, to ensure watch mode is disabled in the other tests + await page.getByLabel("Disable watch mode for Component tests").click(); // Wait for test results to appear const errorFilter = page.getByLabel("Toggle errors"); @@ -216,7 +217,7 @@ test.describe("component testing", () => { // Assert for expected success const successfulStoryElement = page.locator( - '[data-item-id="addons-test--expected-success"] [role="status"]' + '[data-item-id="addons-group-test--expected-success"] [role="status"]' ); await expect(successfulStoryElement).toHaveAttribute( "aria-label", @@ -225,7 +226,7 @@ test.describe("component testing", () => { // Assert for expected failure const failingStoryElement = page.locator( - '[data-item-id="addons-test--expected-failure"] [role="status"]' + '[data-item-id="addons-group-test--expected-failure"] [role="status"]' ); await expect(failingStoryElement).toHaveAttribute( "aria-label", @@ -240,4 +241,223 @@ test.describe("component testing", () => { ); await expect(sidebarItems).toHaveCount(1); }); + + test("should collect coverage to testing module and HTML report", async ({ + page, + browserName, + }) => { + test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + // Arrange - Prepare Storybook + await setForceFailureFlag(false); + + const sbPage = new SbPage(page, expect); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); + + const expandButton = await page.getByLabel('Expand testing module') + await expandButton.click(); + + const storyElement = sbPage + .getCanvasBodyElement() + .getByRole("button", { name: "test" }); + await expect(storyElement).toBeVisible({ timeout: 30000 }); + + // Assert - No coverage report initially + await expect(page.getByLabel("Open coverage report")).toHaveCount(0); + + // Act - Enable coverage and run tests + await page.getByLabel("Open settings for Component tests").click(); + await page.getByLabel("Coverage").click(); + await expect(page.getByText("Settings updated")).toBeVisible({ timeout: 3000 }); + await page.getByLabel("Close settings for Component tests").click(); + // Wait for Vitest to have (re)started + await page.waitForTimeout(2000); + + await page.getByLabel("Start Component tests").click(); + + // Assert - Coverage report is collected and shown + await expect(page.getByLabel("Open coverage report")).toBeVisible({ timeout: 30000 }); + const sbPercentageText = await page.getByLabel(/percent coverage$/).textContent(); + expect(sbPercentageText).toMatch(/^\d+\s%$/); + const sbPercentage = Number.parseInt(sbPercentageText!.replace(' %', '') ?? ''); + expect(sbPercentage).toBeGreaterThanOrEqual(0); + expect(sbPercentage).toBeLessThanOrEqual(100); + + // Act - Open HTML coverage report + const coverageReportLink = await page.getByLabel("Open coverage report"); + // Remove target="_blank" attribute to open in the same tab + await coverageReportLink.evaluate((elem) => elem.removeAttribute("target")); + await page.getByLabel("Open coverage report").click(); + + // Assert - HTML coverage report is accessible and reports the same coverage percentage as Storybook + const htmlPercentageText = await page.locator('span:has(+ :text("Statements"))').first().textContent() ?? ''; + const htmlPercentage = Number.parseFloat(htmlPercentageText.replace('% ', '')); + expect(Math.round(htmlPercentage)).toBe(sbPercentage); + + // Cleanup - Disable coverage again + await page.goBack(); + await expandButton.click(); + await page.getByLabel("Open settings for Component tests").click(); + await page.getByLabel("Coverage").click(); + await expect(page.getByText("Settings updated")).toBeVisible({ timeout: 3000 }); + }); + + test("should run focused test for a single story", async ({ + page, + browserName, + }) => { + test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + // Arrange - Prepare Storybook + await setForceFailureFlag(false); + + const sbPage = new SbPage(page, expect); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); + + const expandButton = await page.getByLabel('Expand testing module') + await expandButton.click(); + + const storyElement = sbPage + .getCanvasBodyElement() + .getByRole("button", { name: "test" }); + await expect(storyElement).toBeVisible({ timeout: 30000 }); + + // Act - Open sidebar context menu and start focused test + await page.locator('[data-item-id="addons-group-test--expected-failure"]').hover(); + await page.locator('[data-item-id="addons-group-test--expected-failure"] div[data-testid="context-menu"] button').click(); + const sidebarContextMenu = page.getByTestId('tooltip'); + await sidebarContextMenu.getByLabel('Start Component tests').click(); + + // Assert - Only one test is running and reported + await expect(sidebarContextMenu.locator('#testing-module-description')).toContainText('Ran 1 test', { timeout: 30000 }); + await expect(sidebarContextMenu.getByLabel('status: passed')).toHaveCount(1); + await page.click('body'); + await expect(page.locator('#storybook-explorer-menu').getByRole('status', { name: 'Test status: success' })).toHaveCount(1); + }); + + test("should run focused test for a component", async ({ + page, + browserName, + }) => { + test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + // Arrange - Prepare Storybook + await setForceFailureFlag(false); + + const sbPage = new SbPage(page, expect); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); + + const expandButton = await page.getByLabel('Expand testing module') + await expandButton.click(); + + const storyElement = sbPage + .getCanvasBodyElement() + .getByRole("button", { name: "test" }); + await expect(storyElement).toBeVisible({ timeout: 30000 }); + + // Act - Open sidebar context menu and start focused test + await page.locator('[data-item-id="addons-group-test"]').hover(); + await page.locator('[data-item-id="addons-group-test"] div[data-testid="context-menu"] button').click(); + const sidebarContextMenu = page.getByTestId('tooltip'); + await sidebarContextMenu.getByLabel('Start Component tests').click(); + + // Assert - Tests are running and reported + await expect(sidebarContextMenu.locator('#testing-module-description')).toContainText('Ran 8 tests', { timeout: 30000 }); + // Assert - Failing test shows as a failed status + await expect(sidebarContextMenu.getByText('1 story with errors')).toBeVisible(); + await expect(sidebarContextMenu.getByLabel('status: failed')).toHaveCount(1); + + await page.click('body'); + await expect(page.locator('#storybook-explorer-menu').getByRole('status', { name: 'Test status: success' })).toHaveCount(7); + await expect(page.locator('#storybook-explorer-menu').getByRole('status', { name: 'Test status: error' })).toHaveCount(1); + }); + + test("should run focused test for a group", async ({ + page, + browserName, + }) => { + test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + // Arrange - Prepare Storybook + await setForceFailureFlag(false); + + const sbPage = new SbPage(page, expect); + await sbPage.navigateToStory("addons/group/test", "Expected Failure"); + + const expandButton = await page.getByLabel('Expand testing module') + await expandButton.click(); + + const storyElement = sbPage + .getCanvasBodyElement() + .getByRole("button", { name: "test" }); + await expect(storyElement).toBeVisible({ timeout: 30000 }); + + // Act - Open sidebar context menu and start focused test + await page.locator('[data-item-id="addons-group"]').hover(); + await page.locator('[data-item-id="addons-group"] div[data-testid="context-menu"] button').click(); + const sidebarContextMenu = page.getByTestId('tooltip'); + await sidebarContextMenu.getByLabel('Start Component tests').click(); + + // Assert - Tests are running and reported + await expect(sidebarContextMenu.locator('#testing-module-description')).toContainText('Ran 10 test', { timeout: 30000 }); + // Assert - 1 failing test shows as a failed status + await expect(sidebarContextMenu.getByText('2 stories with errors')).toBeVisible(); + await expect(sidebarContextMenu.getByLabel('status: failed')).toHaveCount(1); + + await page.click('body'); + await expect(page.locator('#storybook-explorer-menu').getByRole('status', { name: 'Test status: success' })).toHaveCount(7); + await expect(page.locator('#storybook-explorer-menu').getByRole('status', { name: 'Test status: error' })).toHaveCount(1); + }); + + test("should run focused tests without coverage, even when enabled", async ({ + page, + browserName, + }) => { + test.skip(browserName !== "chromium", `Skipping tests for ${browserName}`); + // Arrange - Prepare Storybook + await setForceFailureFlag(false); + + const sbPage = new SbPage(page, expect); + await sbPage.navigateToStory("example/button", "CSF 3 Primary"); + + const expandButton = await page.getByLabel('Expand testing module') + await expandButton.click(); + + const storyElement = sbPage + .getCanvasBodyElement() + .getByRole("button", { name: "foo" }); + await expect(storyElement).toBeVisible({ timeout: 30000 }); + + // Act - Enable coverage + await page.getByLabel("Open settings for Component tests").click(); + await page.getByLabel("Coverage").click(); + await expect(page.getByText("Settings updated")).toBeVisible({ timeout: 3000 }); + await page.getByLabel("Close settings for Component tests").click(); + // Wait for Vitest to have (re)started + await page.waitForTimeout(2000); + + // Act - Open sidebar context menu and start focused test + await page.locator('[data-item-id="example-button--csf-3-primary"]').hover(); + await page.locator('[data-item-id="example-button--csf-3-primary"] div[data-testid="context-menu"] button').click(); + const sidebarContextMenu = page.getByTestId('tooltip'); + await sidebarContextMenu.getByLabel('Start Component tests').click(); + + // Arrange - Wait for test to finish and unfocus sidebar context menu + await expect(sidebarContextMenu.locator('#testing-module-description')).toContainText('Ran 1 test', { timeout: 30000 }); + await page.click('body'); + + // Assert - Coverage is not shown because Focused Tests shouldn't collect coverage + await expect(page.getByLabel("Open coverage report")).not.toBeVisible(); + + // Act - Run ALL tests + await page.getByLabel("Start Component tests").click(); + + // Arrange - Wait for tests to finish + await expect(page.locator('#testing-module-description')).toContainText(/Ran \d{2,} tests/, { timeout: 30000 }); + + // Assert - Coverage percentage is now collected and shown because running all tests automatically re-enables coverage + await expect(page.getByLabel("Open coverage report")).toBeVisible({ timeout: 30000 }); + const sbPercentageText = await page.getByLabel(/percent coverage$/).textContent(); + expect(sbPercentageText).toMatch(/^\d+\s%$/); + const sbPercentage = Number.parseInt(sbPercentageText!.replace(' %', '') ?? ''); + expect(sbPercentage).toBeGreaterThanOrEqual(0); + expect(sbPercentage).toBeLessThanOrEqual(100); + }); + }); diff --git a/test-storybooks/portable-stories-kitchen-sink/react/package.json b/test-storybooks/portable-stories-kitchen-sink/react/package.json index 8f392f7f1add..383364e5909a 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/package.json +++ b/test-storybooks/portable-stories-kitchen-sink/react/package.json @@ -12,8 +12,8 @@ "playwright-ct": "playwright test -c playwright-ct.config.ts", "playwright-e2e": "playwright test -c playwright-e2e.config.ts", "preview": "vite preview", - "storybook": "storybook dev -p 6006", - "vitest": "echo 'not running'" + "storybook": "NODE_OPTIONS=\"--preserve-symlinks --preserve-symlinks-main\" storybook dev -p 6006", + "vitest": "SKIP_FAIL_ON_PURPOSE=true vitest run" }, "resolutions": { "@playwright/test": "1.48.1", @@ -110,6 +110,8 @@ "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react": "^4.2.1", "@vitest/browser": "^2.1.3", + "@vitest/coverage-v8": "^2.1.3", + "@vitest/ui": "^2.1.3", "cypress": "^13.6.4", "eslint": "^8.56.0", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/test-storybooks/portable-stories-kitchen-sink/react/stories/AddonTest.stories.tsx b/test-storybooks/portable-stories-kitchen-sink/react/stories/AddonTest.stories.tsx index 365ed4da0e6b..650b091b33cb 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/stories/AddonTest.stories.tsx +++ b/test-storybooks/portable-stories-kitchen-sink/react/stories/AddonTest.stories.tsx @@ -1,24 +1,28 @@ -import { Meta } from '@storybook/react' +import { expect } from '@storybook/test'; +import { Meta, type StoryObj } from '@storybook/react' import { instrument } from '@storybook/instrumenter' -import type { StoryAnnotations } from 'storybook/internal/types'; declare global { - // eslint-disable-next-line no-var, @typescript-eslint/naming-convention + // eslint-disable-next-line no-var var __vitest_browser__: boolean; } const Component = () => -export default { - title: 'Addons/Test', +const meta = { + title: 'Addons/Group/Test', component: Component, } as Meta; +export default meta; + +type Story = StoryObj; + const { pass } = instrument({ pass: async () => {}, }, { intercept: true }) -export const ExpectedFailure = { +export const ExpectedFailure: Story = { args: { forceFailure: false, }, @@ -28,34 +32,61 @@ export const ExpectedFailure = { throw new Error('Expected failure'); } } -} satisfies StoryAnnotations; +}; -export const ExpectedSuccess = { +export const ExpectedSuccess: Story = { play: async () => { await pass(); } -} satisfies StoryAnnotations; +}; -export const LongRunning = { +export const LongRunning: Story = { loaders: [async () => new Promise((resolve) => setTimeout(resolve, 800))], -} satisfies StoryAnnotations; +}; // Tests will pass in browser, but fail in CLI -export const MismatchFailure = { +export const MismatchFailure: Story = { play: async () => { await pass(); if(!globalThis.__vitest_browser__) { throw new Error('Expected failure'); } } -} satisfies StoryAnnotations; +}; // Tests will fail in browser, but pass in CLI -export const MismatchSuccess = { +export const MismatchSuccess: Story = { play: async () => { await pass(); if(globalThis.__vitest_browser__) { throw new Error('Unexpected success'); } + }, + tags: ['fail-on-purpose'], +}; + +export const PreviewHeadTest: Story = { + play: async () => { + const styles = window.getComputedStyle(document.body); + // set in preview-head.html + expect(styles.backgroundColor).toBe('rgb(250, 250, 210)'); + // set in main.js#previewHead + expect(styles.borderColor).toBe('rgb(255, 0, 0)'); } -} satisfies StoryAnnotations; \ No newline at end of file +}; + +export const StaticDirTest: Story = { + play: async () => { + const path = '/test-static-dirs/static.js'; + const { staticFunction } = await import(/* @vite-ignore */path); + expect(staticFunction()).toBe(true); + } +} + +export const ViteFinalTest: Story = { + play: async () => { + // @ts-expect-error TS doesn't know about the alias + const { aliasedFunction } = await import('test-alias'); + expect(aliasedFunction()).toBe(true); + } +} diff --git a/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.playwright.tsx b/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.playwright.tsx index db4590c82fab..ee201e587159 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.playwright.tsx +++ b/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.playwright.tsx @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ + import { createTest } from '@storybook/react/experimental-playwright'; import { test as base, expect } from '@playwright/experimental-ct-react'; import stories, { SingleComposedStory, WithSpanishGlobal } from './Button.stories.playwright'; diff --git a/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.stories.tsx b/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.stories.tsx index 9d2cf8230964..2c976b43cc43 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.stories.tsx +++ b/test-storybooks/portable-stories-kitchen-sink/react/stories/Button.stories.tsx @@ -67,6 +67,8 @@ export const CSF3Primary: CSF3Story = { size: 'large', primary: true, }, + // Accessibility is failing for the Button + tags: ['fail-on-purpose'], }; export const CSF3Button: CSF3Story = { diff --git a/test-storybooks/portable-stories-kitchen-sink/react/stories/OtherComponent.stories.tsx b/test-storybooks/portable-stories-kitchen-sink/react/stories/OtherComponent.stories.tsx new file mode 100644 index 000000000000..dd410fe9c748 --- /dev/null +++ b/test-storybooks/portable-stories-kitchen-sink/react/stories/OtherComponent.stories.tsx @@ -0,0 +1,22 @@ +import { Meta, type StoryObj } from '@storybook/react' + +const Component = () => + +const meta = { + title: 'Addons/Group/Other', + component: Component, +} as Meta; + +export default meta; + +type Story = StoryObj; + +export const Passes: Story = { +}; + +export const Fails: Story = { + play: async () => { + throw new Error('Expected failure'); + }, + tags: ['fail-on-purpose'], +}; diff --git a/test-storybooks/portable-stories-kitchen-sink/react/vitest.workspace.ts b/test-storybooks/portable-stories-kitchen-sink/react/vitest.workspace.ts index 041918fb126d..effd954bd780 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/vitest.workspace.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react/vitest.workspace.ts @@ -5,7 +5,11 @@ export default defineWorkspace([ { extends: "vite.config.ts", plugins: [ - storybookTest(), + storybookTest(process.env.SKIP_FAIL_ON_PURPOSE ? { + tags: { + exclude: ["fail-on-purpose"], + } + } : undefined), ], test: { name: "storybook", diff --git a/test-storybooks/portable-stories-kitchen-sink/react/yarn.lock b/test-storybooks/portable-stories-kitchen-sink/react/yarn.lock index e3484dc01721..b8242119352f 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/yarn.lock +++ b/test-storybooks/portable-stories-kitchen-sink/react/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -135,6 +135,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 10/c28656c52bd48e8c1d9f3e8e68ecafd09d949c57755b0d353739eb4eae7ba4f7e67e92e4036f1cd43378cc1397a2c943ed7bcaf5949b04ab48607def0258b775 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.25.7": version: 7.25.7 resolution: "@babel/helper-validator-identifier@npm:7.25.7" @@ -142,6 +149,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 10/3f9b649be0c2fd457fa1957b694b4e69532a668866b8a0d81eabfa34ba16dbf3107b39e0e7144c55c3c652bf773ec816af8df4a61273a2bb4eb3145ca9cf478e + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.25.7": version: 7.25.7 resolution: "@babel/helper-validator-option@npm:7.25.7" @@ -182,6 +196,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.25.4": + version: 7.26.2 + resolution: "@babel/parser@npm:7.26.2" + dependencies: + "@babel/types": "npm:^7.26.0" + bin: + parser: ./bin/babel-parser.js + checksum: 10/8baee43752a3678ad9f9e360ec845065eeee806f1fdc8e0f348a8a0e13eef0959dabed4a197c978896c493ea205c804d0a1187cc52e4a1ba017c7935bab4983d + languageName: node + linkType: hard + "@babel/plugin-syntax-async-generators@npm:^7.8.4": version: 7.8.4 resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" @@ -437,6 +462,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.25.4, @babel/types@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + checksum: 10/40780741ecec886ed9edae234b5eb4976968cc70d72b4e5a40d55f83ff2cc457de20f9b0f4fe9d858350e43dab0ea496e7ef62e2b2f08df699481a76df02cd6e + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -444,12 +479,12 @@ __metadata: languageName: node linkType: hard -"@bundled-es-modules/cookie@npm:^2.0.0": - version: 2.0.0 - resolution: "@bundled-es-modules/cookie@npm:2.0.0" +"@bundled-es-modules/cookie@npm:^2.0.1": + version: 2.0.1 + resolution: "@bundled-es-modules/cookie@npm:2.0.1" dependencies: - cookie: "npm:^0.5.0" - checksum: 10/c8ef02aa5d3f6c786cfa407e1c93b4af29c600eb09990973f47a7a49e4771c1bec37c8f8e567638bb9cbc41f4e38d065ff1d8eaf9bf91f0c3613a6d60bc82c8c + cookie: "npm:^0.7.2" + checksum: 10/0038a5e82c41bfcd722afedabeb6961a5f15747b3681d7f4b61e35eb1e33130039e10ee9250dc9c9e4d3915ce1aeee717c0fb92225111574f0a030411abc0987 languageName: node linkType: hard @@ -911,58 +946,48 @@ __metadata: languageName: node linkType: hard -"@inquirer/confirm@npm:^3.0.0": - version: 3.2.0 - resolution: "@inquirer/confirm@npm:3.2.0" +"@inquirer/confirm@npm:^5.0.0": + version: 5.0.2 + resolution: "@inquirer/confirm@npm:5.0.2" dependencies: - "@inquirer/core": "npm:^9.1.0" - "@inquirer/type": "npm:^1.5.3" - checksum: 10/6b032a26c64075dc14769558720b17f09bc6784a223bbf2c85ec42e491be6ce4c4b83518433c47e05d7e8836ba680ab1b2f6b9c553410d4326582308a1fd2259 + "@inquirer/core": "npm:^10.1.0" + "@inquirer/type": "npm:^3.0.1" + peerDependencies: + "@types/node": ">=18" + checksum: 10/4e775b80b689adeb0b2852ed79b368ef23a82fe3d5f580a562f4af7cdf002a19e0ec1b3b95acc6d49427a72c0fcb5b6548e0cdcafe2f0d3f3d6a923e04aabd0c languageName: node linkType: hard -"@inquirer/core@npm:^9.1.0": - version: 9.2.1 - resolution: "@inquirer/core@npm:9.2.1" +"@inquirer/core@npm:^10.1.0": + version: 10.1.0 + resolution: "@inquirer/core@npm:10.1.0" dependencies: - "@inquirer/figures": "npm:^1.0.6" - "@inquirer/type": "npm:^2.0.0" - "@types/mute-stream": "npm:^0.0.4" - "@types/node": "npm:^22.5.5" - "@types/wrap-ansi": "npm:^3.0.0" + "@inquirer/figures": "npm:^1.0.8" + "@inquirer/type": "npm:^3.0.1" ansi-escapes: "npm:^4.3.2" cli-width: "npm:^4.1.0" - mute-stream: "npm:^1.0.0" + mute-stream: "npm:^2.0.0" signal-exit: "npm:^4.1.0" strip-ansi: "npm:^6.0.1" wrap-ansi: "npm:^6.2.0" yoctocolors-cjs: "npm:^2.1.2" - checksum: 10/bf35e46e70add8ffa9e9d4ae6b528ac660484afca082bca31af95ce8a145a2f8c8d0d07cc7a8627771452e68ade9849c9c9c450a004133ed10ac2d6730900452 + checksum: 10/5d097d0484c1b758f788b792d29395199bdc84af3e8cd4d9273e31de2c5202839b6edf299056956044ba7fb097c4cee7b5c0288e094a380c045082b044f9946e languageName: node linkType: hard -"@inquirer/figures@npm:^1.0.6": - version: 1.0.7 - resolution: "@inquirer/figures@npm:1.0.7" - checksum: 10/ce896860de9d822a7c2a212667bcfd0f04cf2ce86d9a2411cc9c077bb59cd61732cb5f72ac66e88d52912466eec433f005bf8a25efa658f41e1a32f3977080bd - languageName: node - linkType: hard - -"@inquirer/type@npm:^1.5.3": - version: 1.5.5 - resolution: "@inquirer/type@npm:1.5.5" - dependencies: - mute-stream: "npm:^1.0.0" - checksum: 10/bd3f3d7510785af4ad599e042e99e4be6380f52f79f3db140fe6fed0a605acf27b1a0a20fb5cc688eaf7b8aa0c36dacb1d89c7bba4586f38cbf58ba9f159e7b5 +"@inquirer/figures@npm:^1.0.8": + version: 1.0.8 + resolution: "@inquirer/figures@npm:1.0.8" + checksum: 10/0e5e4fbb15e799e818c598fcc3558ef076daf78662149711b046723fd6316381e95f7d5573d6ef0062095ad22c6ac98833033f0948df5c722932107a567fd9c3 languageName: node linkType: hard -"@inquirer/type@npm:^2.0.0": - version: 2.0.0 - resolution: "@inquirer/type@npm:2.0.0" - dependencies: - mute-stream: "npm:^1.0.0" - checksum: 10/e85f359866c28cce06272d2d51cc17788a5c9de9fda7f181c27775dd26821de0dacbc947b521cfe2009cd2965ec54696799035ef3a25a9a5794e47d8e8bdf794 +"@inquirer/type@npm:^3.0.1": + version: 3.0.1 + resolution: "@inquirer/type@npm:3.0.1" + peerDependencies: + "@types/node": ">=18" + checksum: 10/af412f1e7541d43554b02199ae71a2039a1bff5dc51ceefd87de9ece55b199682733b28810fb4b6cb3ed4a159af4cc4a26d4bb29c58dd127e7d9dbda0797d8e7 languageName: node linkType: hard @@ -1287,7 +1312,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -1309,9 +1334,9 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.35.8": - version: 0.35.9 - resolution: "@mswjs/interceptors@npm:0.35.9" +"@mswjs/interceptors@npm:^0.37.0": + version: 0.37.3 + resolution: "@mswjs/interceptors@npm:0.37.3" dependencies: "@open-draft/deferred-promise": "npm:^2.2.0" "@open-draft/logger": "npm:^0.3.0" @@ -1319,7 +1344,7 @@ __metadata: is-node-process: "npm:^1.2.0" outvariant: "npm:^1.4.3" strict-event-emitter: "npm:^0.5.1" - checksum: 10/9eaf8d7876c9a38c2c9a1259873f8ad27ab41c68a49f7e14a55cd9f596458d9232adb85a5084b044d4eead3be1e7ef5bf54ed6d774d16b02d96caf1e7faa2ab3 + checksum: 10/3d3e2e073feead8702c18dc97e5201785865292b32bd882c4d80461adc3380483b33517c55d7c6c1e53723f5e2ecf50cca0412e6ecd2eb771f4eaabfa2138932 languageName: node linkType: hard @@ -1780,11 +1805,11 @@ __metadata: linkType: soft "@storybook/components@file:../../../code/deprecated/components::locator=portable-stories-react%40workspace%3A.": - version: 8.5.0-alpha.18 - resolution: "@storybook/components@file:../../../code/deprecated/components#../../../code/deprecated/components::hash=aad2fe&locator=portable-stories-react%40workspace%3A." + version: 8.5.0-alpha.20 + resolution: "@storybook/components@file:../../../code/deprecated/components#../../../code/deprecated/components::hash=40954d&locator=portable-stories-react%40workspace%3A." peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/44d4a8a54fd32d94b03dc9f29e2d68ca3c37156b56055b94493f5f626786a02349c195859c48b4f8fa25e209ce12f385305d601135f7e63bdc4541fa0645cae5 + checksum: 10/ff9107e9c84c5d522a0067f77e217a9963c4bdde27032fdd38efae906f67df7b65488969a9cee89715d49fa89213fe04a72af825ac118e72e835f4be648409ff languageName: node linkType: hard @@ -1840,15 +1865,14 @@ __metadata: linkType: hard "@storybook/experimental-addon-test@file:../../../code/addons/test::locator=portable-stories-react%40workspace%3A.": - version: 8.5.0-alpha.18 - resolution: "@storybook/experimental-addon-test@file:../../../code/addons/test#../../../code/addons/test::hash=21369f&locator=portable-stories-react%40workspace%3A." + version: 8.5.0-alpha.20 + resolution: "@storybook/experimental-addon-test@file:../../../code/addons/test#../../../code/addons/test::hash=1aa098&locator=portable-stories-react%40workspace%3A." dependencies: "@storybook/csf": "npm:0.1.12" "@storybook/global": "npm:^5.0.0" "@storybook/icons": "npm:^1.2.12" "@storybook/instrumenter": "workspace:*" "@storybook/test": "workspace:*" - "@storybook/theming": "workspace:*" polished: "npm:^4.2.2" prompts: "npm:^2.4.0" ts-dedent: "npm:^2.2.0" @@ -1864,7 +1888,7 @@ __metadata: optional: true vitest: optional: true - checksum: 10/2081814e214dc1dd31144870a6a4ea7637c9c241ab02044488be57e19402c206c0037d449197f77bb4262147703f6d0b27f09c9f6cc2ee358c97fd7d1cdfa908 + checksum: 10/42188bb3814cae7c04df03c75994f8df971cc2ce71bda9e536211b96468bbdf2b8babc78526fdec1b2ddbd4d703118474f23c31f2bddffb6fa8947dc35ef0f19 languageName: node linkType: hard @@ -1897,20 +1921,20 @@ __metadata: linkType: soft "@storybook/manager-api@file:../../../code/deprecated/manager-api::locator=portable-stories-react%40workspace%3A.": - version: 8.5.0-alpha.18 - resolution: "@storybook/manager-api@file:../../../code/deprecated/manager-api#../../../code/deprecated/manager-api::hash=c1892e&locator=portable-stories-react%40workspace%3A." + version: 8.5.0-alpha.20 + resolution: "@storybook/manager-api@file:../../../code/deprecated/manager-api#../../../code/deprecated/manager-api::hash=92b213&locator=portable-stories-react%40workspace%3A." peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/405745f48728bfa4d8340fe2403bca0d60f803ed346c12d20a63ab9472ba1d8d1021aa12ee0fd36a6b41aec42d8c2a657acffeb9c8663aa32edcda490882e7f5 + checksum: 10/c63e624ab2d90f2992ecb2a650d9e54ace0f7f699d425bc68f616f870651a2b5f3c6c7d66be84aaab9200a9f01686376a7532f905f0dbd4dddb5542afe855584 languageName: node linkType: hard "@storybook/preview-api@file:../../../code/deprecated/preview-api::locator=portable-stories-react%40workspace%3A.": - version: 8.5.0-alpha.18 - resolution: "@storybook/preview-api@file:../../../code/deprecated/preview-api#../../../code/deprecated/preview-api::hash=0085a8&locator=portable-stories-react%40workspace%3A." + version: 8.5.0-alpha.20 + resolution: "@storybook/preview-api@file:../../../code/deprecated/preview-api#../../../code/deprecated/preview-api::hash=b70449&locator=portable-stories-react%40workspace%3A." peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/29c5f7134b4300bac03c42f57c3138e24315516b23515893cfb4a144786327fb6e0a90d5470d951eb22e055466769fc9ad4577658afc7da43b60870c0d06e767 + checksum: 10/3251de34aca72eb6c82b7aa8fde6e877e0974294d97eb60f63819b890b399cd7703a4dfde151180cf81918b36b3523bdbafe0731d232bda7d77c9f3b8fc5b75b languageName: node linkType: hard @@ -1991,11 +2015,11 @@ __metadata: linkType: soft "@storybook/theming@file:../../../code/deprecated/theming::locator=portable-stories-react%40workspace%3A.": - version: 8.5.0-alpha.18 - resolution: "@storybook/theming@file:../../../code/deprecated/theming#../../../code/deprecated/theming::hash=dd5360&locator=portable-stories-react%40workspace%3A." + version: 8.5.0-alpha.20 + resolution: "@storybook/theming@file:../../../code/deprecated/theming#../../../code/deprecated/theming::hash=db0fbd&locator=portable-stories-react%40workspace%3A." peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/8f8ecbd709ff4a8e0bafa19642497aad0d6ee40f2e613793a4248cb3825765783dd40eb57d180cb6cc4ad1f8acbd4e4a1a1b3448245b89e28581e25289c88c86 + checksum: 10/de77ed744ce172b1007cf94b4b5ff1cf9cf8492d4ddb9ac1ca61d76b18ed73f76e911c1518c1b66ba37c8d2d4e0f63f2eb3bddc64cd0beb7d64f952a45f9b8b7 languageName: node linkType: hard @@ -2356,16 +2380,7 @@ __metadata: languageName: node linkType: hard -"@types/mute-stream@npm:^0.0.4": - version: 0.0.4 - resolution: "@types/mute-stream@npm:0.0.4" - dependencies: - "@types/node": "npm:*" - checksum: 10/af8d83ad7b68ea05d9357985daf81b6c9b73af4feacb2f5c2693c7fd3e13e5135ef1bd083ce8d5bdc8e97acd28563b61bb32dec4e4508a8067fcd31b8a098632 - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^22.5.5": +"@types/node@npm:*": version: 22.7.7 resolution: "@types/node@npm:22.7.7" dependencies: @@ -2456,13 +2471,6 @@ __metadata: languageName: node linkType: hard -"@types/wrap-ansi@npm:^3.0.0": - version: 3.0.0 - resolution: "@types/wrap-ansi@npm:3.0.0" - checksum: 10/8aa644946ca4e859668c36b8e2bcf2ac4bdee59dac760414730ea57be8a93ae9166ebd40a088f2ab714843aaea2a2a67f0e6e6ec11cfc9c8701b2466ca1c4089 - languageName: node - linkType: hard - "@types/yargs-parser@npm:*": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -2697,21 +2705,21 @@ __metadata: linkType: hard "@vitest/browser@npm:^2.1.3": - version: 2.1.3 - resolution: "@vitest/browser@npm:2.1.3" + version: 2.1.8 + resolution: "@vitest/browser@npm:2.1.8" dependencies: "@testing-library/dom": "npm:^10.4.0" "@testing-library/user-event": "npm:^14.5.2" - "@vitest/mocker": "npm:2.1.3" - "@vitest/utils": "npm:2.1.3" - magic-string: "npm:^0.30.11" - msw: "npm:^2.3.5" - sirv: "npm:^2.0.4" + "@vitest/mocker": "npm:2.1.8" + "@vitest/utils": "npm:2.1.8" + magic-string: "npm:^0.30.12" + msw: "npm:^2.6.4" + sirv: "npm:^3.0.0" tinyrainbow: "npm:^1.2.0" ws: "npm:^8.18.0" peerDependencies: playwright: "*" - vitest: 2.1.3 + vitest: 2.1.8 webdriverio: "*" peerDependenciesMeta: playwright: @@ -2720,7 +2728,33 @@ __metadata: optional: true webdriverio: optional: true - checksum: 10/e639496fa529140fb9e7dce97890c5b75fffbfb41881bee5ef25b194832d3cadcb77490d9b54777bfa968b993f6878649fe4961d6ef312ca1222b9a2fc8d4f12 + checksum: 10/6063e02222440347bbc23b2c54e259078aa83a29869337b9ffd642be5a4321ac3ddf3c0bbe4eac5237eb0bb8b9fa17d21d2c31299376de407716e3c7dd3b704c + languageName: node + linkType: hard + +"@vitest/coverage-v8@npm:^2.1.3": + version: 2.1.8 + resolution: "@vitest/coverage-v8@npm:2.1.8" + dependencies: + "@ampproject/remapping": "npm:^2.3.0" + "@bcoe/v8-coverage": "npm:^0.2.3" + debug: "npm:^4.3.7" + istanbul-lib-coverage: "npm:^3.2.2" + istanbul-lib-report: "npm:^3.0.1" + istanbul-lib-source-maps: "npm:^5.0.6" + istanbul-reports: "npm:^3.1.7" + magic-string: "npm:^0.30.12" + magicast: "npm:^0.3.5" + std-env: "npm:^3.8.0" + test-exclude: "npm:^7.0.1" + tinyrainbow: "npm:^1.2.0" + peerDependencies: + "@vitest/browser": 2.1.8 + vitest: 2.1.8 + peerDependenciesMeta: + "@vitest/browser": + optional: true + checksum: 10/2e1e7fe2a20c1eec738f6d84d890bed4aa5138094943dd1229962c2c42428a1a517c8a4ad4fb52637d7494f044440e061e9bc5982a83df95223db185d5a28f4d languageName: node linkType: hard @@ -2736,35 +2770,34 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/expect@npm:2.1.3" +"@vitest/expect@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/expect@npm:2.1.8" dependencies: - "@vitest/spy": "npm:2.1.3" - "@vitest/utils": "npm:2.1.3" - chai: "npm:^5.1.1" + "@vitest/spy": "npm:2.1.8" + "@vitest/utils": "npm:2.1.8" + chai: "npm:^5.1.2" tinyrainbow: "npm:^1.2.0" - checksum: 10/94e61e01f14cfcd9ced0e7ac1bbdeee55ff4bf68f09d8f244fd7d73f97b106f35d10cba3fe7a0132464c312206f2eee9e83b16a8d761101b61da053890062858 + checksum: 10/3594149dd67dfac884a90f8b6a35687cdddd2f5f764562819bf7b66ae2eacfd4aa5e8914155deb4082fbe5a3792dced2fd7e59a948ffafe67acba4d2229dfe5f languageName: node linkType: hard -"@vitest/mocker@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/mocker@npm:2.1.3" +"@vitest/mocker@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/mocker@npm:2.1.8" dependencies: - "@vitest/spy": "npm:2.1.3" + "@vitest/spy": "npm:2.1.8" estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.11" + magic-string: "npm:^0.30.12" peerDependencies: - "@vitest/spy": 2.1.3 - msw: ^2.3.5 + msw: ^2.4.9 vite: ^5.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - checksum: 10/84be8830d6e965109730257d7a84b3d7594db0998ae55decdbfc304857c1c7d29b49f1f5b23f2addcbce1bd7e8bb33832407737a9bb3f95cb3bf7bb312db4d9d + checksum: 10/f04060f42102caa4cca72059e63c1ecae8b8e091aaa61a2d4a914b129fc711ada4ad117eb0184e49e363757784ed1117fdbf9f4a81a45fe575fd92769740a970 languageName: node linkType: hard @@ -2777,33 +2810,33 @@ __metadata: languageName: node linkType: hard -"@vitest/pretty-format@npm:2.1.3, @vitest/pretty-format@npm:^2.1.3": - version: 2.1.3 - resolution: "@vitest/pretty-format@npm:2.1.3" +"@vitest/pretty-format@npm:2.1.8, @vitest/pretty-format@npm:^2.1.8": + version: 2.1.8 + resolution: "@vitest/pretty-format@npm:2.1.8" dependencies: tinyrainbow: "npm:^1.2.0" - checksum: 10/d9382ee93f0f32e2ef8fe03bda818e5277f052a50ddb05b6a6cf0864b2ccb228484f12f130c05faf62dc2140292ffafc213f2941b0fa24058b3ee2943daa286c + checksum: 10/f0f60c007424194887ad398d202867d58d850154de327993925041e2972357544eea95a22e0bb3a62a470b006ff8de5f691d2078708dcd7f625e24f8a06b26e7 languageName: node linkType: hard -"@vitest/runner@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/runner@npm:2.1.3" +"@vitest/runner@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/runner@npm:2.1.8" dependencies: - "@vitest/utils": "npm:2.1.3" + "@vitest/utils": "npm:2.1.8" pathe: "npm:^1.1.2" - checksum: 10/cdf9b82d388c1cc148753f4a8632dfcadf9c4a1c0e065fdcd485d5af824af62507fd7eab9efb21244009775c05773ccb59547043af522a5ab6d216433321066e + checksum: 10/27f265a3ab1e20297b948b06232bfa4dc9fda44d1f9bb6206baa9e6fa643b71143ebfd2d1771570296b7ee74a12d684e529a830f545ad61235cefb454e94a8e9 languageName: node linkType: hard -"@vitest/snapshot@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/snapshot@npm:2.1.3" +"@vitest/snapshot@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/snapshot@npm:2.1.8" dependencies: - "@vitest/pretty-format": "npm:2.1.3" - magic-string: "npm:^0.30.11" + "@vitest/pretty-format": "npm:2.1.8" + magic-string: "npm:^0.30.12" pathe: "npm:^1.1.2" - checksum: 10/2c0c4ad8abb758f2f76d1d6094f8928360437e09d0a59e0c6a85a544c892cc41a5324ebbc5657a66c8a3793e51cbf58e357c7f71e899f4e5c5eb76e8c9745abf + checksum: 10/71edf4f574d317579c605ed0a7ecab7ee96fddcebc777bd130774a770ddc692c538f9f5b3dfde89af83ecb36f7338fe880943c83cede58f55e3556768a1a0749 languageName: node linkType: hard @@ -2816,12 +2849,29 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/spy@npm:2.1.3" +"@vitest/spy@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/spy@npm:2.1.8" dependencies: - tinyspy: "npm:^3.0.0" - checksum: 10/94d6f1bc34da5d0c973d9382c133b938e555fcf2d238edf0aaad3de1a98dd57ebf7c104ba229c6beec48122d2e6f55386d8d2cf96a5804dc95ac683a54754cc7 + tinyspy: "npm:^3.0.2" + checksum: 10/9a1cb9cf6b23c122681469b5890d91ca26fc8d74953b3d46d293a5d2a4944490106891f6a178cd732ab7a8abbda339f43681c81d1594565ecc3bf3e7f9b7735f + languageName: node + linkType: hard + +"@vitest/ui@npm:^2.1.3": + version: 2.1.8 + resolution: "@vitest/ui@npm:2.1.8" + dependencies: + "@vitest/utils": "npm:2.1.8" + fflate: "npm:^0.8.2" + flatted: "npm:^3.3.1" + pathe: "npm:^1.1.2" + sirv: "npm:^3.0.0" + tinyglobby: "npm:^0.2.10" + tinyrainbow: "npm:^1.2.0" + peerDependencies: + vitest: 2.1.8 + checksum: 10/7ff0532b3b0e3f93c037cad3528b8fde8a93188f3222b92faae42e0fdd996e9284b362c4e5e9d725ce0a019870d3b0b7ad80c1874f74b43ffc5a1d703803fdd8 languageName: node linkType: hard @@ -2837,14 +2887,14 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:2.1.3, @vitest/utils@npm:^2.1.1": - version: 2.1.3 - resolution: "@vitest/utils@npm:2.1.3" +"@vitest/utils@npm:2.1.8, @vitest/utils@npm:^2.1.1": + version: 2.1.8 + resolution: "@vitest/utils@npm:2.1.8" dependencies: - "@vitest/pretty-format": "npm:2.1.3" - loupe: "npm:^3.1.1" + "@vitest/pretty-format": "npm:2.1.8" + loupe: "npm:^3.1.2" tinyrainbow: "npm:^1.2.0" - checksum: 10/f064e6634cb84c925a17d8937df7441d150c3e24fa5bbd6304151d11dab6cdeb0cb3d5a95a9aacb8b416c87fb0d9aa8c6b9cc5e174191784231e8345948d6d18 + checksum: 10/be1f4254347199fb5c1d9de8e4537dad4af3f434c033e7cd023165bd4b7e9de16fa0f86664256ab331120585df95ed6be8eea58b209b510651b49f6482051733 languageName: node linkType: hard @@ -3455,16 +3505,16 @@ __metadata: languageName: node linkType: hard -"chai@npm:^5.1.1": - version: 5.1.1 - resolution: "chai@npm:5.1.1" +"chai@npm:^5.1.1, chai@npm:^5.1.2": + version: 5.1.2 + resolution: "chai@npm:5.1.2" dependencies: assertion-error: "npm:^2.0.1" check-error: "npm:^2.1.1" deep-eql: "npm:^5.0.1" loupe: "npm:^3.1.0" pathval: "npm:^2.0.0" - checksum: 10/ee67279a5613bd36dc1dc13660042429ae2f1dc5a9030a6abcf381345866dfb5bce7bc10b9d74c8de86b6f656489f654bbbef3f3361e06925591e6a00c72afff + checksum: 10/e8c2bbc83cb5a2f87130d93056d4cfbbe04106e12aa798b504816dbe3fa538a9f68541b472e56cbf0f54558b501d7e31867d74b8218abcd5a8cc8ba536fba46c languageName: node linkType: hard @@ -3695,10 +3745,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:^0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 10/aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 +"cookie@npm:^0.7.2": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10/24b286c556420d4ba4e9bc09120c9d3db7d28ace2bd0f8ccee82422ce42322f73c8312441271e5eefafbead725980e5996cc02766dbb89a90ac7f5636ede608f languageName: node linkType: hard @@ -3853,7 +3903,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.6": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.7": version: 4.3.7 resolution: "debug@npm:4.3.7" dependencies: @@ -4174,6 +4224,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.5.4": + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: 10/f29c7c97a58eb17640dcbd71bd6ef754ad4f58f95c3073894573d29dae2cad43ecd2060d97ed5b866dfb7804d5590fb7de1d2c5339a5fceae8bd60b580387fc5 + languageName: node + linkType: hard + "esbuild-register@npm:^3.5.0": version: 3.6.0 resolution: "esbuild-register@npm:3.6.0" @@ -4634,6 +4691,13 @@ __metadata: languageName: node linkType: hard +"expect-type@npm:^1.1.0": + version: 1.1.0 + resolution: "expect-type@npm:1.1.0" + checksum: 10/05fca80ddc7d493a89361f783c6b000750fa04a8226bc24701f3b90adb0efc2fb467f2a0baaed4015a02d8b9034ef5bb87521df9dba980f50b1105bd596ef833 + languageName: node + linkType: hard + "expect@npm:^29.7.0": version: 29.7.0 resolution: "expect@npm:29.7.0" @@ -4753,6 +4817,25 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.2": + version: 6.4.2 + resolution: "fdir@npm:6.4.2" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10/5ff80d1d2034e75cc68be175401c9f64c4938a6b2c1e9a0c27f2d211ffbe491fd86d29e4576825d9da8aff9bd465f0283427c2dddc11653457906c46d3bbc448 + languageName: node + linkType: hard + +"fflate@npm:^0.8.2": + version: 0.8.2 + resolution: "fflate@npm:0.8.2" + checksum: 10/2bd26ba6d235d428de793c6a0cd1aaa96a06269ebd4e21b46c8fd1bd136abc631acf27e188d47c3936db090bf3e1ede11d15ce9eae9bffdc4bfe1b9dc66ca9cb + languageName: node + linkType: hard + "figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -4818,6 +4901,13 @@ __metadata: languageName: node linkType: hard +"flatted@npm:^3.3.1": + version: 3.3.2 + resolution: "flatted@npm:3.3.2" + checksum: 10/ac3c159742e01d0e860a861164bcfd35bb567ccbebb8a0dd041e61cf3c64a435b917dd1e7ed1c380c2ebca85735fb16644485ec33665bc6aafc3b316aa1eed44 + languageName: node + linkType: hard + "for-each@npm:^0.3.3": version: 0.3.3 resolution: "for-each@npm:0.3.3" @@ -5030,7 +5120,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10": +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.4.1": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -5726,7 +5816,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" checksum: 10/40bbdd1e937dfd8c830fa286d0f665e81b7a78bdabcd4565f6d5667c99828bda3db7fb7ac6b96a3e2e8a2461ddbc5452d9f8bc7d00cb00075fa6a3e99f5b6a81 @@ -5759,7 +5849,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-report@npm:^3.0.0": +"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": version: 3.0.1 resolution: "istanbul-lib-report@npm:3.0.1" dependencies: @@ -5781,7 +5871,18 @@ __metadata: languageName: node linkType: hard -"istanbul-reports@npm:^3.1.3": +"istanbul-lib-source-maps@npm:^5.0.6": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + checksum: 10/569dd0a392ee3464b1fe1accbaef5cc26de3479eacb5b91d8c67ebb7b425d39fd02247d85649c3a0e9c29b600809fa60b5af5a281a75a89c01f385b1e24823a2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3, istanbul-reports@npm:^3.1.7": version: 3.1.7 resolution: "istanbul-reports@npm:3.1.7" dependencies: @@ -6593,7 +6694,7 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^3.1.0, loupe@npm:^3.1.1": +"loupe@npm:^3.1.0, loupe@npm:^3.1.1, loupe@npm:^3.1.2": version: 3.1.2 resolution: "loupe@npm:3.1.2" checksum: 10/8f5734e53fb64cd914aa7d986e01b6d4c2e3c6c56dcbd5428d71c2703f0ab46b5ab9f9eeaaf2b485e8a1c43f865bdd16ec08ae1a661c8f55acdbd9f4d59c607a @@ -6634,7 +6735,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.0, magic-string@npm:^0.30.11": +"magic-string@npm:^0.30.0": version: 0.30.12 resolution: "magic-string@npm:0.30.12" dependencies: @@ -6643,6 +6744,26 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.12": + version: 0.30.14 + resolution: "magic-string@npm:0.30.14" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: 10/8ca0f8937c2824e48ebc70e7e065a193c467713639cc6e5972aaba0fa5417b375a6f62c383410a19a66e618c386bb7253fbd3ccbfb0144bb310f0ba772121f12 + languageName: node + linkType: hard + +"magicast@npm:^0.3.5": + version: 0.3.5 + resolution: "magicast@npm:0.3.5" + dependencies: + "@babel/parser": "npm:^7.25.4" + "@babel/types": "npm:^7.25.4" + source-map-js: "npm:^1.2.0" + checksum: 10/3a2dba6b0bdde957797361d09c7931ebdc1b30231705360eeb40ed458d28e1c3112841c3ed4e1b87ceb28f741e333c7673cd961193aa9fdb4f4946b202e6205a + languageName: node + linkType: hard + "make-dir@npm:^4.0.0": version: 4.0.0 resolution: "make-dir@npm:4.0.0" @@ -6892,15 +7013,16 @@ __metadata: languageName: node linkType: hard -"msw@npm:^2.3.5": - version: 2.4.11 - resolution: "msw@npm:2.4.11" +"msw@npm:^2.6.4": + version: 2.6.6 + resolution: "msw@npm:2.6.6" dependencies: - "@bundled-es-modules/cookie": "npm:^2.0.0" + "@bundled-es-modules/cookie": "npm:^2.0.1" "@bundled-es-modules/statuses": "npm:^1.0.1" "@bundled-es-modules/tough-cookie": "npm:^0.1.6" - "@inquirer/confirm": "npm:^3.0.0" - "@mswjs/interceptors": "npm:^0.35.8" + "@inquirer/confirm": "npm:^5.0.0" + "@mswjs/interceptors": "npm:^0.37.0" + "@open-draft/deferred-promise": "npm:^2.2.0" "@open-draft/until": "npm:^2.1.0" "@types/cookie": "npm:^0.6.0" "@types/statuses": "npm:^2.0.4" @@ -6920,14 +7042,14 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: 10/d073ede4bfc7f1f41f7a0cb05b3d20d9befc1658e53faacd3f217a7cb78e3e748a3ee8e937e2a4d93fd09f16b35cba00d71df767736dd567ac15fd8e01aa7d6e + checksum: 10/7762ba5f1570789328af27167e03c2b8eb4981faa476ae47d74c125c90ddc1792bc28b9ce1100bbc4e105b55e3e7d65e7cae8d27fa7677b6516e42a63c38b7a3 languageName: node linkType: hard -"mute-stream@npm:^1.0.0": - version: 1.0.0 - resolution: "mute-stream@npm:1.0.0" - checksum: 10/36fc968b0e9c9c63029d4f9dc63911950a3bdf55c9a87f58d3a266289b67180201cade911e7699f8b2fa596b34c9db43dad37649e3f7fdd13c3bb9edb0017ee7 +"mute-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "mute-stream@npm:2.0.0" + checksum: 10/d2e4fd2f5aa342b89b98134a8d899d8ef9b0a6d69274c4af9df46faa2d97aeb1f2ce83d867880d6de63643c52386579b99139801e24e7526c3b9b0a6d1e18d6c languageName: node linkType: hard @@ -7298,6 +7420,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10/ce617b8da36797d09c0baacb96ca8a44460452c89362d7cb8f70ca46b4158ba8bc3606912de7c818eb4a939f7f9015cef3c766ec8a0c6bfc725fdc078e39c717 + languageName: node + linkType: hard + "pify@npm:^2.2.0": version: 2.3.0 resolution: "pify@npm:2.3.0" @@ -7380,6 +7509,8 @@ __metadata: "@typescript-eslint/parser": "npm:^6.21.0" "@vitejs/plugin-react": "npm:^4.2.1" "@vitest/browser": "npm:^2.1.3" + "@vitest/coverage-v8": "npm:^2.1.3" + "@vitest/ui": "npm:^2.1.3" cypress: "npm:^13.6.4" eslint: "npm:^8.56.0" eslint-plugin-react-hooks: "npm:^4.6.0" @@ -7991,14 +8122,14 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^2.0.4": - version: 2.0.4 - resolution: "sirv@npm:2.0.4" +"sirv@npm:^3.0.0": + version: 3.0.0 + resolution: "sirv@npm:3.0.0" dependencies: "@polka/url": "npm:^1.0.0-next.24" mrmime: "npm:^2.0.0" totalist: "npm:^3.0.0" - checksum: 10/24f42cf06895017e589c9d16fc3f1c6c07fe8b0dbafce8a8b46322cfba67b7f2498610183954cb0e9d089c8cb60002a7ee7e8bca6a91a0d7042bfbc3473c95c3 + checksum: 10/94dbd5df7cf4965f7c5941767117cbf9709e1d25de1d619a114c3f77fc63c124b5a5255717af2a0de637bb83d0b0defd0822d01420764b56432b53281b1d675d languageName: node linkType: hard @@ -8066,7 +8197,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.1": +"source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 @@ -8157,10 +8288,10 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.7.0": - version: 3.7.0 - resolution: "std-env@npm:3.7.0" - checksum: 10/6ee0cca1add3fd84656b0002cfbc5bfa20340389d9ba4720569840f1caa34bce74322aef4c93f046391583e50649d0cf81a5f8fe1d411e50b659571690a45f12 +"std-env@npm:^3.8.0": + version: 3.8.0 + resolution: "std-env@npm:3.8.0" + checksum: 10/034176196cfcaaab16dbdd96fc9e925a9544799fb6dc5a3e36fe43270f3a287c7f779d785b89edaf22cef2b5f1dcada2aae67430b8602e785ee74bdb3f671768 languageName: node linkType: hard @@ -8359,6 +8490,17 @@ __metadata: languageName: node linkType: hard +"test-exclude@npm:^7.0.1": + version: 7.0.1 + resolution: "test-exclude@npm:7.0.1" + dependencies: + "@istanbuljs/schema": "npm:^0.1.2" + glob: "npm:^10.4.1" + minimatch: "npm:^9.0.4" + checksum: 10/e6f6f4e1df2e7810e082e8d7dfc53be51a931e6e87925f5e1c2ef92cc1165246ba3bf2dae6b5d86251c16925683dba906bd41e40169ebc77120a2d1b5a0dbbe0 + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -8394,17 +8536,27 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^0.3.0": +"tinyexec@npm:^0.3.1": version: 0.3.1 resolution: "tinyexec@npm:0.3.1" checksum: 10/0537c70590d52d354f40c0255ff0f654a3d18ddb3812b440ddf9d436edf516c8057838ad5a38744c0c59670ec03e3cf23fbe04ae3d49f031d948274e99002569 languageName: node linkType: hard -"tinypool@npm:^1.0.0": - version: 1.0.1 - resolution: "tinypool@npm:1.0.1" - checksum: 10/eaceb93784b8e27e60c0e3e2c7d11c29e1e79b2a025b2c232215db73b90fe22bd4753ad53fc8e801c2b5a63b94a823af549555d8361272bc98271de7dd4a9925 +"tinyglobby@npm:^0.2.10": + version: 0.2.10 + resolution: "tinyglobby@npm:0.2.10" + dependencies: + fdir: "npm:^6.4.2" + picomatch: "npm:^4.0.2" + checksum: 10/10c976866d849702edc47fc3fef27d63f074c40f75ef17171ecc1452967900699fa1e62373681dd58e673ddff2e3f6094bcd0a2101e3e4b30f4c2b9da41397f2 + languageName: node + linkType: hard + +"tinypool@npm:^1.0.1": + version: 1.0.2 + resolution: "tinypool@npm:1.0.2" + checksum: 10/6109322f14b3763f65c8fa49fddab72cd3edd96b82dd50e05e63de74867329ff5353bff4377281ec963213d9314f37f4a353e9ee34bbac85fd4c1e4a568d6076 languageName: node linkType: hard @@ -8415,7 +8567,7 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^3.0.0": +"tinyspy@npm:^3.0.0, tinyspy@npm:^3.0.2": version: 3.0.2 resolution: "tinyspy@npm:3.0.2" checksum: 10/5db671b2ff5cd309de650c8c4761ca945459d7204afb1776db9a04fb4efa28a75f08517a8620c01ee32a577748802231ad92f7d5b194dc003ee7f987a2a06337 @@ -8759,17 +8911,18 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:2.1.3": - version: 2.1.3 - resolution: "vite-node@npm:2.1.3" +"vite-node@npm:2.1.8": + version: 2.1.8 + resolution: "vite-node@npm:2.1.8" dependencies: cac: "npm:^6.7.14" - debug: "npm:^4.3.6" + debug: "npm:^4.3.7" + es-module-lexer: "npm:^1.5.4" pathe: "npm:^1.1.2" vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10/8ba6b145cbb02a492c7bb1f0490d02383000462f234ed61d24f650547163825c16f14e6908ee1eb661403bd0a7a3fb3cdbedf116cc015b1e5cdf7bb992872a01 + checksum: 10/0ff0ed7a6fb234d3ddc4946e4c1150229980cac9f34fb4bd7f443aab0aae2da5b73ac20ff68af1df476545807dc23189247194e8cea0dcdfa394311c73f04429 languageName: node linkType: hard @@ -8833,33 +8986,34 @@ __metadata: linkType: hard "vitest@npm:^2.1.3": - version: 2.1.3 - resolution: "vitest@npm:2.1.3" - dependencies: - "@vitest/expect": "npm:2.1.3" - "@vitest/mocker": "npm:2.1.3" - "@vitest/pretty-format": "npm:^2.1.3" - "@vitest/runner": "npm:2.1.3" - "@vitest/snapshot": "npm:2.1.3" - "@vitest/spy": "npm:2.1.3" - "@vitest/utils": "npm:2.1.3" - chai: "npm:^5.1.1" - debug: "npm:^4.3.6" - magic-string: "npm:^0.30.11" + version: 2.1.8 + resolution: "vitest@npm:2.1.8" + dependencies: + "@vitest/expect": "npm:2.1.8" + "@vitest/mocker": "npm:2.1.8" + "@vitest/pretty-format": "npm:^2.1.8" + "@vitest/runner": "npm:2.1.8" + "@vitest/snapshot": "npm:2.1.8" + "@vitest/spy": "npm:2.1.8" + "@vitest/utils": "npm:2.1.8" + chai: "npm:^5.1.2" + debug: "npm:^4.3.7" + expect-type: "npm:^1.1.0" + magic-string: "npm:^0.30.12" pathe: "npm:^1.1.2" - std-env: "npm:^3.7.0" + std-env: "npm:^3.8.0" tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.0" - tinypool: "npm:^1.0.0" + tinyexec: "npm:^0.3.1" + tinypool: "npm:^1.0.1" tinyrainbow: "npm:^1.2.0" vite: "npm:^5.0.0" - vite-node: "npm:2.1.3" + vite-node: "npm:2.1.8" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 2.1.3 - "@vitest/ui": 2.1.3 + "@vitest/browser": 2.1.8 + "@vitest/ui": 2.1.8 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -8877,7 +9031,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10/f6079a88583045b551e6526c08774aeac4a9cf85b132793a03f9470c013326abd7fce3985e3c2217dc0dac2fadeee3506e3dc51e215f10862b2fe9da9289af0f + checksum: 10/c2552c068f6faac82eb4e6debb9ed505c0e8016fd6e0a0f0e0dbb5b5417922fbcde80c54af0d3b5a5503a5d6ad6862b6e95b9b59b8b7e98bb553217b9c6fc227 languageName: node linkType: hard