apollo MockedProvider + Storybook 不工作

Posted

技术标签:

【中文标题】apollo MockedProvider + Storybook 不工作【英文标题】:apollo MockedProvider + Storybook not working 【发布时间】:2020-09-02 11:29:03 【问题描述】:

在 Storybook 中使用 MockedProvider 似乎没有返回任何内容。

将我的组件包装在 MockedProvider 中时,它不再抛出没有 Apollo 客户端的错误。所以这证明了 MockProvider “有效”

预期结果:

以下钩子应该返回模拟中的数据:

const loading, error, data = useQuery(LATEST_SELL_SIGNALS)

实际结果:

第一次渲染时加载为true,第二次渲染时加载为false

数据是undefined

错误是undefined

加载道具正在工作的事实也应该表明 MockedProvider 正在运行。

示例故事:

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>
  )

LATEST_SELL_SIGNALS 是这个文件的位置:

import  gql  from 'apollo-boost'

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

我正在包装的组件正在使用这样的反应钩子:

const loading, error, data = useQuery(LATEST_SELL_SIGNALS)

查询的导入在组件中与在模拟中相同

请注意,这一切都适用于我的普通 Apollo Provider,我只是遇到了 MockProvider 的问题,没有做这件事。

组件。效果也很好

版本 3.1.4

【问题讨论】:

【参考方案1】:

在我的项目中,我使用从mock-apollo-client 导入的ApolloProvidercreateMockClient 为我的故事书创建模拟客户端。 有我的组件。希望它可以帮助你。 1.在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.在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.在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/>

【讨论】:

感谢您的回答! mock-apollo-client 确实有效。然而,这不是阿波罗团队的官方解决方案。我正在专门寻找有关如何让 MockedProvider (官方)与故事书一起工作的答案。为其他人投票,但不是这个特定问题的答案。 我也对此进行了研究,我认为没有得到很好支持的官方解决方案。查看推荐的工具可能最终会将您指向 apollo-client 模拟,但是当您通过 @apollo/react-hooks 进行查询时,该解决方案会失效。我认为迈克尔的建议是目前最好的建议:D【参考方案2】:

模拟结果的形状必须与查询完全相同,否则useQuerydata 的值将是undefined

由于查询是

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

因此模拟数据的结果必须是

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

更新的故事

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>
  );
;


控制台输出:

【讨论】:

以上是关于apollo MockedProvider + Storybook 不工作的主要内容,如果未能解决你的问题,请参考以下文章

reactjs / jest:无法使用 MockedProvider 用数据填充 react-apollo 组件?

阿波罗的 MockedProvider 没有明确警告丢失的模拟

在 jest-react 中使用 MockedProvider 会导致错误“查询没有更多的模拟响应”

React Apollo 错误:查询不再有模拟响应:突变

通过 apollo 客户端测试使用查询和订阅的反应组件

使用酶进行测试时如何找到包裹在 MockedProvider 中的 Typography 组件