Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
CLI: Avoid mixed CSF in files with unconventional stories
- Added early exit condition in `storyToCsfFactory` to skip transformation when no stories are detected, preventing mixed CSF syntax.
- Updated tests to verify the new behavior, ensuring proper logging when no stories are transformed.
- Mocked logger's log method for improved test coverage and validation of warning messages.
  • Loading branch information
yannbf committed Oct 13, 2025
commit b1b26aa0b161f7adca969f89b3f07d1e6b352c19
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { storyToCsfFactory } from './story-to-csf-factory';

vi.mock('storybook/internal/node-logger', () => ({
logger: {
log: vi.fn(),
warn: vi.fn(),
},
}));
Expand All @@ -34,25 +35,30 @@ describe('stories codemod', () => {
transform(dedent`
const meta = { title: 'Component' };
export default meta;
export const A = {};
`)
).resolves.toMatchInlineSnapshot(`
import preview from '#.storybook/preview';

const meta = preview.meta({ title: 'Component' });
export const A = meta.story();
`);
});

it('should transform and wrap inline default exported meta', async () => {
await expect(
transform(dedent`
export default { title: 'Component' };
export const A = {};
`)
).resolves.toMatchInlineSnapshot(`
import preview from '#.storybook/preview';

const meta = preview.meta({
title: 'Component',
});

export const A = meta.story();
`);
});

Expand All @@ -61,11 +67,13 @@ describe('stories codemod', () => {
transform(dedent`
const componentMeta = { title: 'Component' };
export default componentMeta;
export const A = {};
`)
).resolves.toMatchInlineSnapshot(`
import preview from '#.storybook/preview';

const componentMeta = preview.meta({ title: 'Component' });
export const A = componentMeta.story();
`);
});

Expand Down Expand Up @@ -349,6 +357,7 @@ describe('stories codemod', () => {
source: dedent`
import preview, { extra } from '../../../.storybook/preview';
export default {};
export const A = {};
`,
path: 'Component.stories.tsx',
},
Expand All @@ -359,6 +368,7 @@ describe('stories codemod', () => {
import preview, { extra } from '#.storybook/preview';

const meta = preview.meta({});
export const A = meta.story();
`);

await expect(
Expand All @@ -369,6 +379,7 @@ describe('stories codemod', () => {
source: dedent`
import preview, { extra } from '#.storybook/preview';
export default {};
export const A = {};
`,
path: 'Component.stories.tsx',
},
Expand All @@ -379,6 +390,7 @@ describe('stories codemod', () => {
import preview, { extra } from '../../preview';

const meta = preview.meta({});
export const A = meta.story();
`);
} finally {
relativeMock.mockRestore();
Expand Down Expand Up @@ -666,6 +678,24 @@ describe('stories codemod', () => {
// expect(transformed).toContain('C = meta.story');
});

it('should bail transformation when no stories can be transformed', async () => {
const source = dedent`
export default {
title: 'Component',
};
`;
const transformed = await transform(source);
const formattedSource = await formatFileContent('Component.stories.tsx', source);
expect(transformed).toEqual(formattedSource);

expect(transformed).not.toContain('preview.meta');
expect(transformed).not.toContain('meta.story');

expect(vi.mocked(logger.warn).mock.calls[0][0]).toMatchInlineSnapshot(
`Skipping codemod for Component.stories.tsx: no stories were transformed. Either there are no stories, file has been already transformed or some stories are written in an unsupported format.`
);
});

it('should bail transformation and warn if some stories are not transformed to avoid mixed CSF formats', async () => {
const source = dedent`
export default {
Expand Down Expand Up @@ -700,7 +730,7 @@ describe('stories codemod', () => {
const formattedSource = await formatFileContent('Component.stories.tsx', source);
expect(transformed).toEqual(formattedSource);

expect(logger.warn).not.toHaveBeenCalled();
expect(logger.log).not.toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,16 @@ export async function storyToCsfFactory(
},
});

// If no stories were transformed, bail early to avoid having a mixed CSF syntax and therefore a broken indexer.
if (transformedStoryExports.size === 0) {
logger.warn(
`Skipping codemod for ${info.path}: no stories were transformed. Either there are no stories, file has been already transformed or some stories are written in an unsupported format.`
);
return info.source;
}

// If some stories were detected but not all could be transformed, we skip the codemod to avoid mixed csf syntax and therefore a broken indexer.
if (
detectedStoryNames.length > 0 &&
transformedStoryExports.size > 0 &&
transformedStoryExports.size !== detectedStoryNames.length
) {
if (detectedStoryNames.length > 0 && transformedStoryExports.size !== detectedStoryNames.length) {
logger.warn(
`Skipping codemod for ${info.path}:\nSome of the detected stories [${detectedStoryNames
.map((name) => `"${name}"`)
Expand Down
Loading