reactjs - 如何通过选择数据列表来测试更改事件的触发器

标签 reactjs testing jestjs react-testing-library

如何测试用户从数据列表中选择选项的情况?我使用 @testing-library/user-event 在输入上断言 onChange 回调。

这是我的 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 | });

您可以找到一个实例 in this CodeSandbox .

我想模拟现实生活中的场景,其中用户单击输入,呈现数据列表,然后用户单击其中一个选项。我应该以某种方式瞄准渲染的数据列表吗?又如何?

最佳答案

onChange事件处理程序由 <input type='text'> 使用jsx,所以你应该使用 type(element, text, [options])<input> 中写入文本或<textarea>selectOptions(element, values)用于选择 <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",

关于reactjs - 如何通过选择数据列表来测试更改事件的触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65687415/

相关文章:

java - 如何在 Selenium RC 项目中设置 URL 变量

reactjs - @testing-library/react TDD,react-bootstrap : Is this kind of test useful or just time loose

javascript - 在应用程序完全加载后,如何将 Google 跟踪代码管理器加载到 next.js 应用程序?

c# - 当 Assert 语句在不同的方法中时使用 NUnit Multiple Assert

javascript - 为什么其他路由上没有加载bundle.js?

android - 是否有 Android 模拟器 AVD 的存储库?

javascript - Jest 'projects' 配置不读取子文件夹中的 .babelrc 和 webpack.config.json

javascript - Jest : cannot find module required inside module to be tested (relative path)

javascript - 函数在 React 组件中永远运行

reactjs - 设置 babel-plugin-styled-components + Typescript + create-react-app