apollo MockedProvider + Storybook not working

Viewed 3432

Using MockedProvider in Storybook doesn't seem to return anything.

When wrapping my component in the MockedProvider, it no longer throws an error that there's no Apollo client. So this proves that the MockProvider "works"

Intended outcome:

The following hook should return the data that's in the mock:

const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS)

Actual outcome:

loading is true on first render and false on the second render

data is undefined

error is undefined

The fact that the loading props are working, should also suggest MockedProvider is running.

Example story:

import React from 'react'
import { MockedProvider } from '@apollo/react-testing'

import { LATEST_SELL_SIGNALS } from '~/common/queries'
import LatestSells from './LatestSells'

const mocks = [
  {
    request: {
      query: LATEST_SELL_SIGNALS,
    },
    result: {
      data: {
        yourData: { name: 'Storybook Data' },
      },
    },
  },
]


export default {
  title: 'Sales Components'
}

export const latest_sells = () => {
  return (
      <MockedProvider mocks={mocks}>
        <LatestSells />
      </MockedProvider>
  )
}

Where the LATEST_SELL_SIGNALS is this file:

import { gql } from 'apollo-boost'

export const LATEST_SELL_SIGNALS = gql`
  query {
    latestSellSignalsList(orderBy: createdAt_DESC, first: 10) {
      items {
        name
        ticker
        boughtAt
        soldAt
      }
    }
  }
`

the Component I'm wrapping is using react hooks like this:

const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS)

The import for the query is the same in the Component as it is in the mock

please note this all works just fine with my normal Apollo Provider, I'm only having issues with the MockProvider not doing it's thing.

The component. also renders fine

Version 3.1.4

2 Answers

In my project, I use ApolloProvider and createMockClient imported from mock-apollo-client to create mock client for my story book. There are my components. Hopefully, it can help you.
1. In withApolloProvider.js

import React from 'react'
import { ApolloProvider } from '@apollo/react-hooks'
import { createMockClient } from 'mock-apollo-client'

export const withApolloProvider = ({ requestMockHandlers }) => {
 const mockClient = createMockClient()
 requestMockHandlers.mutations.forEach(mockHandler => {
  mockClient.setRequestHandler(mockHandler.type, mockHandler.handler)
 })
 requestMockHandlers.queries.forEach(mockHandler => {
  mockClient.setRequestHandler(mockHandler.type, mockHandler.handler)
 })
 return storyFn => {
  return <ApolloProvider client={mockClient}>{storyFn()}</ApolloProvider>
 }
}

2. In NavBar.stories.js

import React from 'react'
import { ThemeProvider } from '@material-ui/core'
import muiTheme from '../../src/theme/muiTheme'
import NavBarDefault from './NavBarDefault'
import './navbar.scss'
import { addDecorator } from '@storybook/react'
import { RESET_CACHE } from '../../src/views/components/NavPanel/gql/mutation'

import gql from 'graphql-tag'
import { withApolloProvider } from '../withApolloProvider'

export default {
 title: 'Component Api|Navbar',
 includeStories: [],
}

const requestMockHandlers = {
 queries: [],
 mutations: [
  {
   type: RESET_CACHE,
   handler: () => {},
  },
 ],
}

addDecorator(
 withApolloProvider({
  requestMockHandlers,
 })
)

export const NavBarStory = () => {
 return (
  <ThemeProvider theme={muiTheme}>
   <NavBarDefault />
  </ThemeProvider>
 )
}


3. In NavBar.stories.mdx

import { Meta, Story, Preview,Props } from '@storybook/addon-docs/blocks';
import NavBarDefault from './NavBarDefault'

import * as stories from './NavBar.stories.js';

<Meta title="Component Api|NavBar" />

# NavBar
With `MDX` we can define a story for `Nav Bar` right in the middle of our
markdown documentation.




  <Story name="Basic">
    {stories.NavBarStory()}
  </Story>


```jsx
<NavBarDefault />
```

# PropTypes

<Props of={NavBarDefault}/>

The shape of the mocked result MUST be exactly the same as the query, otherwise, the value of the data of the useQuery will be undefined.

Since the query is

const LATEST_SELL_SIGNALS = gql`
      query {
        latestSellSignalsList(orderBy: "desc", first: 10) {
          items {
            name
            ticker
            boughtAt
            soldAt
          }
        }
      }
    `;

thus the result of the mocked data must be

result: {
  data: {
    latestSellSignalsList: {
      items: [
        { 
          name: 'Storybook Data', 
          ticker: 'STB', 
          boughtAt: 'boughtAt', 
          soldAt: 'soldAt'
        }
      ],
    },
  },
},
    

Updated Story

import React from 'react';
import { gql, useQuery } from '@apollo/client';
import { MockedProvider } from '@apollo/client/testing';

export default {
  title: 'MockedProvider',
};
const LATEST_SELL_SIGNALS = gql`
  query {
    latestSellSignalsList(orderBy: "desc", first: 10) {
      items {
        name
        ticker
        boughtAt
        soldAt
      }
    }
  }
`;

const mocks = [
  {
    request: {
      query: LATEST_SELL_SIGNALS,
    },
    result: {
      data: {
        latestSellSignalsList: {
          items: [
            { name: 'Storybook Data', ticker: 'STB', boughtAt: 'boughtAt', soldAt: 'soldAt' },
          ],
        },
      },
    },
  },
];

const LatestSells = () => {
  const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS);
  console.log('LatestSells', { loading, data });
  return <div>{JSON.stringify(data)}</div>;
};

export const Default = () => {
  return (
    <MockedProvider mocks={mocks}>
      <LatestSells />
    </MockedProvider>
  );
};


The console output:

The console output

Related