如何测试用户从数据列表中选择选项的情况?我使用
onChange
在输入上断言 @testing-library/user-event
回调。
这是我的 React 组件:
// MyInput.js
import React from "react";
const MyInput = ({ value, list, id, onChange }) => {
return (
<label>
<strong>{id}</strong>
<div>
<input type="text" value={value} onChange={onChange} list={id} />
<datalist id={id} aria-label="datalist-items">
{list.map((item) => (
<option
key={`item-${item.id}`}
aria-label="data-list-item"
value={item.value}
/>
))}
</datalist>
</div>
</label>
);
};
export default MyInput;
这是我失败的测试
// MyInput.spec.js
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import MyInput from "./MyInput";
import data from "./data.json";
describe("MyInput", () => {
it("should trigger onChange with selected option", () => {
const onChange = jest.fn();
const list = [...data.list];
const screen = render(<MyInput onChange={onChange} list={list} />);
userEvent.selectOptions(screen.getByLabelText("datalist-items"), "first");
expect(onChange).toHaveBeenCalledWith("first");
});
});
提供给组件的数据:
// data.json
{
"list": [
{ "id": 1, "value": "first" },
{ "id": 2, "value": "second" }
]
}
然而,这不起作用。测试报告失败:
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: "first"
Number of calls: 0
14 | userEvent.selectOptions(screen.getByLabelText("datalist-items"), "first");
> 16 | expect(onChange).toHaveBeenCalledWith("first");
17 | });
18 | });
您可以在这个 CodeSandbox 中找到一个实例。
我想模拟现实生活中的场景,其中用户单击输入,呈现数据列表,然后用户单击其中一个选项。我应该以某种方式瞄准渲染的数据列表吗?又如何?
onChange
事件处理程序由
<input type='text'>
jsx 使用,因此您应该使用type(element, text, [options]) 在
<input>
或
<textarea>
内写入文本。selectOptions(element, value) 用于选择
<select>
或
<select multiple>
元素的指定选项。
MyInput.jsx
:
import React from 'react';
const MyInput = ({ value, list, id, onChange }) => {
return (
<label>
<strong>{id}</strong>
<div>
<input type="text" value={value} onChange={onChange} data-testid="test" list={id} />
<datalist id={id} aria-label="datalist-items">
{list.map((item) => (
<option key={`item-${item.id}`} aria-label="data-list-item" value={item.value} />
))}
</datalist>
</div>
</label>
);
};
export default MyInput;
MyInput.spec.jsx
:
import React from 'react';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MyInput from './MyInput';
import data from './data.json';
describe('MyInput', () => {
it('should trigger onChange with selected option', () => {
expect.assertions(6);
let events = [];
const onChange = jest.fn().mockImplementation((e) => {
e.persist();
events.push(e);
});
const list = [...data.list];
const screen = render(<MyInput onChange={onChange} list={list} id="test" />);
userEvent.type(screen.getByTestId('test'), 'first');
expect(onChange).toBeCalledTimes(5);
events.forEach((e) => {
expect(onChange).toHaveBeenCalledWith(e);
});
});
});
测试结果:
PASS examples/65687415/MyInput.spec.jsx
MyInput
✓ should trigger onChange with selected option (44 ms)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
MyInput.jsx | 100 | 100 | 100 | 100 |
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.175 s
封装版本:
"react": "^16.14.0",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",