[英]How to set InitialState in React Testing Library
我正在編寫一個需要渲染組件的測試,但我的組件的渲染不起作用,我收到此錯誤:
Uncaught [TypeError: Cannot read property 'role' of undefined].
這是因為在我的組件中的componentDidMount
function 中,我正在檢查this.props.authentication.user.role === 'EXPERT'
。 但是, this.props.authentication
的user
為undefined
。
這是我的程序的正確初始狀態,但對於測試,我想將我的initialState
狀態設置為擁有user
initialState
。 這就是我在測試中重新定義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
}
}
}
我還使用了自定義渲染 function 如下
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 }
值得一提的是,您可以/應該刪除對您的情況沒有任何意義的提供程序(可能是FlagsProvider
或HeaderContextProvider
) ,但我留下來說明我決定將 UI 提供程序保留在路由內,將其他提供程序保留在外部(但是無論如何,這對我來說沒有多大意義)
就商店文件而言,我這樣做了:
//...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
干杯!
我不確定您在配置商店中在做什么,但我想您的組件的初始 state 應該在商店中傳遞。
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 { createMemoryHistory } from 'history'
function render(
ui,
{
initialState = reducerInitialState,
store = createStore(reducer,initialState),
...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 }
我希望它會幫助你:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.