From d853f2032b8e88409b0c9db205006252854da906 Mon Sep 17 00:00:00 2001 From: nutboltu Date: Fri, 7 Oct 2022 14:48:13 +1100 Subject: [PATCH 1/2] fix: remove hooks from the withRoundTrip --- .../examples/stories/fetch/stories.jsx | 4 +- .../examples/stories/superagent/stories.jsx | 4 +- .../stories/examples/utils/index.js | 1 - packages/mock-addon-docs/stories/mock.js | 16 +----- packages/mock-addon/src/utils/faker.js | 6 +- packages/mock-addon/src/withRoundTrip.js | 56 ++++++++++++------- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/packages/mock-addon-docs/stories/examples/stories/fetch/stories.jsx b/packages/mock-addon-docs/stories/examples/stories/fetch/stories.jsx index a6449da..d8d2325 100644 --- a/packages/mock-addon-docs/stories/examples/stories/fetch/stories.jsx +++ b/packages/mock-addon-docs/stories/examples/stories/fetch/stories.jsx @@ -10,7 +10,7 @@ export default { }; const Template = (args) => ( - + ); export const Get = Template.bind({}); @@ -25,9 +25,9 @@ Get.parameters = { export const ResponseFunction = Template.bind({}); ResponseFunction.args = { title: 'Fetch (Response function)', + code: customFunctinBlock, }; ResponseFunction.parameters = { mockData: customMockData, - code: customFunctinBlock, }; diff --git a/packages/mock-addon-docs/stories/examples/stories/superagent/stories.jsx b/packages/mock-addon-docs/stories/examples/stories/superagent/stories.jsx index c2f8a32..88e21a5 100644 --- a/packages/mock-addon-docs/stories/examples/stories/superagent/stories.jsx +++ b/packages/mock-addon-docs/stories/examples/stories/superagent/stories.jsx @@ -10,7 +10,7 @@ export default { }; const Template = (args) => ( - + ); export const Get = Template.bind({}); @@ -25,9 +25,9 @@ Get.parameters = { export const ResponseFunction = Template.bind({}); ResponseFunction.args = { title: 'Superagent (Response function)', + code: customFunctinBlock, }; ResponseFunction.parameters = { mockData: customMockData, - code: customFunctinBlock, }; diff --git a/packages/mock-addon-docs/stories/examples/utils/index.js b/packages/mock-addon-docs/stories/examples/utils/index.js index bd03480..b2963b1 100644 --- a/packages/mock-addon-docs/stories/examples/utils/index.js +++ b/packages/mock-addon-docs/stories/examples/utils/index.js @@ -81,7 +81,6 @@ export const callSuperAgent = async ({ try { const response = await request(method, url, body); - data = response.body; status = response.status; } catch (err) { diff --git a/packages/mock-addon-docs/stories/mock.js b/packages/mock-addon-docs/stories/mock.js index b1ddff9..51b83d7 100644 --- a/packages/mock-addon-docs/stories/mock.js +++ b/packages/mock-addon-docs/stories/mock.js @@ -46,23 +46,13 @@ export const mockData = [ export const customMockData = [ { - url: 'https://jsonplaceholder.typicode.com/todos/1', + url: 'https://jsonplaceholder.typicode.com/todos/:id', method: 'GET', status: 200, response: (request) => { - const { body, searchParams } = request; - - if (searchParams.id == 1) { - return { - data: 'Custom data for id 1', - }; - } else if (body.name === 'mock') { - return { - data: 'Custom data for name mock', - }; - } return { - data: 'Default data', + data: 'Custom function data', + method: `Request method: ${request.method}`, }; }, }, diff --git a/packages/mock-addon/src/utils/faker.js b/packages/mock-addon/src/utils/faker.js index 2051d8e..d9d1d03 100644 --- a/packages/mock-addon/src/utils/faker.js +++ b/packages/mock-addon/src/utils/faker.js @@ -141,7 +141,11 @@ export class Faker { setTimeout(() => { if (typeof response === 'function') { const data = response(new Request(url, { method, body })); - xhr.respond(status, defaultResponseHeaders, data); + xhr.respond( + status, + defaultResponseHeaders, + JSON.stringify(data) + ); } else { xhr.respond( +status, diff --git a/packages/mock-addon/src/withRoundTrip.js b/packages/mock-addon/src/withRoundTrip.js index db434a2..1ea9709 100644 --- a/packages/mock-addon/src/withRoundTrip.js +++ b/packages/mock-addon/src/withRoundTrip.js @@ -1,33 +1,51 @@ -import { useEffect } from 'react'; import { FORCE_RE_RENDER } from '@storybook/core-events'; -import { useChannel, useParameter } from '@storybook/addons'; +import addons from '@storybook/addons'; import { EVENTS, PARAM_KEY, GLOBAL_PARAM_KEY } from './utils/constants'; import faker from './utils/faker'; -export const withRoundTrip = (storyFn) => { - const paramData = useParameter(PARAM_KEY, []); - const mockAddonConfigs = useParameter(GLOBAL_PARAM_KEY, { +const getParameter = (parameters, key, defaultValue) => { + return parameters[key] || defaultValue; +}; + +export const withRoundTrip = (storyFn, context) => { + const { parameters } = context; + const paramData = getParameter(parameters, PARAM_KEY, []); + const mockAddonConfigs = getParameter(parameters, GLOBAL_PARAM_KEY, { refreshStoryOnUpdate: false, globalMockData: [], }); - const emit = useChannel({ - [EVENTS.UPDATE]: (item, name, value) => { - faker.update(item, name, value); + const channel = addons.getChannel(); - const { refreshStoryOnUpdate } = mockAddonConfigs; - const req = faker.getRequests(); - emit(EVENTS.SEND, req); - refreshStoryOnUpdate && emit(FORCE_RE_RENDER); - }, + const { globalMockData } = mockAddonConfigs; + const data = [...globalMockData, ...paramData]; + faker.makeInitialRequestMap(data); + channel.emit(EVENTS.SEND, faker.getRequests()); + + channel.on(EVENTS.UPDATE, ({ item, key, value }) => { + faker.update(item, key, value); + const { refreshStoryOnUpdate } = mockAddonConfigs; + const req = faker.getRequests(); + channel.emit(EVENTS.SEND, req); + refreshStoryOnUpdate && channel.emit(FORCE_RE_RENDER); }); + // const emit = useChannel({ + // [EVENTS.UPDATE]: (item, name, value) => { + // faker.update(item, name, value); + + // const { refreshStoryOnUpdate } = mockAddonConfigs; + // const req = faker.getRequests(); + // emit(EVENTS.SEND, req); + // refreshStoryOnUpdate && emit(FORCE_RE_RENDER); + // }, + // }); - useEffect(() => { - const { globalMockData } = mockAddonConfigs; - const data = [...globalMockData, ...paramData]; - faker.makeInitialRequestMap(data); - emit(EVENTS.SEND, faker.getRequests()); - }, []); + // useEffect(() => { + // const { globalMockData } = mockAddonConfigs; + // const data = [...globalMockData, ...paramData]; + // faker.makeInitialRequestMap(data); + // emit(EVENTS.SEND, faker.getRequests()); + // }, []); return storyFn(); }; From 16e60d71a3c4e661f57901740a230392eb7e7ac8 Mon Sep 17 00:00:00 2001 From: nutboltu Date: Mon, 10 Oct 2022 12:13:34 +1100 Subject: [PATCH 2/2] feat: support vue3 --- packages/mock-addon/src/Panel.js | 8 +-- packages/mock-addon/src/utils/faker.js | 2 +- packages/mock-addon/src/withRoundTrip.js | 75 +++++++++++++----------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/packages/mock-addon/src/Panel.js b/packages/mock-addon/src/Panel.js index 34ea419..6be995a 100644 --- a/packages/mock-addon/src/Panel.js +++ b/packages/mock-addon/src/Panel.js @@ -15,8 +15,8 @@ export const Panel = (props) => { }, }); - const onChange = (item, name, value) => { - emit(EVENTS.UPDATE, item, name, value); + const onChange = (item, key, value) => { + emit(EVENTS.UPDATE, { item, key, value }); }; if (!mockData || mockData.length === 0) { @@ -49,8 +49,8 @@ export const Panel = (props) => { - onChange(item, name, value) + onChange={(key, value) => + onChange(item, key, value) } {...rest} /> diff --git a/packages/mock-addon/src/utils/faker.js b/packages/mock-addon/src/utils/faker.js index d9d1d03..ca71649 100644 --- a/packages/mock-addon/src/utils/faker.js +++ b/packages/mock-addon/src/utils/faker.js @@ -142,7 +142,7 @@ export class Faker { if (typeof response === 'function') { const data = response(new Request(url, { method, body })); xhr.respond( - status, + +status, defaultResponseHeaders, JSON.stringify(data) ); diff --git a/packages/mock-addon/src/withRoundTrip.js b/packages/mock-addon/src/withRoundTrip.js index 1ea9709..a0c1afb 100644 --- a/packages/mock-addon/src/withRoundTrip.js +++ b/packages/mock-addon/src/withRoundTrip.js @@ -1,4 +1,4 @@ -import { FORCE_RE_RENDER } from '@storybook/core-events'; +import { FORCE_RE_RENDER, STORY_CHANGED } from '@storybook/core-events'; import addons from '@storybook/addons'; import { EVENTS, PARAM_KEY, GLOBAL_PARAM_KEY } from './utils/constants'; import faker from './utils/faker'; @@ -7,6 +7,11 @@ const getParameter = (parameters, key, defaultValue) => { return parameters[key] || defaultValue; }; +let INITIAL_MOUNT_STATE = true; +let STORY_CHANGED_STATE = false; + +const channel = addons.getChannel(); + export const withRoundTrip = (storyFn, context) => { const { parameters } = context; const paramData = getParameter(parameters, PARAM_KEY, []); @@ -14,38 +19,40 @@ export const withRoundTrip = (storyFn, context) => { refreshStoryOnUpdate: false, globalMockData: [], }); - - const channel = addons.getChannel(); - - const { globalMockData } = mockAddonConfigs; + const { globalMockData, refreshStoryOnUpdate } = mockAddonConfigs; const data = [...globalMockData, ...paramData]; - faker.makeInitialRequestMap(data); - channel.emit(EVENTS.SEND, faker.getRequests()); - - channel.on(EVENTS.UPDATE, ({ item, key, value }) => { - faker.update(item, key, value); - const { refreshStoryOnUpdate } = mockAddonConfigs; - const req = faker.getRequests(); - channel.emit(EVENTS.SEND, req); - refreshStoryOnUpdate && channel.emit(FORCE_RE_RENDER); - }); - // const emit = useChannel({ - // [EVENTS.UPDATE]: (item, name, value) => { - // faker.update(item, name, value); - - // const { refreshStoryOnUpdate } = mockAddonConfigs; - // const req = faker.getRequests(); - // emit(EVENTS.SEND, req); - // refreshStoryOnUpdate && emit(FORCE_RE_RENDER); - // }, - // }); - - // useEffect(() => { - // const { globalMockData } = mockAddonConfigs; - // const data = [...globalMockData, ...paramData]; - // faker.makeInitialRequestMap(data); - // emit(EVENTS.SEND, faker.getRequests()); - // }, []); - - return storyFn(); + + /** + * Initiate event listener for story change and update. + * This state executes once to setup. + */ + if (INITIAL_MOUNT_STATE) { + faker.makeInitialRequestMap(data); + + channel.emit(EVENTS.SEND, faker.getRequests()); + + channel.on(STORY_CHANGED, () => { + STORY_CHANGED_STATE = true; + }); + + channel.on(EVENTS.UPDATE, ({ item, key, value }) => { + faker.update(item, key, value); + const req = faker.getRequests(); + channel.emit(EVENTS.SEND, req); + refreshStoryOnUpdate && channel.emit(FORCE_RE_RENDER); + }); + + INITIAL_MOUNT_STATE = false; + } + + /** + * This state executes when a story change. So that it can + * take the new parameters to setup the faker requests. + */ + if (STORY_CHANGED_STATE) { + faker.makeInitialRequestMap(data); + channel.emit(EVENTS.SEND, faker.getRequests()); + STORY_CHANGED_STATE = false; + } + return storyFn(context); };