@storybook/addon-svelte-csf 5.1.1 → 5.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/compiler/post-transform/appendix/create-export-order.test.d.ts +1 -0
  2. package/dist/compiler/post-transform/appendix/create-export-order.test.js +21 -0
  3. package/dist/compiler/post-transform/appendix/create-import.test.d.ts +1 -0
  4. package/dist/compiler/post-transform/appendix/create-import.test.js +9 -0
  5. package/dist/compiler/post-transform/appendix/create-named-export-stories.test.d.ts +1 -0
  6. package/dist/compiler/post-transform/appendix/create-named-export-stories.test.js +35 -0
  7. package/dist/compiler/post-transform/appendix/create-runtime-story-variable-declaration.test.d.ts +1 -0
  8. package/dist/compiler/post-transform/appendix/create-runtime-story-variable-declaration.test.js +100 -0
  9. package/dist/compiler/post-transform/appendix/create-variable-from-runtime-stories-call.test.d.ts +1 -0
  10. package/dist/compiler/post-transform/appendix/create-variable-from-runtime-stories-call.test.js +22 -0
  11. package/dist/compiler/post-transform/define-meta/index.test.d.ts +1 -0
  12. package/dist/compiler/post-transform/define-meta/index.test.js +96 -0
  13. package/dist/compiler/post-transform/index.test.d.ts +1 -0
  14. package/dist/compiler/post-transform/index.test.js +279 -0
  15. package/dist/compiler/post-transform/remove-export-default.test.d.ts +1 -0
  16. package/dist/compiler/post-transform/remove-export-default.test.js +33 -0
  17. package/dist/compiler/post-transform/story/index.test.d.ts +1 -0
  18. package/dist/compiler/post-transform/story/index.test.js +147 -0
  19. package/dist/compiler/pre-transform/codemods/component-meta-to-define-meta.test.d.ts +1 -0
  20. package/dist/compiler/pre-transform/codemods/component-meta-to-define-meta.test.js +121 -0
  21. package/dist/compiler/pre-transform/codemods/export-const-to-define-meta.test.d.ts +1 -0
  22. package/dist/compiler/pre-transform/codemods/export-const-to-define-meta.test.js +68 -0
  23. package/dist/compiler/pre-transform/codemods/import-declaration.test.d.ts +1 -0
  24. package/dist/compiler/pre-transform/codemods/import-declaration.test.js +24 -0
  25. package/dist/compiler/pre-transform/codemods/legacy-story.test.d.ts +1 -0
  26. package/dist/compiler/pre-transform/codemods/legacy-story.test.js +287 -0
  27. package/dist/compiler/pre-transform/codemods/template-to-snippet.test.d.ts +1 -0
  28. package/dist/compiler/pre-transform/codemods/template-to-snippet.test.js +75 -0
  29. package/dist/compiler/pre-transform/index.test.d.ts +1 -0
  30. package/dist/compiler/pre-transform/index.test.js +256 -0
  31. package/dist/parser/analyse/story/attributes/identifiers.test.d.ts +1 -0
  32. package/dist/parser/analyse/story/attributes/identifiers.test.js +294 -0
  33. package/dist/parser/analyse/story/attributes.test.d.ts +1 -0
  34. package/dist/parser/analyse/story/attributes.test.js +151 -0
  35. package/dist/parser/analyse/story/content.test.d.ts +1 -0
  36. package/dist/parser/analyse/story/content.test.js +263 -0
  37. package/dist/parser/extract/svelte/define-meta.test.d.ts +1 -0
  38. package/dist/parser/extract/svelte/define-meta.test.js +32 -0
  39. package/dist/parser/extract/svelte/fragment-nodes.test.d.ts +1 -0
  40. package/dist/parser/extract/svelte/fragment-nodes.test.js +101 -0
  41. package/dist/parser/extract/svelte/module-nodes.test.d.ts +1 -0
  42. package/dist/parser/extract/svelte/module-nodes.test.js +143 -0
  43. package/dist/parser/extract/svelte/nodes.test.d.ts +1 -0
  44. package/dist/parser/extract/svelte/nodes.test.js +29 -0
  45. package/dist/parser/extract/svelte/story/attributes.test.d.ts +1 -0
  46. package/dist/parser/extract/svelte/story/attributes.test.js +50 -0
  47. package/dist/parser/extract/svelte/story/template.test.d.ts +1 -0
  48. package/dist/parser/extract/svelte/story/template.test.js +51 -0
  49. package/dist/runtime/emit-code.test.d.ts +1 -0
  50. package/dist/runtime/emit-code.test.js +149 -0
  51. package/dist/utils/identifier-utils.test.d.ts +1 -0
  52. package/dist/utils/identifier-utils.test.js +22 -0
  53. package/package.json +22 -27
@@ -0,0 +1,147 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import url from 'node:url';
4
+ import { print } from 'esrap';
5
+ import MagicString from 'magic-string';
6
+ import { parseAst } from 'rollup/parseAst';
7
+ import { describe, it } from 'vitest';
8
+ import { transformStory } from './index.js';
9
+ import { getSvelteAST } from '../../../parser/ast.js';
10
+ import { extractSvelteASTNodes } from '../../../parser/extract/svelte/nodes.js';
11
+ import { extractCompiledASTNodes } from '../../../parser/extract/compiled/nodes.js';
12
+ import { extractStoriesNodesFromExportDefaultFn } from '../../../parser/extract/compiled/stories.js';
13
+ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
14
+ describe(transformStory.name, () => {
15
+ it("each transformed compiled 'Story' component matches inlined snapshots", async ({ expect, }) => {
16
+ const filename = path.resolve(__dirname, '../../../../tests/stories/Example.stories.svelte');
17
+ const originalCode = fs.readFileSync(filename).toString();
18
+ const compiledPreTransformCode = fs
19
+ .readFileSync(path.resolve(__dirname, '../../../../tests/__compiled__/pre-transform/Example.stories.dev.js'))
20
+ .toString();
21
+ const svelteAST = getSvelteAST({ code: originalCode, filename });
22
+ const svelteASTNodes = await extractSvelteASTNodes({
23
+ ast: svelteAST,
24
+ filename,
25
+ });
26
+ const compiledASTNodes = await extractCompiledASTNodes({
27
+ ast: parseAst(compiledPreTransformCode),
28
+ filename,
29
+ });
30
+ const code = new MagicString(compiledPreTransformCode);
31
+ const extractedCompiledStoriesNodes = await extractStoriesNodesFromExportDefaultFn({
32
+ nodes: compiledASTNodes,
33
+ filename,
34
+ });
35
+ const svelteStories = [...svelteASTNodes.storyComponents].reverse();
36
+ const compiledPreTransformedStories = [...extractedCompiledStoriesNodes].reverse();
37
+ svelteStories.forEach((svelte, index) => {
38
+ transformStory({
39
+ code,
40
+ nodes: {
41
+ svelte: svelteASTNodes,
42
+ component: {
43
+ svelte,
44
+ compiled: compiledPreTransformedStories[index],
45
+ },
46
+ },
47
+ filename,
48
+ originalCode,
49
+ });
50
+ });
51
+ const compiledPostTransformedStories = await extractStoriesNodesFromExportDefaultFn({
52
+ nodes: await extractCompiledASTNodes({
53
+ ast: parseAst(code.toString()),
54
+ }),
55
+ filename,
56
+ });
57
+ expect(print(compiledPostTransformedStories[0]).code).toMatchInlineSnapshot(`
58
+ "Story(node_1, {
59
+ name: 'Default',
60
+ template,
61
+ parameters: {
62
+ docs: {
63
+ description: { story: "Description for the default story" }
64
+ },
65
+ __svelteCsf: {
66
+ rawCode: "<Example {...args} onclick={handleClick}>\\n <p>{context.name}</p>\\n You clicked: {count}<br />\\n</Example>"
67
+ }
68
+ }
69
+ })"
70
+ `);
71
+ expect(print(compiledPostTransformedStories[1]).code).toMatchInlineSnapshot(`
72
+ "Story(node_2, {
73
+ name: 'Rounded',
74
+ args: { rounded: true },
75
+ template,
76
+ parameters: {
77
+ docs: {
78
+ description: { story: "Description for the rounded story" }
79
+ },
80
+ __svelteCsf: {
81
+ rawCode: "<Example {...args} onclick={handleClick}>\\n <p>{context.name}</p>\\n You clicked: {count}<br />\\n</Example>"
82
+ }
83
+ }
84
+ })"
85
+ `);
86
+ expect(print(compiledPostTransformedStories[2]).code).toMatchInlineSnapshot(`
87
+ "Story(node_3, {
88
+ name: 'Square',
89
+ args: { rounded: false },
90
+ template,
91
+ parameters: {
92
+ docs: {
93
+ description: { story: "Description for the squared story" }
94
+ },
95
+ __svelteCsf: {
96
+ rawCode: "<Example {...args} onclick={handleClick}>\\n <p>{context.name}</p>\\n You clicked: {count}<br />\\n</Example>"
97
+ }
98
+ }
99
+ })"
100
+ `);
101
+ expect(print(compiledPostTransformedStories[3]).code).toMatchInlineSnapshot(`
102
+ "Story(node_4, {
103
+ name: 'As child',
104
+ asChild: true,
105
+ children: $.wrap_snippet(Example_stories, ($$anchor, $$slotProps) => {
106
+ var fragment_3 = $.comment();
107
+ var node_5 = $.first_child(fragment_3);
108
+
109
+ Example(node_5, {
110
+ children: $.wrap_snippet(Example_stories, ($$anchor, $$slotProps) => {
111
+ $.next();
112
+
113
+ var text_2 = $.text('Label');
114
+
115
+ $.append($$anchor, text_2);
116
+ }),
117
+ $$slots: { default: true }
118
+ });
119
+
120
+ $.append($$anchor, fragment_3);
121
+ }),
122
+ $$slots: { default: true },
123
+ parameters: {
124
+ __svelteCsf: { rawCode: "<Example>Label</Example>" }
125
+ }
126
+ })"
127
+ `);
128
+ expect(print(compiledPostTransformedStories[4]).code).toMatchInlineSnapshot(`
129
+ "Story(node_6, {
130
+ name: 'Children forwared',
131
+ children: $.wrap_snippet(Example_stories, ($$anchor, $$slotProps) => {
132
+ $.next();
133
+
134
+ var text_3 = $.text('Forwarded label');
135
+
136
+ $.append($$anchor, text_3);
137
+ }),
138
+ $$slots: { default: true },
139
+ parameters: {
140
+ __svelteCsf: {
141
+ rawCode: "<Example {...args}>\\n Forwarded label\\n</Example>"
142
+ }
143
+ }
144
+ })"
145
+ `);
146
+ });
147
+ });
@@ -0,0 +1,121 @@
1
+ import { print } from 'svelte-ast-print';
2
+ import { describe, it } from 'vitest';
3
+ import { transformComponentMetaToDefineMeta } from './component-meta-to-define-meta.js';
4
+ import { parseAndExtractSvelteNode } from '../../../../tests/extractor.js';
5
+ describe(transformComponentMetaToDefineMeta.name, () => {
6
+ it('works with a simple example', async ({ expect }) => {
7
+ const code = `
8
+ <script context="module">
9
+ import { Meta } from "@storybook/addon-svelte-csf";
10
+ </script>
11
+
12
+ <Meta title="Atoms/Button" component={Button} />
13
+ `;
14
+ const node = await parseAndExtractSvelteNode(code, 'Component');
15
+ expect(print(transformComponentMetaToDefineMeta({
16
+ component: node,
17
+ }))).toMatchInlineSnapshot(`"const { Story } = defineMeta({ title: "Atoms/Button", component: Button });"`);
18
+ });
19
+ it('leading comments are included', async ({ expect }) => {
20
+ const code = `
21
+ <script context="module">
22
+ import { Meta } from "@storybook/addon-svelte-csf";
23
+ </script>
24
+
25
+ <!-- This is a description for the **Button** component stories. -->
26
+ <Meta title="Atoms/Button" component={Button} />
27
+ `;
28
+ const [comment, component] = await Promise.all([
29
+ parseAndExtractSvelteNode(code, 'Comment'),
30
+ parseAndExtractSvelteNode(code, 'Component'),
31
+ ]);
32
+ expect(print(transformComponentMetaToDefineMeta({
33
+ component,
34
+ comment,
35
+ }))).toMatchInlineSnapshot(`
36
+ "/** This is a description for the **Button** component stories. */ const { Story } = defineMeta({ title: "Atoms/Button", component: Button });"
37
+ `);
38
+ });
39
+ it('supports <Meta> parameters with functions', async ({ expect }) => {
40
+ const code = `
41
+ <script context="module">
42
+ import { Meta } from "@storybook/addon-svelte-csf";
43
+ import WithParameters from './WithParameters.svelte';
44
+ </script>
45
+
46
+ <Meta component={WithParameters} parameters={{
47
+ docs: {
48
+ source: {
49
+ transform: (code) => {
50
+ return code + 'transformed';
51
+ }
52
+ }
53
+ }
54
+ }} />
55
+ `;
56
+ const component = await parseAndExtractSvelteNode(code, 'Component');
57
+ expect(print(transformComponentMetaToDefineMeta({ component }))).toMatchInlineSnapshot(`
58
+ "const { Story } = defineMeta({
59
+ component: WithParameters,
60
+ parameters: {
61
+ docs: {
62
+ source: {
63
+ transform: (code) => {
64
+ return code + 'transformed';
65
+ }
66
+ }
67
+ }
68
+ }
69
+ });"
70
+ `);
71
+ });
72
+ it('supports <Meta> with parameters being referenced to variable in the instance tag', async ({ expect, }) => {
73
+ const code = `
74
+ <script>
75
+ const parameters = { foo: 'bar' };
76
+ </script>
77
+
78
+ <Meta component={WithParameters} parameters={{ ...parameters, baz: 'yes'}} />
79
+ `;
80
+ const component = await parseAndExtractSvelteNode(code, 'Component');
81
+ expect(print(transformComponentMetaToDefineMeta({ component }))).toMatchInlineSnapshot(`
82
+ "const { Story } = defineMeta({
83
+ component: WithParameters,
84
+ parameters: { ...parameters, baz: 'yes' }
85
+ });"
86
+ `);
87
+ });
88
+ it("transforms singular expresion tag with literal string on 'tags' attribute to array expression", async ({ expect, }) => {
89
+ const code = `
90
+ <script context="module">
91
+ import { Story } from "@storybook/addon-svelte-csf";
92
+ </script>
93
+
94
+ <Meta tags={"autodocs"} />
95
+ `;
96
+ const component = await parseAndExtractSvelteNode(code, 'Component');
97
+ expect(print(transformComponentMetaToDefineMeta({ component }))).toMatchInlineSnapshot(`"const { Story } = defineMeta({ tags: ["autodocs"] });"`);
98
+ });
99
+ it("transforms singular text value on 'tags' attribute to array expression", async ({ expect, }) => {
100
+ const code = `
101
+ <script context="module">
102
+ import { Story } from "@storybook/addon-svelte-csf";
103
+ </script>
104
+
105
+ <Meta tags="singular" />
106
+ `;
107
+ const component = await parseAndExtractSvelteNode(code, 'Component');
108
+ expect(print(transformComponentMetaToDefineMeta({ component }))).toMatchInlineSnapshot(`"const { Story } = defineMeta({ tags: ["singular"] });"`);
109
+ });
110
+ it('tags with an array expression are left as-is', async ({ expect }) => {
111
+ const code = `
112
+ <script context="module">
113
+ import { Story } from "@storybook/addon-svelte-csf";
114
+ </script>
115
+
116
+ <Meta tags={["autodocs", "!dev"]} />
117
+ `;
118
+ const component = await parseAndExtractSvelteNode(code, 'Component');
119
+ expect(print(transformComponentMetaToDefineMeta({ component }))).toMatchInlineSnapshot(`"const { Story } = defineMeta({ tags: ["autodocs", "!dev"] });"`);
120
+ });
121
+ });
@@ -0,0 +1,68 @@
1
+ import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' };
2
+ import { print } from 'svelte-ast-print';
3
+ import { describe, it } from 'vitest';
4
+ import { transformExportMetaToDefineMeta } from './export-const-to-define-meta.js';
5
+ import { parseAndExtractSvelteNode } from '../../../../tests/extractor.js';
6
+ describe(transformExportMetaToDefineMeta.name, () => {
7
+ it('works with advanced example', async ({ expect }) => {
8
+ const code = `
9
+ <script context="module" lang="ts">
10
+ import { Story, Template } from "${pkg.name}";
11
+
12
+ export const meta = {
13
+ component: Button,
14
+ tags: ['autodocs'],
15
+ args: {
16
+ children: 'Click me',
17
+ onclick: onclickFn,
18
+ },
19
+ argTypes: {
20
+ backgroundColor: { control: 'color' },
21
+ size: {
22
+ control: { type: 'select' },
23
+ options: ['small', 'medium', 'large'],
24
+ },
25
+ children: { control: 'text' },
26
+ }
27
+ } satisfies Meta<Button>;
28
+ </script>
29
+ `;
30
+ const node = await parseAndExtractSvelteNode(code, 'ExportNamedDeclaration');
31
+ expect(print(transformExportMetaToDefineMeta(node))).toMatchInlineSnapshot(`
32
+ "const { Story } = defineMeta({
33
+ component: Button,
34
+ tags: ['autodocs'],
35
+ args: { children: 'Click me', onclick: onclickFn },
36
+ argTypes: {
37
+ backgroundColor: { control: 'color' },
38
+ size: {
39
+ control: { type: 'select' },
40
+ options: ['small', 'medium', 'large']
41
+ },
42
+ children: { control: 'text' }
43
+ }
44
+ });"
45
+ `);
46
+ });
47
+ it('leading comments are included', async ({ expect }) => {
48
+ const code = `
49
+ <script context="module">
50
+ import { Story, Template } from "${pkg.name}";
51
+
52
+ /**
53
+ * This is a description for the **Button** component stories.
54
+ */
55
+ export const meta = {
56
+ component: Button,
57
+ };
58
+ </script>
59
+ `;
60
+ const node = await parseAndExtractSvelteNode(code, 'ExportNamedDeclaration');
61
+ expect(print(transformExportMetaToDefineMeta(node))).toMatchInlineSnapshot(`
62
+ "/**
63
+ * This is a description for the **Button** component stories.
64
+ */
65
+ const { Story } = defineMeta({ component: Button });"
66
+ `);
67
+ });
68
+ });
@@ -0,0 +1,24 @@
1
+ import { print } from 'svelte-ast-print';
2
+ import { describe, it } from 'vitest';
3
+ import { transformImportDeclaration } from './import-declaration.js';
4
+ import { parseAndExtractSvelteNode } from '../../../../tests/extractor.js';
5
+ describe(transformImportDeclaration.name, () => {
6
+ it("removes legacy components and add 'defineMeta'", async ({ expect }) => {
7
+ const code = `
8
+ <script context="module" lang="ts">
9
+ import { Story, Template } from "@storybook/addon-svelte-csf";
10
+ </script>
11
+ `;
12
+ const node = await parseAndExtractSvelteNode(code, 'ImportDeclaration');
13
+ expect(print(transformImportDeclaration({ node }))).toMatchInlineSnapshot(`"import { defineMeta } from "@storybook/addon-svelte-csf";"`);
14
+ });
15
+ it("it doesn't remove existing 'defineMeta'", async ({ expect }) => {
16
+ const code = `
17
+ <script context="module" lang="ts">
18
+ import { Story, Template, defineMeta } from "@storybook/addon-svelte-csf";
19
+ </script>
20
+ `;
21
+ const node = await parseAndExtractSvelteNode(code, 'ImportDeclaration');
22
+ expect(print(transformImportDeclaration({ node }))).toMatchInlineSnapshot(`"import { defineMeta } from "@storybook/addon-svelte-csf";"`);
23
+ });
24
+ });
@@ -0,0 +1,287 @@
1
+ import { print } from 'svelte-ast-print';
2
+ import { describe, it } from 'vitest';
3
+ import { transformLegacyStory } from './legacy-story.js';
4
+ import { parseAndExtractSvelteNode } from '../../../../tests/extractor.js';
5
+ describe(transformLegacyStory.name, () => {
6
+ it("it moves 'autodocs' prop to 'tags' correctly", async ({ expect }) => {
7
+ const code = `
8
+ <script context="module">
9
+ import { Story } from "@storybook/addon-svelte-csf";
10
+ </script>
11
+
12
+ <Story name="Default" autodocs />
13
+ `;
14
+ const component = await parseAndExtractSvelteNode(code, 'Component');
15
+ expect(print(transformLegacyStory({
16
+ component,
17
+ state: { componentIdentifierName: {} },
18
+ }))).toMatchInlineSnapshot(`"<Story name="Default" tags={["autodocs", "svelte-csf-v4"]} />"`);
19
+ });
20
+ it("moving 'autodocs' prop doesn't break with existing 'tags' prop", async ({ expect }) => {
21
+ const code = `
22
+ <script context="module">
23
+ import { Story } from "@storybook/addon-svelte-csf";
24
+ </script>
25
+
26
+ <Story name="Default" autodocs tags={["!dev"]} />
27
+ `;
28
+ const component = await parseAndExtractSvelteNode(code, 'Component');
29
+ expect(print(transformLegacyStory({
30
+ component,
31
+ state: { componentIdentifierName: {} },
32
+ }))).toMatchInlineSnapshot(`"<Story name="Default" tags={["!dev", "autodocs", "svelte-csf-v4"]} />"`);
33
+ });
34
+ it("'source' prop when is a shorthand gets removed", async ({ expect }) => {
35
+ const code = `
36
+ <script context="module">
37
+ import { Story } from "@storybook/addon-svelte-csf";
38
+ </script>
39
+
40
+ <Story name="Default" source />
41
+ `;
42
+ const component = await parseAndExtractSvelteNode(code, 'Component');
43
+ expect(print(transformLegacyStory({
44
+ component,
45
+ state: { componentIdentifierName: {} },
46
+ }))).toMatchInlineSnapshot(`"<Story name="Default" tags={["svelte-csf-v4"]} />"`);
47
+ });
48
+ it("'source' prop when is a text expression gets moved to 'parameters' prop", async ({ expect, }) => {
49
+ const code = `
50
+ <script context="module">
51
+ import { Story } from "@storybook/addon-svelte-csf";
52
+ </script>
53
+
54
+ <Story name="Default" source="'<Button primary />'" />
55
+ `;
56
+ const component = await parseAndExtractSvelteNode(code, 'Component');
57
+ expect(print(transformLegacyStory({
58
+ component,
59
+ state: { componentIdentifierName: {} },
60
+ }))).toMatchInlineSnapshot(`
61
+ "<Story name="Default" parameters={{
62
+ docs: { source: { code: "'<Button primary />'" } }
63
+ }} tags={["svelte-csf-v4"]} />"
64
+ `);
65
+ });
66
+ it("'source' prop when is a text expression and Story has children, gets moved to 'parameters' prop", async ({ expect, }) => {
67
+ const code = `
68
+ <script context="module">
69
+ import { Story } from "@storybook/addon-svelte-csf";
70
+ </script>
71
+
72
+ <Story name="With source as text" source="<LegacyStory>Hi</LegacyStory>">
73
+ <LegacyStory>{'Hi'}</LegacyStory>
74
+ </Story>
75
+ `;
76
+ const component = await parseAndExtractSvelteNode(code, 'Component');
77
+ expect(print(transformLegacyStory({
78
+ component,
79
+ state: { componentIdentifierName: {} },
80
+ }))).toMatchInlineSnapshot(`
81
+ "<Story name="With source as text" parameters={{
82
+ docs: {
83
+ source: { code: "<LegacyStory>Hi</LegacyStory>" }
84
+ }
85
+ }} tags={["svelte-csf-v4"]}>
86
+ <LegacyStory>{'Hi'}</LegacyStory>
87
+ </Story>"
88
+ `);
89
+ });
90
+ it("'source' prop when is a text expression gets moved to existing 'parameters'", async ({ expect, }) => {
91
+ const code = `
92
+ <script context="module">
93
+ import { Story } from "@storybook/addon-svelte-csf";
94
+ </script>
95
+
96
+ <Story
97
+ name="Default"
98
+ source="'<Button primary />'"
99
+ parameters={{
100
+ controls: { disable: true },
101
+ interactions: { disable: true },
102
+ }}
103
+ />
104
+ `;
105
+ const component = await parseAndExtractSvelteNode(code, 'Component');
106
+ expect(print(transformLegacyStory({
107
+ component,
108
+ state: { componentIdentifierName: {} },
109
+ }))).toMatchInlineSnapshot(`
110
+ "<Story name="Default" parameters={{
111
+ controls: { disable: true },
112
+ interactions: { disable: true },
113
+ docs: { source: { code: "'<Button primary />'" } }
114
+ }} tags={["svelte-csf-v4"]} />"
115
+ `);
116
+ });
117
+ it("transforms 'template' id prop to 'template' reference prop and text expression becomes expression tag with identifier to snippet", async ({ expect, }) => {
118
+ const code = `
119
+ <script context="module">
120
+ import { Story } from "@storybook/addon-svelte-csf";
121
+ </script>
122
+
123
+ <Story name="Default" template="someTemplate" />
124
+ `;
125
+ const component = await parseAndExtractSvelteNode(code, 'Component');
126
+ expect(print(transformLegacyStory({
127
+ component,
128
+ state: { componentIdentifierName: {} },
129
+ }))).toMatchInlineSnapshot(`"<Story name="Default" template={someTemplate} tags={["svelte-csf-v4"]} />"`);
130
+ });
131
+ it("transforms 'template' id prop to 'template' reference prop and text expression becomes expression tag with identifier to snippet (case with invalid identifier)", async ({ expect, }) => {
132
+ const code = `
133
+ <script context="module">
134
+ import { Story } from "@storybook/addon-svelte-csf";
135
+ </script>
136
+
137
+ <Story name="Default" template="some template with non valid identifier" />
138
+ `;
139
+ const component = await parseAndExtractSvelteNode(code, 'Component');
140
+ expect(print(transformLegacyStory({
141
+ component,
142
+ state: { componentIdentifierName: {} },
143
+ }))).toMatchInlineSnapshot(`"<Story name="Default" template={template_r71ke5} tags={["svelte-csf-v4"]} />"`);
144
+ });
145
+ it("when directive 'let:args' is used then it wraps Story fragment with 'template' snippet block", async ({ expect, }) => {
146
+ const code = `
147
+ <script context="module">
148
+ import { Story } from "@storybook/addon-svelte-csf";
149
+ </script>
150
+
151
+ <Story name="Default" let:args>
152
+ <Button {...args} />
153
+ </Story>
154
+ `;
155
+ const component = await parseAndExtractSvelteNode(code, 'Component');
156
+ expect(print(transformLegacyStory({
157
+ component,
158
+ state: { componentIdentifierName: {} },
159
+ }))).toMatchInlineSnapshot(`
160
+ "<Story name="Default" tags={["svelte-csf-v4"]}>
161
+ {#snippet template(args)}
162
+ <Button {...args} />
163
+ {/snippet}
164
+ </Story>"
165
+ `);
166
+ });
167
+ it("when directive 'let:context' is used then it wraps Story fragment with 'template' snippet block", async ({ expect, }) => {
168
+ const code = `
169
+ <script context="module">
170
+ import { Story } from "@storybook/addon-svelte-csf";
171
+ </script>
172
+
173
+ <Story name="Default" let:context>
174
+ <p>{context.id}</p>
175
+ </Story>
176
+ `;
177
+ const component = await parseAndExtractSvelteNode(code, 'Component');
178
+ expect(print(transformLegacyStory({
179
+ component,
180
+ state: { componentIdentifierName: {} },
181
+ }))).toMatchInlineSnapshot(`
182
+ "<Story name="Default" tags={["svelte-csf-v4"]}>
183
+ {#snippet template(_args, context)}
184
+ <p>{context.id}</p>
185
+ {/snippet}
186
+ </Story>"
187
+ `);
188
+ });
189
+ it("when both directives 'let:args' and 'let:context' is used then it wraps Story fragment with 'template' snippet block", async ({ expect, }) => {
190
+ const code = `
191
+ <script context="module">
192
+ import { Story } from "@storybook/addon-svelte-csf";
193
+ </script>
194
+
195
+ <Story name="Default" let:args let:context>
196
+ <h1>{args.title}</h1>
197
+ <p>{context.id}</p>
198
+ </Story>
199
+ `;
200
+ const component = await parseAndExtractSvelteNode(code, 'Component');
201
+ expect(print(transformLegacyStory({
202
+ component,
203
+ state: { componentIdentifierName: {} },
204
+ }))).toMatchInlineSnapshot(`
205
+ "<Story name="Default" tags={["svelte-csf-v4"]}>
206
+ {#snippet template(args, context)}
207
+ <h1>{args.title}</h1>
208
+ <p>{context.id}</p>
209
+ {/snippet}
210
+ </Story>"
211
+ `);
212
+ });
213
+ it('leaves existing Story parameters untouched', async ({ expect }) => {
214
+ const code = `
215
+ <script context="module">
216
+ import { Story } from "@storybook/addon-svelte-csf";
217
+ </script>
218
+
219
+ <Story
220
+ name="Default"
221
+ parameters={{
222
+ sveltekit_experimental: {
223
+ stores: {
224
+ page: {
225
+ data: {
226
+ test: 'passed',
227
+ },
228
+ },
229
+ navigating: {
230
+ route: {
231
+ id: '/storybook',
232
+ },
233
+ },
234
+ updated: true,
235
+ },
236
+ },
237
+ }}
238
+ >
239
+ <h1>{"Test"}</h1>
240
+ </Story>
241
+ `;
242
+ const component = await parseAndExtractSvelteNode(code, 'Component');
243
+ expect(print(transformLegacyStory({
244
+ component,
245
+ state: { componentIdentifierName: {} },
246
+ }))).toMatchInlineSnapshot(`
247
+ "<Story name="Default" parameters={{
248
+ sveltekit_experimental: {
249
+ stores: {
250
+ page: { data: { test: 'passed' } },
251
+ navigating: { route: { id: '/storybook' } },
252
+ updated: true
253
+ }
254
+ }
255
+ }} tags={["svelte-csf-v4"]}>
256
+ <h1>{"Test"}</h1>
257
+ </Story>"
258
+ `);
259
+ });
260
+ it('legacy `source` prop with template literal value is supported _(moved to parameters)_', async ({ expect, }) => {
261
+ const code = `
262
+ <script context="module">
263
+ import { Story } from "@storybook/addon-svelte-csf";
264
+ </script>
265
+
266
+ <Story
267
+ name="Default"
268
+ source={\`
269
+ <Foo bar />
270
+ \`}
271
+ >
272
+ <h1>{"Test"}</h1>
273
+ </Story>
274
+ `;
275
+ const component = await parseAndExtractSvelteNode(code, 'Component');
276
+ expect(print(transformLegacyStory({
277
+ component,
278
+ state: { componentIdentifierName: {} },
279
+ }))).toMatchInlineSnapshot(`
280
+ "<Story name="Default" parameters={{
281
+ docs: { source: { code: "\\n <Foo bar />\\n " } }
282
+ }} tags={["svelte-csf-v4"]}>
283
+ <h1>{"Test"}</h1>
284
+ </Story>"
285
+ `);
286
+ });
287
+ });