reactjs - 如何在 React 测试库中设置 InitialState
问题描述
我正在编写一个需要渲染组件的测试,但我的组件的渲染不起作用,我收到此错误:
Uncaught [TypeError: Cannot read property 'role' of undefined].
这是因为在componentDidMount
我的组件的函数中,我正在检查 if this.props.authentication.user.role === 'EXPERT'
。但是,this.props.authentication
具有.user
undefined
这对我的程序是正确initialState
的,但对于我想设置我的测试initialState
有一个user
对象。这就是我initialState
在测试中重新定义的原因。但是,该组件不会使用新的initialState
.
这是测试文件:
import { Component } from '../Component.js';
import React from 'react';
import { MemoryRouter, Router } from 'react-router-dom';
import { render, cleanup, waitFor } from '../../test-utils.js';
import '@testing-library/jest-dom/extend-expect';
afterEach(cleanup)
describe('Component Testing', () => {
test('Loading text appears', async () => {
const { getByTestId } = render(
<MemoryRouter><Component /></MemoryRouter>,
{
initialState: {
authentication: {
user: { role: "MEMBER", memberID:'1234' }
}
}
},
);
let label = getByTestId('loading-text')
expect(label).toBeTruthy()
})
});
这是组件文件:
class Component extends React.Component {
constructor(props) {
super(props)
this.state = {
tasks: [],
loading: true,
}
this.loadTasks = this.loadTasks.bind(this)
}
componentDidMount() {
if (
this.props.authentication.user.role == 'EXPERT' ||
this.props.authentication.user.role == 'ADMIN'
) {
this.loadTasks(this.props.location.state.member)
} else {
this.loadTasks(this.props.authentication.user.memberID)
}
}
mapState(state) {
const { tasks } = state.tasks
return {
tasks: state.tasks,
authentication: state.authentication
}
}
}
我也在使用下面的自定义渲染函数
import React from 'react'
import { render as rtlRender } from '@testing-library/react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { initialState as reducerInitialState, reducer } from './_reducers'
import rootReducer from './_reducers'
import configureStore from './ConfigureStore.js';
import { createMemoryHistory } from 'history'
function render(ui, {
initialState = reducerInitialState,
store = configureStore({}),
...renderOptions
} = {}
) {
function Wrapper({ children }) {
return <Provider store={store}>{children}</Provider>
}
return rtlRender(ui, { wrapper: Wrapper, ...renderOptions })
}
// re-export everything
export * from '@testing-library/react'
// override render method
export { render }
解决方案
也许我来晚了,但也许这对某人有用。我为 Typescript 设置所做的如下(所有这些都在 内test-utils.tsx
)
const AllProviders = ({
children,
initialState,
}: {
children: React.ReactNode
initialState?: RootState
}) => {
return (
<ThemeProvider>
<Provider store={generateStoreWithInitialState(initialState || {})}>
<FlagsProvider value={flags}>
<Router>
<Route
render={({ location }) => {
return (
<HeaderContextProvider>
{React.cloneElement(children as React.ReactElement, {
location,
})}
</HeaderContextProvider>
)
}}
/>
</Router>
</FlagsProvider>
</Provider>
</ThemeProvider>
)
}
interface CustomRenderProps extends RenderOptions {
initialState?: RootState
}
const customRender = (
ui: React.ReactElement,
customRenderProps: CustomRenderProps = {}
) => {
const { initialState, ...renderProps } = customRenderProps
return render(ui, {
wrapper: (props) => (
<AllProviders initialState={initialState}>{props.children}</AllProviders>
),
...renderProps,
})
}
export * from '@testing-library/react'
export { customRender as render }
值得一提的是,您可以/应该删除对您的情况没有任何意义的提供程序(可能是 theFlagsProvider
或HeaderContextProvider
反正我没有多大意义)
就商店文件而言,我这样做了:
//...omitting extra stuff
const storeConfig = {
// All your store setup some TS infer types may be a extra challenge to solve
}
export const store = configureStore(storeConfig)
export const generateStoreWithInitialState = (initialState: Partial<RootState>) =>
configureStore({ ...storeConfig, preloadedState: initialState })
//...omitting extra stuff
干杯!
推荐阅读
- php - Stomp Over Websocket - CONNECT 数据(无法识别的操作码)
- python - Tkinter 菜单未出现在 MacOS 11.2.2 上
- bash - 为什么我的 Bash sed 命令( sed -e "s/-*[a-zA-Z\-]* / /g" )删除点后的字符?
- javascript - 如何隐藏普通 HTML/CSS/JS GitHub Pages 项目的数据库连接信息?
- python - Linkedin - 通过python登录问题
- reactjs - 在同一视图中具有 Material UI 的多个自动完成字段
- django - 如何在 Django 中获取客户端远程端口号?
- python - Itertools 链在 Cython 中的行为不同
- python - 使用“截断”大 68 点模型进行人脸编码
- javascript - 使用 ui 构建在 javascript 中的 DOM 中查找元素