diff --git a/.circleci/config.yml b/.circleci/config.yml index dac362b5530b..6db12bf41959 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -614,22 +614,22 @@ workflows: requires: - build - create-sandboxes: - parallelism: 35 + parallelism: 36 requires: - build # - smoke-test-sandboxes: # disabled for now # requires: # - create-sandboxes - build-sandboxes: - parallelism: 35 + parallelism: 36 requires: - create-sandboxes - chromatic-sandboxes: - parallelism: 32 + parallelism: 33 requires: - build-sandboxes - e2e-production: - parallelism: 30 + parallelism: 31 requires: - build-sandboxes - e2e-dev: @@ -637,7 +637,7 @@ workflows: requires: - create-sandboxes - test-runner-production: - parallelism: 30 + parallelism: 31 requires: - build-sandboxes # TODO: reenable once we find out the source of flakyness diff --git a/code/e2e-tests/addon-actions.spec.ts b/code/e2e-tests/addon-actions.spec.ts index 520c2b5dc41f..a9f32e61c022 100644 --- a/code/e2e-tests/addon-actions.spec.ts +++ b/code/e2e-tests/addon-actions.spec.ts @@ -3,9 +3,16 @@ import process from 'process'; import { SbPage } from './util'; const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; +const templateName = process.env.STORYBOOK_TEMPLATE_NAME || ''; test.describe('addon-actions', () => { test('should trigger an action', async ({ page }) => { + // eslint-disable-next-line jest/no-disabled-tests + test.skip( + // eslint-disable-next-line jest/valid-title + templateName.includes('svelte') && templateName.includes('prerelease'), + 'Svelte 5 prerelase does not support automatic actions with our current example components yet' + ); await page.goto(storybookUrl); const sbPage = new SbPage(page); sbPage.waitUntilLoaded(); diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 585a77752bed..4cfe87214037 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -52,18 +52,18 @@ "@storybook/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^2.4.2", "magic-string": "^0.30.0", - "svelte-preprocess": "^5.0.4", + "svelte-preprocess": "^5.1.1", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0" }, "devDependencies": { "@types/node": "^18.0.0", - "svelte": "^4.0.0", + "svelte": "^5.0.0-next.16", "typescript": "^5.3.2", "vite": "^4.0.0" }, "peerDependencies": { - "svelte": "^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "engines": { diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 9e47d3bb34ee..4885a726417b 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -59,7 +59,7 @@ }, "peerDependencies": { "@babel/core": "*", - "svelte": "^3.48.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "svelte-loader": "*" }, "engines": { diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index f952e2515b07..162fb8229411 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -64,7 +64,7 @@ "vite": "^4.0.0" }, "peerDependencies": { - "svelte": "^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "vite": "^4.0.0" }, "engines": { diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte new file mode 100644 index 000000000000..cd00f38a3d57 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte @@ -0,0 +1,38 @@ + + +
A little text to show this is a view.
+If we need to test components in a Svelte environment, for instance to test slot behaviour,
+then wrapping the component up in a view
+made just for the story is the simplest way to achieve this.
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte new file mode 100644 index 000000000000..371a17656bea --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte new file mode 100644 index 000000000000..4e7d69e0e051 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte @@ -0,0 +1,8 @@ + diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte new file mode 100644 index 000000000000..4bcb7d0e6fc9 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte @@ -0,0 +1,25 @@ + + + + + + + diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte new file mode 100644 index 000000000000..164b00f7fa8b --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte @@ -0,0 +1,17 @@ + + +Directly importing
+{JSON.stringify($page, null, 2)}
+{JSON.stringify($navigating, null, 2)}
+{JSON.stringify($updated, null, 2)}
+
+With getStores
+{JSON.stringify($pageStore, null, 2)}
+{JSON.stringify($navigatingStore, null, 2)}
+{JSON.stringify($updatedStore, null, 2)}
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js
new file mode 100644
index 000000000000..72b584baef76
--- /dev/null
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js
@@ -0,0 +1,26 @@
+import { expect, fn, within } from '@storybook/test';
+import Forms from './Forms.svelte';
+
+export default {
+ title: 'stories/sveltekit/modules/forms',
+ component: Forms,
+ tags: ['autodocs'],
+};
+
+const enhance = fn();
+
+export const Enhance = {
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('enhance');
+ button.click();
+ expect(enhance).toHaveBeenCalled();
+ },
+ parameters: {
+ sveltekit_experimental: {
+ forms: {
+ enhance,
+ },
+ },
+ },
+};
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js
new file mode 100644
index 000000000000..f1cbf4973534
--- /dev/null
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js
@@ -0,0 +1,53 @@
+import { expect, fn, within } from '@storybook/test';
+import Hrefs from './Hrefs.svelte';
+
+export default {
+ title: 'stories/sveltekit/modules/hrefs',
+ component: Hrefs,
+ tags: ['autodocs'],
+};
+
+export const DefaultActions = {
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ // eslint-disable-next-line no-undef
+ const initialUrl = window.location.toString();
+
+ const basicHref = canvas.getByText('/basic-href');
+ basicHref.click();
+
+ const complexHref = canvas.getByText(
+ '/deep/nested/link?with=true&multiple-params=200#and-an-id'
+ );
+ complexHref.click();
+
+ // eslint-disable-next-line no-undef
+ const finalUrl = window.location.toString();
+ expect(finalUrl).toBe(initialUrl);
+ },
+};
+
+const basicStringMatch = fn();
+const noMatch = fn();
+const exactStringMatch = fn();
+const regexMatch = fn();
+
+export const Callbacks = {
+ parameters: {
+ sveltekit_experimental: {
+ hrefs: {
+ '/basic-href': basicStringMatch,
+ '/basic': noMatch,
+ '/deep/nested/link?with=true&multiple-params=200#and-an-id': exactStringMatch,
+ 'nested/link\\?with': { callback: regexMatch, asRegex: true },
+ },
+ },
+ },
+ play: async (ctx) => {
+ await DefaultActions.play(ctx);
+ expect(basicStringMatch).toHaveBeenCalledTimes(1);
+ expect(noMatch).not.toHaveBeenCalled();
+ expect(exactStringMatch).toHaveBeenCalledTimes(1);
+ expect(regexMatch).toHaveBeenCalledTimes(1);
+ },
+};
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js
new file mode 100644
index 000000000000..ded12268e03c
--- /dev/null
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js
@@ -0,0 +1,84 @@
+import { expect, fn, within } from '@storybook/test';
+import Navigation from './Navigation.svelte';
+
+export default {
+ title: 'stories/sveltekit/modules/navigation',
+ component: Navigation,
+ tags: ['autodocs'],
+};
+
+const goto = fn();
+
+export const Goto = {
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('goto');
+ button.click();
+ expect(goto).toHaveBeenCalledWith('/storybook-goto');
+ },
+ parameters: {
+ sveltekit_experimental: {
+ navigation: {
+ goto,
+ },
+ },
+ },
+};
+
+export const DefaultActions = {};
+
+const invalidate = fn();
+
+export const Invalidate = {
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('invalidate', { exact: true });
+ button.click();
+ expect(invalidate).toHaveBeenCalledWith('/storybook-invalidate');
+ },
+ parameters: {
+ sveltekit_experimental: {
+ navigation: {
+ invalidate,
+ },
+ },
+ },
+};
+
+const invalidateAll = fn();
+
+export const InvalidateAll = {
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const button = canvas.getByText('invalidateAll');
+ button.click();
+ expect(invalidateAll).toHaveBeenCalledWith();
+ },
+ parameters: {
+ sveltekit_experimental: {
+ navigation: {
+ invalidateAll,
+ },
+ },
+ },
+};
+
+const afterNavigateFn = fn();
+
+export const AfterNavigate = {
+ async play() {
+ expect(afterNavigateFn).toHaveBeenCalledWith({ test: 'passed' });
+ },
+ args: {
+ afterNavigateFn,
+ },
+ parameters: {
+ sveltekit_experimental: {
+ navigation: {
+ afterNavigate: {
+ test: 'passed',
+ },
+ },
+ },
+ },
+};
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js
new file mode 100644
index 000000000000..7f7401cf8bee
--- /dev/null
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js
@@ -0,0 +1,116 @@
+import Stores from './Stores.svelte';
+
+export default {
+ title: 'stories/sveltekit/modules/stores',
+ component: Stores,
+ tags: ['autodocs'],
+};
+
+export const AllUndefined = {};
+
+export const PageStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ page: {
+ data: {
+ test: 'passed',
+ },
+ },
+ },
+ },
+ },
+};
+
+export const NavigatingStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ navigating: {
+ route: {
+ id: '/storybook',
+ },
+ },
+ },
+ },
+ },
+};
+
+export const UpdatedStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ updated: true,
+ },
+ },
+ },
+};
+
+export const PageAndNavigatingStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ page: {
+ data: {
+ test: 'passed',
+ },
+ },
+ navigating: {
+ route: {
+ id: '/storybook',
+ },
+ },
+ },
+ },
+ },
+};
+
+export const PageAndUpdatedStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ page: {
+ data: {
+ test: 'passed',
+ },
+ },
+ updated: true,
+ },
+ },
+ },
+};
+
+export const NavigatingAndUpdatedStore = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ navigating: {
+ route: {
+ id: '/storybook',
+ },
+ },
+ updated: true,
+ },
+ },
+ },
+};
+
+export const AllThreeStores = {
+ parameters: {
+ sveltekit_experimental: {
+ stores: {
+ page: {
+ data: {
+ test: 'passed',
+ },
+ },
+ navigating: {
+ route: {
+ id: '/storybook',
+ },
+ },
+ updated: true,
+ },
+ },
+ },
+};
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js
new file mode 100644
index 000000000000..f33428810ee9
--- /dev/null
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js
@@ -0,0 +1,12 @@
+import ButtonTypescript from './ButtonTypeScript.svelte';
+
+export default {
+ title: 'stories/renderers/svelte/ts-docs',
+ component: ButtonTypescript,
+ args: {
+ primary: true,
+ },
+ tags: ['autodocs'],
+};
+
+export const Primary = {};
diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts
index 24fb3dc9846f..bcd5b470dcac 100644
--- a/code/lib/cli/src/sandbox-templates.ts
+++ b/code/lib/cli/src/sandbox-templates.ts
@@ -356,6 +356,17 @@ const baseTemplates = {
},
skipTasks: ['e2e-tests-dev', 'bench'],
},
+ 'svelte-kit/prerelease-ts': {
+ name: 'SvelteKit Prerelease (Vite | TypeScript)',
+ script:
+ 'yarn create svelte-with-args --name=svelte-kit/prerelease-ts --directory={{beforeDir}} --template=skeleton --types=typescript --no-prettier --no-eslint --no-playwright --no-vitest --svelte5',
+ expected: {
+ framework: '@storybook/sveltekit',
+ renderer: '@storybook/svelte',
+ builder: '@storybook/builder-vite',
+ },
+ skipTasks: ['e2e-tests-dev', 'bench'],
+ },
'lit-vite/default-js': {
name: 'Lit Latest (Vite | JavaScript)',
script:
@@ -599,6 +610,7 @@ export const daily: TemplateKey[] = [
'vue-cli/default-js',
'lit-vite/default-js',
'svelte-kit/skeleton-js',
+ 'svelte-kit/prerelease-ts',
'svelte-vite/default-js',
'nextjs/13-ts',
'nextjs/default-js',
diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json
index fca64af0725c..2792fa28bc32 100644
--- a/code/presets/svelte-webpack/package.json
+++ b/code/presets/svelte-webpack/package.json
@@ -76,7 +76,7 @@
},
"peerDependencies": {
"@babel/core": "*",
- "svelte": "^3.1.0 || ^4.0.0",
+ "svelte": "^4.0.0 || ^5.0.0-next.16",
"svelte-loader": "*"
},
"engines": {
diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json
index 74eae303430f..c7b3ad589592 100644
--- a/code/renderers/svelte/package.json
+++ b/code/renderers/svelte/package.json
@@ -63,12 +63,12 @@
},
"devDependencies": {
"expect-type": "^0.15.0",
- "svelte": "^4.0.0",
- "svelte-check": "3.4.6",
+ "svelte": "^5.0.0-next.15",
+ "svelte-check": "^3.6.1",
"typescript": "^5.3.2"
},
"peerDependencies": {
- "svelte": "^3.1.0 || ^4.0.0"
+ "svelte": "^4.0.0 || ^5.0.0-next.16"
},
"engines": {
"node": ">=16.0.0"
diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts
index cfde36047fa1..b1821b692358 100644
--- a/code/renderers/svelte/src/render.ts
+++ b/code/renderers/svelte/src/render.ts
@@ -1,6 +1,5 @@
/* eslint-disable no-param-reassign */
import type { RenderContext, ArgsStoryFn } from '@storybook/types';
-import type { SvelteComponentTyped } from 'svelte';
import { RESET_STORY_ARGS } from '@storybook/core-events';
// ! DO NOT change this PreviewRender import to a relative path, it will break it.
// ! A relative import will be compiled at build time, and Svelte will be unable to
@@ -10,10 +9,14 @@ import { RESET_STORY_ARGS } from '@storybook/core-events';
// eslint-disable-next-line import/no-extraneous-dependencies
import PreviewRender from '@storybook/svelte/templates/PreviewRender.svelte';
import { addons } from '@storybook/preview-api';
+import * as svelte from 'svelte';
import type { SvelteRenderer } from './types';
-const componentsByDomElement = new Map