Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow parameters.msw to be a function that takes args #67

Open
tmikeschu opened this issue Dec 10, 2021 · 9 comments
Open

Allow parameters.msw to be a function that takes args #67

tmikeschu opened this issue Dec 10, 2021 · 9 comments

Comments

@tmikeschu
Copy link

tmikeschu commented Dec 10, 2021

Hello! I'm stoked to see this library growing so much. At work we still have a custom setup for Storybook and MSW because we're using args to result in dynamic MSW calls.

I wonder if you could add something like

if (typeof context.parameters.msw === "function") {
  api.use(...context.parameters.msw(context.args))
}

Where the story meta would be:

export default {
  ...,
  args: { isLoading },
  parameters: {
    msw: (args) => [
      rest.get("...", (_, res, ctx) =>
        res(ctx.delay(args.isLoading ? "infinite" : 0), ctx.json(...))
      )
    ]
  }
}
@itaditya
Copy link
Collaborator

Some discussion on this has happened before. Might be still relevant

#11

@yannbf
Copy link
Collaborator

yannbf commented Dec 11, 2021

Hey @itaditya thanks for referring that! There are a couple of things happening on the storybook side that will allow us to bring a proper control panel experience to this addon, I just need to discuss more with the team and prototype in this addon:

Targeted args will allow users to define args specifically for addons, which will not be passed down to the components props

Loaders that rerun on args change will allow us to move from exporting decorators to loaders so that the mock setup is done before the component renders (then we can support nextjs and its getServerProps for instance) and the mocks will be redone on args change

So @tmikeschu this feature is definitely going to happen, it might just take some time!

@itwasmattgregg
Copy link

Very excited for this feature. Let me know if you want assistance writing these changes.

I was able to make it work by implementing my own handler which could be done at the story or component level.

Example here:

import {getWorker} from 'msw-storybook-addon';

const worker = getWorker();

const Template: StoryFn = () => <TestPage />;

export const Story = Template.bind({});

export const OtherTemplate: StoryFn = ({maxAmount}) => {
  worker.use(
    graphql.query('GraphqlQueryName', (_, res, ctx) => {
      return res(
        ctx.delay(),
        ctx.data<GraphqlQueryNameQueryData>(
          generateMockData({
            maxAmount,
          }),
        ),
      );
    }),
  );
  return <TestPage />;
};

OtherTemplate.args = {
  maxAmount: '40000',
};
OtherTemplate.argTypes = {
  maxAmount: {
    options: ['500', '5000', '10000', '40000', '100000'],
    control: {type: 'select'},
  },
};

@ekeijl
Copy link

ekeijl commented Jun 15, 2022

I think it would be really useful if we can access the context in this function (e.g. globals/parameters, see here for an example), even more so than args. Sometimes you want to quickly switch between datasets, which is a separate concern from the args that control the component's UI.

Use case: you could make a toolbar button where you can switch between a "regular user" and "admin user" (or "large dataset" and "small dataset") and return different datasets in your handlers based on the selected type of user.

@YaNokk
Copy link

YaNokk commented Aug 7, 2022

Hey @itaditya thanks for referring that! There are a couple of things happening on the storybook side that will allow us to bring a proper control panel experience to this addon, I just need to discuss more with the team and prototype in this addon:

Targeted args will allow users to define args specifically for addons, which will not be passed down to the components props

Loaders that rerun on args change will allow us to move from exporting decorators to loaders so that the mock setup is done before the component renders (then we can support nextjs and its getServerProps for instance) and the mocks will be redone on args change

So @tmikeschu this feature is definitely going to happen, it might just take some time!

Hello, are there any news?

@rodrigofeijao
Copy link

@itwasmattgregg Does yours refresh the component when changing the data?

@pushred
Copy link

pushred commented Aug 28, 2023

I think it would be really useful if we can access the context in this function (e.g. globals/parameters, see here for an example), even more so than args

Same here.. in my use case I want to instantiate a test factory and generate story-specific mock data in a loader and then use that data in my Mock Service Worker responses.

@elpddev
Copy link

elpddev commented Apr 17, 2024

Putting this comment also here - For now, I use ctx for transfering data between storybook args and msw.

  • In the main preview decorator, I get parameters and set parameters.msw.handlers.appConfig.__mydata to some data,
  • and in the handler I get the data from the ctx argument.

@jipis
Copy link

jipis commented Jul 17, 2024

I'm using MSW v2, msw-storybook-addon v2, and storybook v8. ctx is no longer available in the handler. :-( However, building on what @elpddev did, I hacked this to make it work.

Made a story-specific decorator:

  decorators: [
    (Story, { args, parameters }) => {
      const originalResolver = parameters.msw.handlers.dashboardApi.resolver;
      parameters.msw.handlers.dashboardApi.resolver = (r) => {
        return originalResolver(r, args);
      };
      return <Story />;
    },
  ],

That handles passing the args into the handler. Then, in the handler, it's just there as an arg!

  parameters: {
    msw: {
      handlers: {
        myApi: http.get('/api/myURL/:id', (r, args) => {
          console.log('Original Handler args", r);
          console.log('MSW HANDLER ARGS PASSED HERE', args);
          // return from here as usual in a handler....
        }),
      },
    },
  },

Does it feel hackish and dirty and there should be a better way? Yup. Does it work good enough for testing purposes? You betcha!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants