sru*_*thi 16 typescript reactjs material-ui react-testing-library
我有一个材料用户界面TextField,它在焦点上打开一个Popper. 我正在尝试使用 react-testing-library 测试这种行为。
组件:
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';
import TextField from '@material-ui/core/TextField';
import React from 'react';
import { ItemType } from './types';
export type TextFieldDropDownProps = {
items: ItemType,
};
export function TextFieldDropDown(props: TextFieldDropDownProps) {
const [searchTerm, setSearchTerm] = React.useState('');
const [anchorEl, setAnchorEl] = React.useState(null);
const handleSearchTermChange = (event: any) => {
setSearchTerm(event.target.value);
};
const onFoucs = (event: any) => {
setAnchorEl(event.currentTarget);
};
const handleClose = (event: any) => {
setAnchorEl(null);
};
const popperTrans = ({ TransitionProps }: any) => {
return (
<Grow
{...TransitionProps}
style={{ transformOrigin: '0 0 0' }}
>
<Paper>
<ul />
</Paper>
</Grow>
);
};
const open = Boolean(anchorEl);
return (
<ClickAwayListener onClickAway={handleClose}>
<div>
<TextField
onChange={handleSearchTermChange}
onFocus={onFoucs}
value={searchTerm}
label='Search'
/>
<Popper
open={open}
anchorEl={anchorEl}
transition={true}
disablePortal={true}
placement='bottom-start'
style={{zIndex: 999, minWidth: '100%'}}
>
{popperTrans}
</Popper>
</div>
</ClickAwayListener>
);
}
Run Code Online (Sandbox Code Playgroud)
测试:
import { fireEvent, render, wait } from '@testing-library/react';
import { getTestData } from 'test-data';
import React from 'react';
import { TextFieldDropDown } from './TextFieldDropDown';
test('that on focus on input field, the component shows a dropdown', async () => {
// Set up test data
const items: any = getTestData();
// Render component
const props = { items };
const { getByRole, queryByRole } = render(<TextFieldDropDown {...props} />, {});
await wait();
expect(queryByRole('list')).toBeNull();
// Fire event
const placeSelectInputField = getByRole('textbox') as HTMLInputElement;
fireEvent.focus(placeSelectInputField);
// Verify that dropdown is shown
expect(queryByRole('list')).toBeInTheDocument();
});
Run Code Online (Sandbox Code Playgroud)
当我运行测试时,我收到以下错误 - TypeError: document.createRange is not a function.
The above error occurred in the <div> component:
in div (created by ForwardRef(Portal))
in ForwardRef(Portal) (created by ForwardRef(Popper))
in ForwardRef(Popper) (created by TextFieldDropDown)
in div (created by ForwardRef(ClickAwayListener))
in ForwardRef(ClickAwayListener) (created by TextFieldDropDown)
in TextFieldDropDown
in Provider (created by AllTheProviders)
in AllTheProviders
Consider adding an error boundary to your tree to customize error handling behavior.
The above error occurred in the <ForwardRef(Popper)> component:
in ForwardRef(Popper) (created by TextFieldDropDown)
in div (created by ForwardRef(ClickAwayListener))
in ForwardRef(ClickAwayListener) (created by TextFieldDropDown)
in TextFieldDropDown
in Provider (created by AllTheProviders)
in AllTheProviders
Consider adding an error boundary to your tree to customize error handling behavior.
? that on focus on input field, the component shows a dropdown
TypeError: document.createRange is not a function
46 | // Fire event
47 | const TextFieldComponent = getByRole('textbox') as HTMLInputElement;
> 48 | fireEvent.focus(TextFieldComponent);
| ^
49 |
50 | // Verify that dropdown is shown
51 | expect(queryByRole('list')).toBeInTheDocument();
Run Code Online (Sandbox Code Playgroud)
我如何使这项工作?
sru*_*thi 21
参考这个 github 问题,我发现我们可以用下面的代码修复这个错误,放在测试设置文件中。
(global as any).document.createRange = () => ({
setStart: () => {},
setEnd: () => {},
commonAncestorContainer: {
nodeName: 'BODY',
ownerDocument: document,
},
});
Run Code Online (Sandbox Code Playgroud)
小智 5
问题在于,document.createRange当没有 DOM API 可供调用时,PopperJS 的底层实现会调用该函数。解决方案是模拟 PopperJS。
// __mocks__/popper.js.js
import PopperJs from 'popper.js';
export default class Popper {
constructor() {
this.placements = PopperJs.placements;
return {
update: () => {},
destroy: () => {},
scheduleUpdate: () => {}
};
}
}
Run Code Online (Sandbox Code Playgroud)
jest 将/__mocks__自动选择目录中的任何模拟,因此只需添加此文件即可解决您的问题
| 归档时间: |
|
| 查看次数: |
8156 次 |
| 最近记录: |