Skip to content

Commit a7014be

Browse files
committed
parse pnp paths in storybook metadata
1 parent 6d0596f commit a7014be

File tree

2 files changed

+90
-9
lines changed

2 files changed

+90
-9
lines changed

code/lib/telemetry/src/get-framework-info.ts

+28-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { PackageJson, StorybookConfig } from '@storybook/types';
2+
import path from 'path';
3+
import { frameworkPackages } from '@storybook/core-common';
4+
import { cleanPaths } from './sanitize';
25
import { getActualPackageJson } from './package-json';
36

47
const knownRenderers = [
@@ -30,20 +33,39 @@ function findMatchingPackage(packageJson: PackageJson, suffixes: string[]) {
3033
return suffixes.map((suffix) => `@storybook/${suffix}`).find((pkg) => allDependencies[pkg]);
3134
}
3235

33-
export async function getFrameworkInfo(mainConfig: StorybookConfig) {
34-
const { framework: frameworkInput } = mainConfig;
36+
export const getFrameworkPackageName = (mainConfig?: StorybookConfig) => {
37+
const packageNameOrPath =
38+
typeof mainConfig?.framework === 'string' ? mainConfig.framework : mainConfig?.framework?.name;
39+
40+
if (!packageNameOrPath) {
41+
return null;
42+
}
43+
44+
const normalizedPath = path.normalize(packageNameOrPath).replace(new RegExp(/\\/, 'g'), '/');
3545

36-
if (!frameworkInput) return {};
46+
const knownFramework = Object.keys(frameworkPackages).find((pkg) => normalizedPath.endsWith(pkg));
47+
48+
return knownFramework || cleanPaths(packageNameOrPath).replace(/.*node_modules\//, '');
49+
};
50+
51+
export async function getFrameworkInfo(mainConfig: StorybookConfig) {
52+
if (!mainConfig.framework) return {};
3753

38-
const framework = typeof frameworkInput === 'string' ? { name: frameworkInput } : frameworkInput;
54+
const frameworkName = getFrameworkPackageName(mainConfig);
55+
if (!frameworkName) return {};
56+
const frameworkOptions =
57+
typeof mainConfig.framework === 'object' ? mainConfig.framework.options : {};
3958

40-
const frameworkPackageJson = await getActualPackageJson(framework.name);
59+
const frameworkPackageJson = await getActualPackageJson(frameworkName);
4160

4261
const builder = findMatchingPackage(frameworkPackageJson, knownBuilders);
4362
const renderer = findMatchingPackage(frameworkPackageJson, knownRenderers);
4463

4564
return {
46-
framework,
65+
framework: {
66+
name: frameworkName,
67+
options: frameworkOptions,
68+
},
4769
builder,
4870
renderer,
4971
};

code/lib/telemetry/src/storybook-metadata.test.ts

+62-3
Original file line numberDiff line numberDiff line change
@@ -82,26 +82,85 @@ describe('sanitizeAddonName', () => {
8282
// @ts-expect-error the property is read only but we can change it for testing purposes
8383
path.sep = '\\';
8484
const cwdMockPath = `C:\\Users\\username\\storybook-app`;
85-
jest.spyOn(process, `cwd`).mockImplementationOnce(() => cwdMockPath);
85+
const cwdSpy = jest.spyOn(process, `cwd`).mockReturnValue(cwdMockPath);
8686

8787
expect(sanitizeAddonName(`${cwdMockPath}\\local-addon\\themes.js`)).toEqual(
8888
'$SNIP\\local-addon\\themes'
8989
);
90+
cwdSpy.mockRestore();
9091
});
9192

9293
test('Linux paths', () => {
9394
// @ts-expect-error the property is read only but we can change it for testing purposes
9495
path.sep = '/';
9596
const cwdMockPath = `/Users/username/storybook-app`;
96-
jest.spyOn(process, `cwd`).mockImplementationOnce(() => cwdMockPath);
97+
const cwdSpy = jest.spyOn(process, `cwd`).mockReturnValue(cwdMockPath);
9798

9899
expect(sanitizeAddonName(`${cwdMockPath}/local-addon/themes.js`)).toEqual(
99100
'$SNIP/local-addon/themes'
100101
);
102+
103+
cwdSpy.mockRestore();
101104
});
102105
});
103106

104-
describe('await computeStorybookMetadata', () => {
107+
describe('computeStorybookMetadata', () => {
108+
test('should parse pnp paths for known frameworks', async () => {
109+
const reactResult = await computeStorybookMetadata({
110+
packageJson: packageJsonMock,
111+
mainConfig: {
112+
...mainJsMock,
113+
framework: {
114+
name: '/Users/foo/storybook/.yarn/__virtual__/@storybook-react-vite-virtual-769c990b9/0/cache/@storybook-react-vite-npm-7.1.0-alpha.38-512b-a23.zip/node_modules/@storybook/react-vite',
115+
options: {
116+
fastRefresh: false,
117+
},
118+
},
119+
},
120+
});
121+
122+
expect(reactResult.framework).toEqual({
123+
name: '@storybook/react-vite',
124+
options: { fastRefresh: false },
125+
});
126+
});
127+
128+
test('should parse pnp paths for unknown frameworks', async () => {
129+
const pnpResult = await computeStorybookMetadata({
130+
packageJson: packageJsonMock,
131+
mainConfig: {
132+
...mainJsMock,
133+
framework: {
134+
name: '/Users/foo/my-project/.yarn/__virtual__/@storybook-react-vite-virtual-769c990b9/0/cache/@storybook-react-rust-npm-7.1.0-alpha.38-512b-a23.zip/node_modules/storybook-react-rust',
135+
},
136+
},
137+
});
138+
139+
expect(pnpResult.framework).toEqual({
140+
name: 'storybook-react-rust',
141+
});
142+
});
143+
144+
test('should sanitize pnp paths for local frameworks', async () => {
145+
const cwdSpy = jest.spyOn(process, 'cwd').mockReturnValue('/Users/foo/my-project');
146+
147+
const localResult = await computeStorybookMetadata({
148+
packageJson: packageJsonMock,
149+
mainConfig: {
150+
...mainJsMock,
151+
framework: {
152+
name: '/Users/foo/my-project/.storybook/some-local-framework',
153+
},
154+
},
155+
});
156+
157+
expect(localResult.framework).toEqual({
158+
name: '$SNIP/.storybook/some-local-framework',
159+
});
160+
161+
cwdSpy.mockRestore();
162+
});
163+
105164
test('should return frameworkOptions from mainjs', async () => {
106165
const reactResult = await computeStorybookMetadata({
107166
packageJson: packageJsonMock,

0 commit comments

Comments
 (0)