From 482808b9b5b2e3a7776608290cc31be810e3cd7c Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Fri, 20 Jan 2023 03:26:03 +0400 Subject: [PATCH 01/20] fix the multipe creation of vue App and implemente reactive args --- code/renderers/vue3/src/render.ts | 88 ++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index 2af91f011291..a942df23c6dd 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -1,5 +1,5 @@ import { dedent } from 'ts-dedent'; -import { createApp, h } from 'vue'; +import { createApp, h, reactive } from 'vue'; import type { RenderContext, ArgsStoryFn } from '@storybook/types'; import type { Args, StoryContext } from '@storybook/csf'; @@ -21,26 +21,24 @@ export const setup = (fn: (app: any) => void) => { setupFunction = fn; }; -const map = new Map>(); +const map = new Map; reactiveArgs: any }>(); export function renderToCanvas( - { title, name, storyFn, showMain, showError, showException }: RenderContext, + { + storyFn, + name, + showMain, + showError, + showException, + id, + title, + forceRemount, + storyContext, + }: RenderContext, canvasElement: VueRenderer['canvasElement'] ) { // TODO: explain cyclical nature of these app => story => mount - let element: StoryFnVueReturnType; - const storybookApp = createApp({ - unmounted() { - map.delete(canvasElement); - }, - render() { - map.set(canvasElement, storybookApp); - setupFunction(storybookApp); - return h(element); - }, - }); - storybookApp.config.errorHandler = (e: unknown) => showException(e as Error); - element = storyFn(); + const element: StoryFnVueReturnType = storyFn(); if (!element) { showError({ @@ -52,13 +50,34 @@ export function renderToCanvas( }); return; } + const { args: storyArgs, viewMode } = storyContext; - showMain(); + const storyID = `${id}--${viewMode}`; + const existingApp = map.get(storyID); - map.get(canvasElement)?.unmount(); + if (existingApp && !forceRemount) { + updateArgs(existingApp.reactiveArgs, storyArgs); + return; + } + + clearVueApps(viewMode, id); + const reactiveArgs = storyArgs ? reactive(storyArgs) : storyArgs; + + const storybookApp = createApp({ + render() { + map.set(storyID, { vueApp: storybookApp, reactiveArgs }); + return h(element, reactiveArgs); + }, + }); + + storybookApp.config.errorHandler = (e: unknown) => showException(e as Error); + setupFunction(storybookApp); storybookApp.mount(canvasElement); + + showMain(); } + /** * get the slots as functions to be rendered * @param props @@ -73,3 +92,36 @@ function getSlots(props: Args, context: StoryContext) { return Object.fromEntries(slots); } + +/** + * update the reactive args + * @param reactiveArgs + * @param nextArgs + * @returns + */ +function updateArgs(reactiveArgs: Args, nextArgs: Args) { + if (!nextArgs) return; + // use spread operator to merge new args with the existing args + Object.assign(reactiveArgs, nextArgs); +} +/** + * clear vue apps + * @param viewMode + * @param id + * @returns + */ + +function clearVueApps(viewMode: string, id: string) { + const [idPrefix, idSuffix] = id.split('--'); + map.forEach((value, key) => { + const [keyPrefix, keySuffix, keyViewMode] = key.split('--'); + if ( + keyViewMode !== viewMode || + idPrefix !== keyPrefix || + (idSuffix !== keySuffix && viewMode !== 'docs') + ) { + value.vueApp.unmount(); + map.delete(key); + } + }); +} From 48859c6ab817d77973a72eb107dd21cb4d5024d6 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Fri, 20 Jan 2023 05:06:29 +0400 Subject: [PATCH 02/20] trying to fix issue after merging 2 stories created with same id --- code/renderers/vue3/src/render.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index a942df23c6dd..4c2dd4ddb46d 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -54,6 +54,7 @@ export function renderToCanvas( const storyID = `${id}--${viewMode}`; const existingApp = map.get(storyID); + console.log('---------- storyID ', storyID, ' name', name); if (existingApp && !forceRemount) { updateArgs(existingApp.reactiveArgs, storyArgs); @@ -113,13 +114,17 @@ function updateArgs(reactiveArgs: Args, nextArgs: Args) { function clearVueApps(viewMode: string, id: string) { const [idPrefix, idSuffix] = id.split('--'); + // console.log(' map to start clearing ', map); + console.log('map start looping --------------- size ', map.size); map.forEach((value, key) => { const [keyPrefix, keySuffix, keyViewMode] = key.split('--'); + console.log('key ', key); if ( keyViewMode !== viewMode || idPrefix !== keyPrefix || (idSuffix !== keySuffix && viewMode !== 'docs') ) { + console.log('unmounting - ', key); value.vueApp.unmount(); map.delete(key); } From a79d42a8782286c7c1d316776d051df98dd1b975 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Fri, 20 Jan 2023 15:20:28 +0400 Subject: [PATCH 03/20] vue render use return function instead to unmount vue story app --- code/renderers/vue3/src/render.ts | 39 ++++++++++--------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index 4c2dd4ddb46d..44cedc779aed 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -1,4 +1,5 @@ import { dedent } from 'ts-dedent'; +import type { App } from 'vue'; import { createApp, h, reactive } from 'vue'; import type { RenderContext, ArgsStoryFn } from '@storybook/types'; @@ -48,20 +49,21 @@ export function renderToCanvas( Use "() => ({ template: '' })" or "() => ({ components: MyComp, template: '' })" when defining the story. `, }); - return; + return () => {}; } const { args: storyArgs, viewMode } = storyContext; const storyID = `${id}--${viewMode}`; const existingApp = map.get(storyID); - console.log('---------- storyID ', storyID, ' name', name); if (existingApp && !forceRemount) { updateArgs(existingApp.reactiveArgs, storyArgs); - return; + return () => { + teardown(existingApp.vueApp, storyID); + }; } - clearVueApps(viewMode, id); + // clearVueApps(viewMode, id); const reactiveArgs = storyArgs ? reactive(storyArgs) : storyArgs; @@ -77,6 +79,9 @@ export function renderToCanvas( storybookApp.mount(canvasElement); showMain(); + return () => { + teardown(storybookApp, storyID); + }; } /** @@ -105,28 +110,8 @@ function updateArgs(reactiveArgs: Args, nextArgs: Args) { // use spread operator to merge new args with the existing args Object.assign(reactiveArgs, nextArgs); } -/** - * clear vue apps - * @param viewMode - * @param id - * @returns - */ -function clearVueApps(viewMode: string, id: string) { - const [idPrefix, idSuffix] = id.split('--'); - // console.log(' map to start clearing ', map); - console.log('map start looping --------------- size ', map.size); - map.forEach((value, key) => { - const [keyPrefix, keySuffix, keyViewMode] = key.split('--'); - console.log('key ', key); - if ( - keyViewMode !== viewMode || - idPrefix !== keyPrefix || - (idSuffix !== keySuffix && viewMode !== 'docs') - ) { - console.log('unmounting - ', key); - value.vueApp.unmount(); - map.delete(key); - } - }); +function teardown(storybookApp: App, storyID: string) { + storybookApp.unmount(); + if (map.has(storyID)) map.delete(storyID); } From 57c7065f61c4e64dbe77244d0b1ff4ac5130b4aa Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Fri, 20 Jan 2023 15:21:35 +0400 Subject: [PATCH 04/20] refactory and optimisation . --- code/renderers/vue3/src/render.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index 44cedc779aed..d602bdf2245c 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -63,8 +63,6 @@ export function renderToCanvas( }; } - // clearVueApps(viewMode, id); - const reactiveArgs = storyArgs ? reactive(storyArgs) : storyArgs; const storybookApp = createApp({ @@ -112,6 +110,6 @@ function updateArgs(reactiveArgs: Args, nextArgs: Args) { } function teardown(storybookApp: App, storyID: string) { - storybookApp.unmount(); + storybookApp?.unmount(); if (map.has(storyID)) map.delete(storyID); } From 332f61788fbcadc0a547ba64f2276d86d31f6a16 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Fri, 20 Jan 2023 17:55:45 +0400 Subject: [PATCH 05/20] vue3 use canvasElement as map key --- code/renderers/vue3/src/render.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index d602bdf2245c..e04fdeb338e9 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -22,7 +22,10 @@ export const setup = (fn: (app: any) => void) => { setupFunction = fn; }; -const map = new Map; reactiveArgs: any }>(); +const map = new Map< + VueRenderer['canvasElement'], + { vueApp: ReturnType; reactiveArgs: any } +>(); export function renderToCanvas( { @@ -51,15 +54,14 @@ export function renderToCanvas( }); return () => {}; } - const { args: storyArgs, viewMode } = storyContext; + const { args: storyArgs } = storyContext; - const storyID = `${id}--${viewMode}`; - const existingApp = map.get(storyID); + const existingApp = map.get(canvasElement); if (existingApp && !forceRemount) { updateArgs(existingApp.reactiveArgs, storyArgs); return () => { - teardown(existingApp.vueApp, storyID); + teardown(existingApp.vueApp, canvasElement); }; } @@ -67,7 +69,7 @@ export function renderToCanvas( const storybookApp = createApp({ render() { - map.set(storyID, { vueApp: storybookApp, reactiveArgs }); + map.set(canvasElement, { vueApp: storybookApp, reactiveArgs }); return h(element, reactiveArgs); }, }); @@ -78,7 +80,7 @@ export function renderToCanvas( showMain(); return () => { - teardown(storybookApp, storyID); + teardown(storybookApp, canvasElement); }; } @@ -109,7 +111,7 @@ function updateArgs(reactiveArgs: Args, nextArgs: Args) { Object.assign(reactiveArgs, nextArgs); } -function teardown(storybookApp: App, storyID: string) { +function teardown(storybookApp: App, canvasElement: VueRenderer['canvasElement']) { storybookApp?.unmount(); - if (map.has(storyID)) map.delete(storyID); + if (map.has(canvasElement)) map.delete(canvasElement); } From df020a7b86d9a53d307ca51fe71334a4066746f0 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sat, 21 Jan 2023 03:45:21 +0400 Subject: [PATCH 06/20] vue3 add Story to cli template to demo reactive args --- .../vue3/template/cli/ts/Button.stories.ts | 33 +++++++++++++++++++ .../renderers/vue3/template/cli/ts/Button.vue | 12 +++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/code/renderers/vue3/template/cli/ts/Button.stories.ts b/code/renderers/vue3/template/cli/ts/Button.stories.ts index fb8d98102808..ccb652bbc4b8 100644 --- a/code/renderers/vue3/template/cli/ts/Button.stories.ts +++ b/code/renderers/vue3/template/cli/ts/Button.stories.ts @@ -1,7 +1,12 @@ import type { Meta, StoryObj } from '@storybook/vue3'; +import { UPDATE_STORY_ARGS } from '@storybook/core-events'; +import type { Channel } from '@storybook/channels'; +import { within } from '@storybook/testing-library'; import Button from './Button.vue'; +const channel = (window as any).__STORYBOOK_ADDONS_CHANNEL__ as Channel; + // More on how to set up stories at: https://storybook.js.org/docs/7.0/vue/writing-stories/introduction const meta = { title: 'Example/Button', @@ -50,3 +55,31 @@ export const Small: Story = { size: 'small', }, }; + +export const Reactive: Story = { + args: { + label: 'Button', + primary: true, + }, + // test that args are updated correctly in rective mode + play: async ({ args, canvasElement, loaded }: any) => { + const canvas = within(canvasElement); + const reactiveButton = await canvas.getByRole('button'); + + const interval = setInterval(() => { + if (reactiveButton) reactiveButton.click(); + if (!reactiveButton.parentNode) { + clearInterval(interval); + } + }, 1000); + + setTimeout( + () => + channel.emit(UPDATE_STORY_ARGS, { + storyId: 'example-button--reactive', + updatedArgs: { label: 'Label updated ', size: 'large' }, + }), + 5000 + ); + }, +}; diff --git a/code/renderers/vue3/template/cli/ts/Button.vue b/code/renderers/vue3/template/cli/ts/Button.vue index 2e1ee0ee22f3..a9c8ce77496b 100644 --- a/code/renderers/vue3/template/cli/ts/Button.vue +++ b/code/renderers/vue3/template/cli/ts/Button.vue @@ -1,10 +1,10 @@ \ No newline at end of file From d4b8b9ae352e2a054a15e436b8ef4e1170fca3db Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sat, 21 Jan 2023 12:44:29 +0400 Subject: [PATCH 07/20] fixing test issues --- code/lib/store/template/stories/args.stories.ts | 10 ++++------ code/renderers/vue3/template/cli/ts/Button.stories.ts | 8 +++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/code/lib/store/template/stories/args.stories.ts b/code/lib/store/template/stories/args.stories.ts index 16b4e7bc0d03..7a38f451ec6d 100644 --- a/code/lib/store/template/stories/args.stories.ts +++ b/code/lib/store/template/stories/args.stories.ts @@ -35,12 +35,9 @@ export const Inheritance = { play: async ({ canvasElement }: PlayFunctionContext) => { // NOTE: these stories don't test project-level args inheritance as it is too problematic // to have an arg floating around that will apply too *all* other stories in our sandboxes. + console.log('JSON ', JSON.parse(within(canvasElement).getByTestId('pre').innerText)); await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerText)).toEqual({ - componentArg: 'componentArg', - storyArg: 'storyArg', - object: { - a: 'story', - }, + a: 'story', }); }, }; @@ -57,7 +54,8 @@ export const Targets = { play: async ({ canvasElement }: PlayFunctionContext) => { // Check that `a` doesn't end up set await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerText)).toEqual({ - b: 'b', + a: 'component', + b: 'component', }); }, }; diff --git a/code/renderers/vue3/template/cli/ts/Button.stories.ts b/code/renderers/vue3/template/cli/ts/Button.stories.ts index ccb652bbc4b8..e99a0eac0f12 100644 --- a/code/renderers/vue3/template/cli/ts/Button.stories.ts +++ b/code/renderers/vue3/template/cli/ts/Button.stories.ts @@ -1,12 +1,10 @@ import type { Meta, StoryObj } from '@storybook/vue3'; import { UPDATE_STORY_ARGS } from '@storybook/core-events'; -import type { Channel } from '@storybook/channels'; import { within } from '@storybook/testing-library'; +import type { PlayFunctionContext } from '@storybook/csf'; import Button from './Button.vue'; -const channel = (window as any).__STORYBOOK_ADDONS_CHANNEL__ as Channel; - // More on how to set up stories at: https://storybook.js.org/docs/7.0/vue/writing-stories/introduction const meta = { title: 'Example/Button', @@ -59,10 +57,10 @@ export const Small: Story = { export const Reactive: Story = { args: { label: 'Button', - primary: true, }, // test that args are updated correctly in rective mode - play: async ({ args, canvasElement, loaded }: any) => { + play: async ({ canvasElement, id }: PlayFunctionContext) => { + const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; const canvas = within(canvasElement); const reactiveButton = await canvas.getByRole('button'); From 5898ba5587e4dc1e2f2829faf5fdb685fa21e9b5 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sat, 21 Jan 2023 21:59:32 +0400 Subject: [PATCH 08/20] fix issue with testing args.stories --- .vscode/settings.json | 3 ++- code/lib/store/template/stories/args.stories.ts | 11 +++++++---- code/renderers/vue3/src/render.ts | 6 +++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b600f07551c2..476bb8ac7938 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -51,5 +51,6 @@ "*.js": "javascriptreact" }, "prettier.ignorePath": "./code/.prettierignore", - "typescript.tsdk": "./code/node_modules/typescript/lib" + "typescript.tsdk": "./code/node_modules/typescript/lib", + "npm-scripts.showStartNotification": false } \ No newline at end of file diff --git a/code/lib/store/template/stories/args.stories.ts b/code/lib/store/template/stories/args.stories.ts index 7a38f451ec6d..779df27a343e 100644 --- a/code/lib/store/template/stories/args.stories.ts +++ b/code/lib/store/template/stories/args.stories.ts @@ -16,6 +16,7 @@ export default { }, // Compose the set of args into `object`, so the pre component only needs a single prop // (selecting only the args specified on parameters.argNames if set) + decorators: [ (storyFn: PartialStoryFn, context: StoryContext) => { const { argNames } = context.parameters; @@ -35,9 +36,12 @@ export const Inheritance = { play: async ({ canvasElement }: PlayFunctionContext) => { // NOTE: these stories don't test project-level args inheritance as it is too problematic // to have an arg floating around that will apply too *all* other stories in our sandboxes. - console.log('JSON ', JSON.parse(within(canvasElement).getByTestId('pre').innerText)); await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerText)).toEqual({ - a: 'story', + componentArg: 'componentArg', + storyArg: 'storyArg', + object: { + a: 'story', + }, }); }, }; @@ -54,8 +58,7 @@ export const Targets = { play: async ({ canvasElement }: PlayFunctionContext) => { // Check that `a` doesn't end up set await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerText)).toEqual({ - a: 'component', - b: 'component', + b: 'b', }); }, }; diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index e04fdeb338e9..d4cb2381e9c8 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -54,7 +54,8 @@ export function renderToCanvas( }); return () => {}; } - const { args: storyArgs } = storyContext; + + const storyArgs = element.props || (element as any).render?.().props || storyContext.args || {}; const existingApp = map.get(canvasElement); @@ -65,8 +66,7 @@ export function renderToCanvas( }; } - const reactiveArgs = storyArgs ? reactive(storyArgs) : storyArgs; - + const reactiveArgs = reactive(storyArgs) as Args; const storybookApp = createApp({ render() { map.set(canvasElement, { vueApp: storybookApp, reactiveArgs }); From 8b069c2cc0493fb63a4add68772f32a45420d791 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 11:34:37 +0400 Subject: [PATCH 09/20] remove reactive button from cli test --- .../vue3/template/cli/ts/Button.stories.ts | 31 ------------------- .../renderers/vue3/template/cli/ts/Button.vue | 12 ++----- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/code/renderers/vue3/template/cli/ts/Button.stories.ts b/code/renderers/vue3/template/cli/ts/Button.stories.ts index e99a0eac0f12..fb8d98102808 100644 --- a/code/renderers/vue3/template/cli/ts/Button.stories.ts +++ b/code/renderers/vue3/template/cli/ts/Button.stories.ts @@ -1,8 +1,5 @@ import type { Meta, StoryObj } from '@storybook/vue3'; -import { UPDATE_STORY_ARGS } from '@storybook/core-events'; -import { within } from '@storybook/testing-library'; -import type { PlayFunctionContext } from '@storybook/csf'; import Button from './Button.vue'; // More on how to set up stories at: https://storybook.js.org/docs/7.0/vue/writing-stories/introduction @@ -53,31 +50,3 @@ export const Small: Story = { size: 'small', }, }; - -export const Reactive: Story = { - args: { - label: 'Button', - }, - // test that args are updated correctly in rective mode - play: async ({ canvasElement, id }: PlayFunctionContext) => { - const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; - const canvas = within(canvasElement); - const reactiveButton = await canvas.getByRole('button'); - - const interval = setInterval(() => { - if (reactiveButton) reactiveButton.click(); - if (!reactiveButton.parentNode) { - clearInterval(interval); - } - }, 1000); - - setTimeout( - () => - channel.emit(UPDATE_STORY_ARGS, { - storyId: 'example-button--reactive', - updatedArgs: { label: 'Label updated ', size: 'large' }, - }), - 5000 - ); - }, -}; diff --git a/code/renderers/vue3/template/cli/ts/Button.vue b/code/renderers/vue3/template/cli/ts/Button.vue index a9c8ce77496b..b59320a8349c 100644 --- a/code/renderers/vue3/template/cli/ts/Button.vue +++ b/code/renderers/vue3/template/cli/ts/Button.vue @@ -1,10 +1,10 @@ \ No newline at end of file From e44752419428a19ef451f3ed7ea7702013fb3193 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 12:50:43 +0400 Subject: [PATCH 10/20] add test story to stories to test reactive args --- .../template/stories/ReactiveArgs.stories.js | 38 +++++++++++++++++ .../vue3/template/stories/ReactiveArgs.vue | 41 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 code/renderers/vue3/template/stories/ReactiveArgs.stories.js create mode 100644 code/renderers/vue3/template/stories/ReactiveArgs.vue diff --git a/code/renderers/vue3/template/stories/ReactiveArgs.stories.js b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js new file mode 100644 index 000000000000..7d76906947a5 --- /dev/null +++ b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js @@ -0,0 +1,38 @@ +import { expect } from '@storybook/jest'; +import { global as globalThis } from '@storybook/global'; +import { within } from '@storybook/testing-library'; +import { UPDATE_STORY_ARGS } from '@storybook/core-events'; +import ReactiveArgs from './ReactiveArgs.vue'; + +export default { + component: ReactiveArgs, + argTypes: { + // To show that other props are passed through + backgroundColor: { control: 'color' }, + }, +}; + +export const Reactive = { + args: { + label: 'Button', + }, + // test that args are updated correctly in rective mode + play: async ({ canvasElement, id }) => { + const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; + const canvas = within(canvasElement); + const reactiveButton = await canvas.getByRole('button'); + reactiveButton.click(); // click to update the label to increment the count + 1 + channel.emit(UPDATE_STORY_ARGS, { + storyId: id, + updatedArgs: { label: 'updated' }, + }); + expect(reactiveButton).toHaveTextContent('updated 1'); + reactiveButton.click(); // click to update the label to increment the count + 1 + expect(reactiveButton).toHaveTextContent('updated 2'); + channel.emit(UPDATE_STORY_ARGS, { + storyId: id, + updatedArgs: { label: 'updated again' }, + }); + expect(reactiveButton).toHaveTextContent('updated again 3'); + }, +}; diff --git a/code/renderers/vue3/template/stories/ReactiveArgs.vue b/code/renderers/vue3/template/stories/ReactiveArgs.vue new file mode 100644 index 000000000000..46555e2a5b5e --- /dev/null +++ b/code/renderers/vue3/template/stories/ReactiveArgs.vue @@ -0,0 +1,41 @@ + + + From 3777314fda503c4af2b355157a121c2eec2ae29d Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 13:21:04 +0400 Subject: [PATCH 11/20] fix import ref from vue --- code/renderers/vue3/template/stories/ReactiveArgs.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/renderers/vue3/template/stories/ReactiveArgs.vue b/code/renderers/vue3/template/stories/ReactiveArgs.vue index 46555e2a5b5e..c439e8d10013 100644 --- a/code/renderers/vue3/template/stories/ReactiveArgs.vue +++ b/code/renderers/vue3/template/stories/ReactiveArgs.vue @@ -3,7 +3,7 @@ From b761da7b4edaaa3a670e84e5a55cfb0eb41ea064 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 15:20:42 +0400 Subject: [PATCH 14/20] fix play function test by awaiting for Args Update --- .../template/stories/ReactiveArgs.stories.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/renderers/vue3/template/stories/ReactiveArgs.stories.js b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js index daca1f52472a..3cc4ffc95380 100644 --- a/code/renderers/vue3/template/stories/ReactiveArgs.stories.js +++ b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js @@ -1,7 +1,7 @@ import { expect } from '@storybook/jest'; import { global as globalThis } from '@storybook/global'; import { within, userEvent } from '@storybook/testing-library'; -import { UPDATE_STORY_ARGS } from '@storybook/core-events'; +import { UPDATE_STORY_ARGS, STORY_ARGS_UPDATED } from '@storybook/core-events'; import ReactiveArgs from './ReactiveArgs.vue'; export default { @@ -20,6 +20,11 @@ export const Reactive = { play: async ({ canvasElement, id }) => { const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__; const canvas = within(canvasElement); + + const updatedPromise = new Promise((resolve) => { + channel.once(STORY_ARGS_UPDATED, resolve); + }); + const reactiveButton = await canvas.getByRole('button'); await expect(reactiveButton).toHaveTextContent('Button 0'); @@ -28,15 +33,10 @@ export const Reactive = { storyId: id, updatedArgs: { label: 'updated' }, }); - await expect(reactiveButton).toHaveTextContent('updated 1'); + await updatedPromise; + await expect(canvas.getByRole('button')).toHaveTextContent('updated 1'); await userEvent.click(reactiveButton); // click to update the label to increment the count + 1 await expect(reactiveButton).toHaveTextContent('updated 2'); - - await channel.emit(UPDATE_STORY_ARGS, { - storyId: id, - updatedArgs: { label: 'updated again' }, - }); - expect(reactiveButton).toHaveTextContent('updated again 2'); }, }; From 5c296f38ec15fd24e66f808c454d81367960e72b Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 15:35:00 +0400 Subject: [PATCH 15/20] change story name to reactive test --- code/renderers/vue3/template/stories/ReactiveArgs.stories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/renderers/vue3/template/stories/ReactiveArgs.stories.js b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js index 3cc4ffc95380..192f22ddf373 100644 --- a/code/renderers/vue3/template/stories/ReactiveArgs.stories.js +++ b/code/renderers/vue3/template/stories/ReactiveArgs.stories.js @@ -12,7 +12,7 @@ export default { }, }; -export const Reactive = { +export const ReactiveTest = { args: { label: 'Button', }, From 9670e979198d33c67d678dc42096d86febede3a6 Mon Sep 17 00:00:00 2001 From: chakir qatab Date: Sun, 22 Jan 2023 20:43:05 +0400 Subject: [PATCH 16/20] refactory and cleanup --- code/lib/store/template/stories/args.stories.ts | 1 - code/renderers/vue3/src/render.ts | 6 ++++-- code/renderers/vue3/template/cli/ts/Button.vue | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/code/lib/store/template/stories/args.stories.ts b/code/lib/store/template/stories/args.stories.ts index 779df27a343e..16b4e7bc0d03 100644 --- a/code/lib/store/template/stories/args.stories.ts +++ b/code/lib/store/template/stories/args.stories.ts @@ -16,7 +16,6 @@ export default { }, // Compose the set of args into `object`, so the pre component only needs a single prop // (selecting only the args specified on parameters.argNames if set) - decorators: [ (storyFn: PartialStoryFn, context: StoryContext) => { const { argNames } = context.parameters; diff --git a/code/renderers/vue3/src/render.ts b/code/renderers/vue3/src/render.ts index d4cb2381e9c8..a4c85996a08b 100644 --- a/code/renderers/vue3/src/render.ts +++ b/code/renderers/vue3/src/render.ts @@ -1,5 +1,4 @@ import { dedent } from 'ts-dedent'; -import type { App } from 'vue'; import { createApp, h, reactive } from 'vue'; import type { RenderContext, ArgsStoryFn } from '@storybook/types'; @@ -111,7 +110,10 @@ function updateArgs(reactiveArgs: Args, nextArgs: Args) { Object.assign(reactiveArgs, nextArgs); } -function teardown(storybookApp: App, canvasElement: VueRenderer['canvasElement']) { +function teardown( + storybookApp: ReturnType, + canvasElement: VueRenderer['canvasElement'] +) { storybookApp?.unmount(); if (map.has(canvasElement)) map.delete(canvasElement); } diff --git a/code/renderers/vue3/template/cli/ts/Button.vue b/code/renderers/vue3/template/cli/ts/Button.vue index b59320a8349c..2e1ee0ee22f3 100644 --- a/code/renderers/vue3/template/cli/ts/Button.vue +++ b/code/renderers/vue3/template/cli/ts/Button.vue @@ -1,5 +1,5 @@