gpt4 book ai didi

reactjs - 如何使用 react-testing-library 测试包装在 withStyles 中的样式化的 Material-UI 组件?

转载 作者:搜寻专家 更新时间:2023-10-30 20:33:41 24 4
gpt4 key购买 nike

我正在尝试使用 typescript 中的 react-testing-library 使用样式化的 Material-UI 组件创建测试。我发现很难访问组件的内部函数来模拟和断言。

表格.tsx

export const styles = ({ palette, spacing }: Theme) => createStyles({
root: {
flexGrow: 1,
},
paper: {
padding: spacing.unit * 2,
margin: spacing.unit * 2,
textAlign: 'center',
color: palette.text.secondary,
},
button: {
margin: spacing.unit * 2,
}
});

interface Props extends WithStyles<typeof styles> { };

export class ExampleForm extends Component<Props, State> {
async handleSubmit(event: React.FormEvent<HTMLFormElement>) {
// Handle form Submit
...
if (errors) {
window.alert('Some Error occurred');
return;
}
}
// render the form
}
export default withStyles(styles)(ExampleForm);

测试.tsx

import FormWithStyles from './Form';

it('alerts on submit click', async () => {
jest.spyOn(window,'alert').mockImplementation(()=>{});
const spy = jest.spyOn(ActivityCreateStyles,'handleSubmit');
const { getByText, getByTestId } = render(<FormWithStyles />)
fireEvent.click(getByText('Submit'));

expect(spy).toHaveBeenCalledTimes(1);
expect(window.alert).toHaveBeenCalledTimes(1);
})

jest.spyOn 引发以下错误 Argument of type '"handleSubmit"' is not assignable to parameter of type 'never'.ts(2345) 可能是因为 ExampleForm包裹在 withStyles 中。

我也尝试过直接导入 ExampleForm 组件并手动分配样式,但无法这样做:

import {ExampleForm, styles} from './Form';

it('alerts on submit click', async () => {
...

const { getByText, getByTestId } = render(<ActivityCreateForm classes={styles({palette,spacing})} />)

...
}

出现以下错误:Type '{ palette: any;间距:任意; }' 缺少“主题”类型的以下属性:形状、断点、方向、混合和 4 个 more.ts(2345)

我发现用 react-testing-libraryJestMaterial-UI 组件编写基本测试很困难到强类型和包装组件。请指导。

最佳答案

首先,当您使用react-testing-libraryrender 方法时您无需担心使用 withStyles 或任何包装器,因为最后它会呈现组件,因为它可能在真实的 dom 中,因此您可以正常编写测试。

据我所知,您所做的与我开始测试时所做的相同(这意味着您将变得擅长它;)。您正在尝试模拟一个内部方法,这不是最好的方法,因为您需要做的是测试真正的方法。

让我们想象一下,我们有一个 Register 用户组件。

src/Register.tsx

import ... more cool things
import * as api from './api';

const Register = () => {
const [name, setName] = useState('');
const handleNameChange = (event) => {
setName(event.target.value);
};

const handleSubmit = (event) => {
event.preventDefault();
if (name) {
api.registerUser({ name });
}
};

return (
<form onSubmit={handleSubmit}>
<TextField
id='name'
name='name'
label='Name'
fullWidth
value={name}
onChange={handleNameChange}
/>
<Button data-testid='button' fullWidth type='submit' variant='contained'>
Save
</Button>
</form>
);
}

该组件非常简单,它是一个带有输入和按钮的表单。我们正在使用 react hooks 来更改输入值,并基于此我们在触发 handleSubmit 事件时调用或不调用 api.registerUser

要测试组件,我们需要做的第一件事是mock api.registerUser 方法。

src/__tests__/Register.tsx

import * as api from '../api'

jest.mock('../api')

api.registerUser = jest.fn()

这将使我们能够查看该方法是否被调用。

接下来要做的是......编写测试,在这种情况下,我们可以测试两件事,看看 handleSubmit 是否正常工作。

  1. 如果名称 为空,则不调用 api.registerUser
it('should not call api registerUser method', () => {
const { getByTestId } = render(<Register />)
fireEvent.click(getByTestId('button'))
expect(api.registerUser).toHaveBeenCalledTimes(0)
})
  1. 如果名称为空,则调用api.registerUser
it('should call api registerUser method', () => {
const { getByLabelText, getByTestId } = render(<Register />)

fireEvent.change(getByLabelText('Name'), { target: { value: 'Steve Jobs' }})

fireEvent.click(getByTestId('button'))
expect(api.registerUser).toHaveBeenCalledTimes(1)
})

在最后一个测试中,我们也在测试 handleNameChange,因为我们正在更改名称 :) 所以 name 不会为空并且 registerUser 将被调用。

使用withStylestypescript 的例子在repo .
演示是here .

关于reactjs - 如何使用 react-testing-library 测试包装在 withStyles 中的样式化的 Material-UI 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55939084/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com