Skip to content

Commit fe334bf

Browse files
authored
Merge pull request #33129 from storybookjs/checklistData-improvements
Checklist: Data improvements
2 parents e4ef178 + c10be02 commit fe334bf

File tree

10 files changed

+82
-147
lines changed

10 files changed

+82
-147
lines changed

code/addons/vitest/src/manager.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState } from 'react';
22

3-
import { Addon_TypesEnum } from 'storybook/internal/types';
3+
import { Addon_TypesEnum, SupportedBuilder } from 'storybook/internal/types';
44

55
import {
66
a11yStatusStore,
@@ -23,8 +23,7 @@ import {
2323
import { useTestProvider } from './use-test-provider-state';
2424

2525
addons.register(ADDON_ID, (api) => {
26-
const storybookBuilder = (globalThis as any).STORYBOOK_BUILDER || '';
27-
if (storybookBuilder.includes('vite')) {
26+
if (globalThis.STORYBOOK_BUILDER === SupportedBuilder.VITE) {
2827
const openPanel = (panelId: string) => {
2928
api.setSelectedPanel(panelId);
3029
api.togglePanel(true);

code/addons/vitest/src/typings.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare const BROWSER_CONFIG: object;
2-
declare var STORYBOOK_BUILDER: string | undefined;
2+
declare var STORYBOOK_BUILDER: import('storybook/internal/types').SupportedBuilder | undefined;
33

44
interface ImportMetaEnv {
55
__STORYBOOK_URL__?: string;

code/core/src/builder-manager/utils/framework.test.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,27 @@
1-
import { sep } from 'node:path';
2-
3-
import { extractRenderer, getFrameworkName } from 'storybook/internal/common';
4-
import type { Options } from 'storybook/internal/types';
5-
6-
interface PropertyObject {
7-
name: string;
8-
options?: Record<string, any>;
9-
}
10-
11-
type Property = string | PropertyObject | undefined;
12-
13-
export const pluckNameFromConfigProperty = (property: Property) => {
14-
if (!property) {
15-
return undefined;
16-
}
17-
18-
return typeof property === 'string' ? property : property.name;
19-
};
20-
21-
// For replacing Windows backslashes with forward slashes
22-
const normalizePath = (packagePath: string) => packagePath.replaceAll(sep, '/');
23-
24-
export const pluckStorybookPackageFromPath = (packagePath: string) =>
25-
normalizePath(packagePath).match(/(@storybook\/.*)$/)?.[1];
26-
27-
export const pluckThirdPartyPackageFromPath = (packagePath: string) =>
28-
normalizePath(packagePath).split('node_modules/')[1] ?? packagePath;
1+
import {
2+
extractFrameworkPackageName,
3+
frameworkPackages,
4+
frameworkToRenderer,
5+
getFrameworkName,
6+
} from 'storybook/internal/common';
7+
import { type Options, SupportedBuilder } from 'storybook/internal/types';
298

309
export const buildFrameworkGlobalsFromOptions = async (options: Options) => {
31-
const globals: Record<string, any> = {};
10+
const globals: Record<string, string | undefined> = {};
3211

33-
const { builder } = await options.presets.apply('core');
12+
const builderConfig = (await options.presets.apply('core')).builder;
13+
const builderName = typeof builderConfig === 'string' ? builderConfig : builderConfig?.name;
14+
const builder = Object.values(SupportedBuilder).find((builder) => builderName?.includes(builder));
3415

3516
const frameworkName = await getFrameworkName(options);
36-
const rendererName = await extractRenderer(frameworkName);
37-
38-
if (rendererName) {
39-
globals.STORYBOOK_RENDERER = rendererName ?? undefined;
40-
}
41-
42-
const resolvedPreviewBuilder = pluckNameFromConfigProperty(builder);
43-
if (resolvedPreviewBuilder) {
44-
globals.STORYBOOK_BUILDER =
45-
pluckStorybookPackageFromPath(resolvedPreviewBuilder) ??
46-
pluckThirdPartyPackageFromPath(resolvedPreviewBuilder);
47-
}
48-
49-
const framework = pluckNameFromConfigProperty(await options.presets.apply('framework'));
50-
if (framework) {
51-
globals.STORYBOOK_FRAMEWORK = framework;
52-
}
53-
54-
if (options.networkAddress) {
55-
globals.STORYBOOK_NETWORK_ADDRESS = options.networkAddress;
56-
}
17+
const frameworkPackageName = extractFrameworkPackageName(frameworkName);
18+
const framework = frameworkPackages[frameworkPackageName];
19+
const renderer = frameworkToRenderer[framework];
20+
21+
globals.STORYBOOK_BUILDER = builder;
22+
globals.STORYBOOK_FRAMEWORK = framework;
23+
globals.STORYBOOK_RENDERER = renderer;
24+
globals.STORYBOOK_NETWORK_ADDRESS = options.networkAddress;
5725

5826
return globals;
5927
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { SupportedFramework } from '../types';
2+
3+
export const SUPPORTED_FRAMEWORKS: readonly SupportedFramework[] = [
4+
SupportedFramework.HTML_VITE,
5+
SupportedFramework.NEXTJS_VITE,
6+
SupportedFramework.PREACT_VITE,
7+
SupportedFramework.REACT_NATIVE_WEB_VITE,
8+
SupportedFramework.REACT_VITE,
9+
SupportedFramework.SVELTE_VITE,
10+
SupportedFramework.SVELTEKIT,
11+
SupportedFramework.VUE3_VITE,
12+
SupportedFramework.WEB_COMPONENTS_VITE,
13+
];

code/core/src/cli/AddonVitestService.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import * as find from 'empathic/find';
1212
import { coerce, minVersion, satisfies, validRange } from 'semver';
1313
import { dedent } from 'ts-dedent';
1414

15-
import { SupportedBuilder, SupportedFramework } from '../types';
15+
import { SupportedBuilder, type SupportedFramework } from '../types';
16+
import { SUPPORTED_FRAMEWORKS } from './AddonVitestService.constants';
1617

1718
type Result = {
1819
compatible: boolean;
@@ -38,17 +39,6 @@ export interface AddonVitestCompatibilityOptions {
3839
export class AddonVitestService {
3940
constructor(private readonly packageManager: JsPackageManager) {}
4041

41-
readonly supportedFrameworks: SupportedFramework[] = [
42-
SupportedFramework.HTML_VITE,
43-
SupportedFramework.NEXTJS_VITE,
44-
SupportedFramework.PREACT_VITE,
45-
SupportedFramework.REACT_NATIVE_WEB_VITE,
46-
SupportedFramework.REACT_VITE,
47-
SupportedFramework.SVELTE_VITE,
48-
SupportedFramework.SVELTEKIT,
49-
SupportedFramework.VUE3_VITE,
50-
SupportedFramework.WEB_COMPONENTS_VITE,
51-
];
5242
/**
5343
* Collect all dependencies needed for @storybook/addon-vitest
5444
*
@@ -196,7 +186,7 @@ export class AddonVitestService {
196186
}
197187

198188
// Check renderer/framework support
199-
const isFrameworkSupported = this.supportedFrameworks.some(
189+
const isFrameworkSupported = SUPPORTED_FRAMEWORKS.some(
200190
(framework) => options.framework === framework
201191
);
202192

code/core/src/manager-api/typings.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ declare var REFS: any;
77
declare var VERSIONCHECK: any;
88
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
99
declare var STORYBOOK_ADDON_STATE: Record<string, any>;
10-
declare var STORYBOOK_RENDERER: string | undefined;
11-
declare var STORYBOOK_BUILDER: string | undefined;
12-
declare var STORYBOOK_FRAMEWORK: string | undefined;
10+
declare var STORYBOOK_FRAMEWORK: import('storybook/internal/types').SupportedFramework | undefined;
11+
declare var STORYBOOK_RENDERER: import('storybook/internal/types').SupportedRenderer | undefined;
12+
declare var STORYBOOK_BUILDER: import('storybook/internal/types').SupportedBuilder | undefined;

code/core/src/manager/components/sidebar/ChecklistWidget.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const meta = preview.meta({
3838
...initialState.items,
3939
controls: { status: 'accepted' },
4040
renderComponent: { status: 'done' },
41+
installVitest: { status: 'done' },
4142
moreComponents: { status: 'skipped' },
4243
moreStories: { status: 'skipped' },
4344
},
@@ -57,6 +58,7 @@ const play: PlayFunction = async ({ step }) => {
5758
...initialState.items,
5859
controls: { status: 'accepted' },
5960
renderComponent: { status: 'done' },
61+
installVitest: { status: 'done' },
6062
viewports: { status: 'done' },
6163
moreComponents: { status: 'skipped' },
6264
moreStories: { status: 'skipped' },
@@ -73,10 +75,11 @@ const play: PlayFunction = async ({ step }) => {
7375
...initialState.items,
7476
controls: { status: 'accepted' },
7577
renderComponent: { status: 'done' },
78+
installVitest: { status: 'done' },
7679
viewports: { status: 'done' },
7780
moreComponents: { status: 'skipped' },
7881
moreStories: { status: 'skipped' },
79-
installVitest: { status: 'skipped' },
82+
writeInteractions: { status: 'skipped' },
8083
},
8184
});
8285
});

code/core/src/shared/checklist-store/checklistData.tsx

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import {
99
STORY_INDEX_INVALIDATED,
1010
UPDATE_GLOBALS,
1111
} from 'storybook/internal/core-events';
12-
import type {
13-
API_IndexHash,
14-
API_PreparedIndexEntry,
15-
API_StoryEntry,
12+
import {
13+
type API_IndexHash,
14+
type API_PreparedIndexEntry,
15+
type API_StoryEntry,
1616
} from 'storybook/internal/types';
1717

1818
import { type API, addons, internal_universalTestProviderStore } from 'storybook/manager-api';
@@ -27,6 +27,7 @@ import {
2727
ADDON_ID as ADDON_TEST_ID,
2828
STORYBOOK_ADDON_TEST_CHANNEL,
2929
} from '../../../../addons/vitest/src/constants';
30+
import { SUPPORTED_FRAMEWORKS } from '../../cli/AddonVitestService.constants';
3031
import { ADDON_ID as ADDON_DOCS_ID } from '../../docs-tools/shared';
3132
import { TourGuide } from '../../manager/components/TourGuide/TourGuide';
3233
import type { initialState } from './checklistData.state';
@@ -119,12 +120,21 @@ export interface ChecklistData {
119120
}[];
120121
}
121122

123+
const isExample = (id: string) =>
124+
id.startsWith('example-') || id.startsWith('configure-your-project--');
125+
122126
const subscribeToIndex: (
123127
condition: (entries: Record<string, API_PreparedIndexEntry>) => boolean
124128
) => ChecklistData['sections'][number]['items'][number]['subscribe'] =
125129
(condition) =>
126130
({ api, done }) => {
127-
const check = () => condition(api.getIndex()?.entries || {});
131+
const check = () =>
132+
condition(
133+
Object.entries(api.getIndex()?.entries || {}).reduce(
134+
(acc, [id, entry]) => (isExample(entry.id) ? acc : Object.assign(acc, { [id]: entry })),
135+
{} as Record<string, API_PreparedIndexEntry>
136+
)
137+
);
128138
if (check()) {
129139
done();
130140
} else {
@@ -187,7 +197,10 @@ export const checklistData = {
187197
label: 'Render a component',
188198
criteria: 'A story finished rendering successfully',
189199
subscribe: ({ api, done }) =>
190-
api.on(STORY_FINISHED, ({ status }) => status === 'success' && done()),
200+
api.on(
201+
STORY_FINISHED,
202+
({ storyId, status }) => status === 'success' && !isExample(storyId) && done()
203+
),
191204
content: ({ api }) => (
192205
<>
193206
<p>
@@ -301,8 +314,7 @@ export const Primary: Story = {
301314
criteria: 'At least 5 components exist in the index',
302315
subscribe: subscribeToIndex((entries) => {
303316
const stories = Object.values(entries).filter(
304-
(entry): entry is API_StoryEntry =>
305-
entry.type === 'story' && !entry.id.startsWith('example-')
317+
(entry): entry is API_StoryEntry => entry.type === 'story'
306318
);
307319
const components = new Set(stories.map(({ title }) => title));
308320
return components.size >= 5;
@@ -342,8 +354,7 @@ export const Primary: Story = {
342354
criteria: 'At least 20 stories exist in the index',
343355
subscribe: subscribeToIndex((entries) => {
344356
const stories = Object.values(entries).filter(
345-
(entry): entry is API_StoryEntry =>
346-
entry.type === 'story' && !entry.id.startsWith('example-')
357+
(entry): entry is API_StoryEntry => entry.type === 'story'
347358
);
348359
return stories.length >= 20;
349360
}),
@@ -522,7 +533,9 @@ export default {
522533
id: 'installVitest',
523534
label: 'Install Vitest addon',
524535
afterCompletion: 'unavailable',
525-
available: () => true, // TODO check for compatibility with the project
536+
available: () =>
537+
!!globalThis.STORYBOOK_FRAMEWORK &&
538+
SUPPORTED_FRAMEWORKS.includes(globalThis.STORYBOOK_FRAMEWORK),
526539
criteria: '@storybook/addon-vitest registered in .storybook/main.js|ts',
527540
subscribe: ({ done }) => {
528541
if (addons.experimental_getRegisteredAddons().includes(ADDON_TEST_ID)) {
@@ -665,9 +678,7 @@ export default {
665678
criteria: 'At least one story with a play or test function',
666679
subscribe: subscribeToIndex((entries) =>
667680
Object.values(entries).some(
668-
({ id, tags }) =>
669-
!id.startsWith('example-') &&
670-
(tags?.includes('play-fn') || tags?.includes('test-fn'))
681+
(entry) => entry.tags?.includes('play-fn') || entry.tags?.includes('test-fn')
671682
)
672683
),
673684
content: ({ api }) => (
@@ -1079,9 +1090,7 @@ export const Disabled: Story = {
10791090
label: 'Automatically document your components',
10801091
criteria: 'At least one component with the autodocs tag applied',
10811092
subscribe: subscribeToIndex((entries) =>
1082-
Object.values(entries).some(
1083-
({ id, tags }) => !id.startsWith('example-') && tags?.includes('autodocs')
1084-
)
1093+
Object.values(entries).some((entry) => entry.tags?.includes('autodocs'))
10851094
),
10861095
content: ({ api }) => (
10871096
<>
@@ -1091,12 +1100,14 @@ export const Disabled: Story = {
10911100
and a description.
10921101
</p>
10931102
<CodeSnippet language="typescript">
1094-
{`// Button.stories.ts
1103+
{`// Button.stories.js
10951104
1096-
export default {
1105+
const meta = {
10971106
component: Button,
10981107
tags: ['autodocs'], // 👈 Add this tag
1099-
}`}
1108+
}
1109+
1110+
export default meta;`}
11001111
</CodeSnippet>
11011112
<p>
11021113
That tag can also be applied in <code>.storybook/preview.ts</code>, to generate
@@ -1138,9 +1149,7 @@ export default {
11381149
label: 'Custom content with MDX',
11391150
criteria: 'At least one MDX page',
11401151
subscribe: subscribeToIndex((entries) =>
1141-
Object.values(entries).some(
1142-
({ id, type }) => type === 'docs' && !id.startsWith('example-')
1143-
)
1152+
Object.values(entries).some((entry) => entry.type === 'docs')
11441153
),
11451154
content: ({ api }) => (
11461155
<>

code/core/src/typings.d.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ declare var REFS: any;
77
declare var VERSIONCHECK: any;
88

99
declare var STORYBOOK_ADDON_STATE: Record<string, any>;
10-
declare var STORYBOOK_BUILDER: string | undefined;
11-
declare var STORYBOOK_FRAMEWORK: string | undefined;
10+
declare var STORYBOOK_BUILDER: import('./types/modules/builders').SupportedBuilder | undefined;
11+
declare var STORYBOOK_FRAMEWORK:
12+
| import('./types/modules/frameworks').SupportedFramework
13+
| undefined;
14+
declare var STORYBOOK_RENDERER: import('./types/modules/renderers').SupportedRenderer | undefined;
1215
declare var STORYBOOK_HOOKS_CONTEXT: any;
13-
declare var STORYBOOK_RENDERER: string | undefined;
1416
declare var STORYBOOK_CURRENT_TASK_LOG: undefined | null | Array<any>;
1517

1618
declare var __STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER__: any;

0 commit comments

Comments
 (0)