Madan Chaudhary
Madan Chaudhary

Reputation: 85

RTK query with Storybookjs

I am using RTK query with typescript in my react application and its working fine however storybookjs is not able to mock data for RTK query.

I am trying to mock store object as shown in this storybook document.

example -

export const Test = Template.bind({});
Test.decorators = [
    (story) => <Mockstore data={myData}>{story()}</Mockstore>,
];
.
.
.
const customBaseQuery = (
    args,
    { signal, dispatch, getState },
    extraOptions
) => {
    return { data: [] }; // <--- NOT SURE ABOUT THIS
};


const Mockstore = ({ myData, children }) => (
    <Provider
        store={configureStore({
            reducer: {
                [myApi.reducerPath]: createApi({
                    reducerPath: 'myApi',
                    baseQuery: customBaseQuery,
                    endpoints: (builder) => ({
                        getMyData: myData, //<-- my mock data
                    }),
                }).reducer,
            },
            middleware: (getDefaultMiddleware) =>
                getDefaultMiddleware().concat(myApi.middleware),
        })}
    >
        {children}
    </Provider>
);

Since RTK query hook is autogenerated, I am not sure how to mock it in storybookjs. Instead of getting mock data storybook if trying to fetch actual data.

Please help me.

Upvotes: 2

Views: 2288

Answers (2)

kardave
kardave

Reputation: 1501

Only another method worked for me.

import original API and mock store

const mockStore: EnhancedStore = configureStore({
  reducer: {
    [my.reducerPath]: myApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(myApi.middleware),
});

create your mock data

const mockData = {};

dispatch your pending and the fulfilled actions

mockStore.dispatch({
  type: 'myApi/executeQuery/pending',
  meta: {
    startedTimeStamp: new Date().getTime(),
    requestId: 'r1',
    arg: {
      subscribe: true,
      endpointName: 'getMyData', 
      queryCacheKey:
        'getMyData(undefined)',
    },
  },
});
mockStore.dispatch({
  type: 'myApi/executeQuery/fulfilled',
  payload: mockData, // 
  meta: {
    fulfilledTimeStamp: new Date().getTime(),
    arg: {
      endpointName: 'getMyData',
      queryCacheKey:
        'getMyData(undefined)',
    },
    requestId: 'r1',
  },
});

create the MockStore component to separate your provider

const Mockstore = ({ children }: PropsWithChildren) => (
  <Provider store={mockStore}>{children}</Provider>
);

Add Mockstore to the decorator

const meta: Meta<typeof MyComponent> = {
  title: 'molecules/MyComponent/Views',
  // ...
  component: MyComponent,
  decorators: [
    (story) => (
      <Mockstore>{story()}</Mockstore>
    ),
  ],
};

Upvotes: 1

phry
phry

Reputation: 44326

You'd do


                    endpoints: (builder) => ({
                        getMyData:  builder.query({ 
                          queryFn: () => { data: myData }, //<-- my mock data
                        })
                    }),

alternatively you could leave the store setup just as it is and use msw to mock the real api.

Upvotes: 1

Related Questions