@storybook/addon-svelte-csf
Version:
Allows to write stories in Svelte syntax
257 lines (226 loc) • 8.87 kB
JavaScript
import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' };
import dedent from 'dedent';
import { print } from 'svelte-ast-print';
import { describe, it } from 'vitest';
import { codemodLegacyNodes } from './index.js';
import { getSvelteAST } from '../../parser/ast.js';
describe(codemodLegacyNodes.name, () => {
it("replaces 'export const meta' with 'defineMeta'", async ({ expect }) => {
const code = dedent(`
<script context="module">
import { Story } from "${pkg.name}";
/** This is a description for the **Button** component stories. */
export const meta = {
title: "Atoms/Button",
component: Button,
};
</script>
<!-- This is a description for **default** Button. -->
<Story name="Default" />
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script context="module">
import { defineMeta } from "@storybook/addon-svelte-csf";
/** This is a description for the **Button** component stories. */
const { Story } = defineMeta({ title: "Atoms/Button", component: Button });
</script>
<!-- This is a description for **default** Button. -->
<Story name="Default" tags={["svelte-csf-v4"]} />"
`);
});
it("replaces 'Meta' with inserting 'defineMeta' to module tag", async ({ expect }) => {
const code = dedent(`
<script context="module">
import { Meta, Template } from "${pkg.name}";
</script>
<!-- This is a description for the **Button** component stories. -->
<Meta title="Atoms/Button" component={Button} />
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script context="module">
import { defineMeta } from "@storybook/addon-svelte-csf";
/** This is a description for the **Button** component stories. */
const { Story } = defineMeta({ title: "Atoms/Button", component: Button });
</script>"
`);
});
it("replaces 'Template' with snippet block", async ({ expect }) => {
const code = dedent(`
<script>
import { Meta, Template } from "${pkg.name}";
</script>
<!-- This is a description for the **Button** component stories. -->
<Meta title="Atoms/Button" component={Button} />
<Template let:args>
<Button {...args} />
</Template>
<Story name="Default" />
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
/** This is a description for the **Button** component stories. */
const { Story } = defineMeta({ title: "Atoms/Button", component: Button });
</script>
{#snippet sb_default_template(args)}
<Button {...args} />
{/snippet}
<Story name="Default" />"
`);
});
it('transforms legacy syntax correctly', async ({ expect }) => {
const code = dedent(`
<script context="module">
import { Meta, Story, Template } from "${pkg.name}";
</script>
<!-- This is a description for the **Button** component stories. -->
<Meta title="Atoms/Button" component={Button} />
<Template id="sample" let:args let:context>
<p>{context.id}</p>
<Button {...args} />
</Template>
<Story name="Default" autodocs source={"<Button {...args} />"} template="sample" let:args let:context>
<p>{context.id}</p>
<Button {...args} />
</Story>
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script context="module">
import { defineMeta } from "@storybook/addon-svelte-csf";
/** This is a description for the **Button** component stories. */
const { Story } = defineMeta({ title: "Atoms/Button", component: Button });
</script>
{#snippet sample(args, context)}
<p>{context.id}</p>
<Button {...args} />
{/snippet} <Story name="Default" template={sample} tags={["autodocs", "svelte-csf-v4"]} parameters={{
docs: { source: { code: "<Button {...args} />" } }
}}>
{#snippet template(args, context)}
<p>{context.id}</p>
<Button {...args} />
{/snippet}
</Story>"
`);
});
it('moves package import declaration from instance to module tag', async ({ expect }) => {
const code = dedent(`
<script>
import { Meta, Story, Template } from "${pkg.name}";
</script>
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
</script>"
`);
});
it('moves transformed export const meta from instance to module tag', async ({ expect }) => {
const code = dedent(`
<script>
import { Story, Template } from "${pkg.name}";
export const meta = {
args: {
primary: true,
},
tags: ["autodocs"],
};
</script>
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
const { Story } = defineMeta({
args: { primary: true },
tags: ["autodocs"]
});
</script>"
`);
});
it('moves transformed export const meta and stories component import declaration from instance to module tag', async ({ expect, }) => {
const code = dedent(`
<script>
import { Story, Template } from "${pkg.name}";
import Button from "./Button.svelte";
export const meta = {
component: Button,
args: {
primary: true,
},
tags: ["autodocs"],
};
</script>
`);
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
import Button from "./Button.svelte";
const { Story } = defineMeta({
component: Button,
args: { primary: true },
tags: ["autodocs"]
});
</script>"
`);
});
it('throws error on more than one unidentified <Template> components', async ({ expect }) => {
const code = `
<script module lang="ts">
import { Story, Template } from "${pkg.name}";
</script>
<Template let:context>
<p>{context.args}</p>
</Template>
<Story name="Default" />
<Template let:args>
<Button {...args} />
</Template>
<Story name="NextOne" />
`;
const ast = getSvelteAST({ code });
await expect(codemodLegacyNodes({ ast })).rejects.toThrowErrorMatchingInlineSnapshot(`
[SB_SVELTE_CSF_LEGACY_API_0003 (DuplicatedUnidentifiedTemplateError): Stories file: undefined
has two '<Template />' components without provided prop 'id'. This leads to unwanted runtime behavior.
Please provide an 'id' to one of them.
And for the '<Story />' component(s) which are supposed to use it, add the 'template' prop with the same 'id' value.
More info: https://github.com/storybookjs/addon-svelte-csf/blob/v${pkg.version}/ERRORS.md#SB_SVELTE_CSF_LEGACY_API_0003
]
`);
});
it('moves import declaration of stories target component from instance tag to module tag', async ({ expect, }) => {
const code = `
<script context="module" lang="ts">
export const meta: Meta<Button> = {
component: Button,
};
</script>
<script>
import { Story } from "${pkg.name}";
import Button from "./Button.svelte";
</script>
`;
const ast = getSvelteAST({ code });
const transformed = await codemodLegacyNodes({ ast });
expect(print(transformed)).toMatchInlineSnapshot(`
"<script context="module" lang="ts">
import { defineMeta } from "@storybook/addon-svelte-csf";
import Button from "./Button.svelte";
const { Story } = defineMeta({ component: Button });
</script>"
`);
});
});