如何使用 React 测试库从选择列表中选择一个选项
Posted
技术标签:
【中文标题】如何使用 React 测试库从选择列表中选择一个选项【英文标题】:How to select an option from a select list with React Testing Library 【发布时间】:2020-01-16 16:50:45 【问题描述】:我有一个正常的选择列表。当我选择一个选项时,我需要测试 handleChoice 是否被调用。如何使用 React 测试库做到这一点?
<select
onChange=handleChoice
data-testid="select"
>
<option value="default">Make your choice</option>
attributes.map(item =>
return (
<option key=item.key value=item.key>
item.label
</option>
);
)
</select>
getByDisplayValue
的值为item.label
不返回任何内容,可能是因为它在页面上不可见?
【问题讨论】:
你试过fireEvent.change(getByTestId("select"), target: value: '<item label>' );
好像不像getByTestId("select"),报错:TypeError: container.querySelectorAll is not a function
【参考方案1】:
在 2021 年,您可以使用 userEvent,它是 React 测试库生态系统的一部分。它允许您编写更接近真实用户行为的测试。示例:
it('should correctly set default option', () =>
render(<App />)
expect(screen.getByRole('option', name: 'Make a choice').selected).toBe(true)
)
it('should allow user to change country', () =>
render(<App />)
userEvent.selectOptions(
// Find the select element
screen.getByRole('combobox'),
// Find and select the Ireland option
screen.getByRole('option', name: 'Ireland'),
)
expect(screen.getByRole('option', name: 'Ireland').selected).toBe(true)
)
查看this article,了解有关如何使用 React 测试库测试选择元素的更多信息。
【讨论】:
【参考方案2】:这对我来说似乎更简单:
userEvent.selectOptions(screen.getByLabelText('County'), 'Aberdeenshire');
【讨论】:
【参考方案3】:你也可以使用getByText
,这样你就不用添加data-testid
属性了
在我的情况下,我做到了
import screen from '@testing-library/react';
....
<select>
<option value="foo">Foo</option>
<option selected value="bar">Bar</option>
</select>
....
expect((screen.getByText('Foo') as htmlOptionElement).selected).toBeFalsy();
expect((screen.getByText('Bar') as HTMLOptionElement).selected).toBeTruthy();
【讨论】:
【参考方案4】:这个解决方案对我不起作用,起作用的是 userEvent。 https://testing-library.com/docs/ecosystem-user-event/
import React from 'react';
import render from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
test('Simulates selection', () =>
const getByTestId = render(<App />);
// where <value> is the option value without angle brackets!
userEvent.selectOptions(getByTestId('select'), '<value>');
expect((getByTestId('<value>') as HTMLOptionElement).selected).toBeTruthy();
expect((getByTestId('<another value>') as HTMLOptionElement).selected).toBeFalsy();
//...
)
如果您有标签(您应该这样做!),您也可以放弃在选择元素中添加data-testid
,而只需使用getByLabelText('Select')
此外,如果您使用 getByText
,则可以去掉每个选项元素上的额外 data-testid
。
<label for="selectId">
Select
</label>
<select
onChange=handleChoice
id="selectId"
>
<option value="default">Make your choice</option>
attributes.map(item =>
return (
<option key=item.key value=item.key>
item.label
</option>
);
)
</select>
然后:
import React from 'react';
import render from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
test('Simulates selection', () =>
const getByLabelText, getByText = render(<App />);
// where <value> is the option value without angle brackets!
userEvent.selectOptions(getByLabelText('<your select label text>'), '<value>');
expect((getByText('<your selected option text>') as HTMLOptionElement).selected).toBeTruthy();
expect((getByText('<another option text>') as HTMLOptionElement).selected).toBeFalsy();
//...
)
这似乎是进行此类测试的最佳方式。
【讨论】:
【参考方案5】:在选项中添加data-testid
<option data-testid="select-option" key=item.key value=item.key>
item.label
</option>
然后,在测试调用fireEvent.change
中,通过getAllByTestId
获取所有选项并勾选选中的选项:
import React from 'react';
import render, fireEvent from '@testing-library/react';
import App from './App';
test('Simulates selection', () =>
const getByTestId, getAllByTestId = render(<App />);
//The value should be the key of the option
fireEvent.change(getByTestId('select'), target: value: 2 )
let options = getAllByTestId('select-option')
expect(options[0].selected).toBeFalsy();
expect(options[1].selected).toBeTruthy();
expect(options[2].selected).toBeFalsy();
//...
)
对于您的问题,getByDisplayValue
仅适用于显示的值
【讨论】:
fireEvent.change
对我不起作用;我用了fireEvent.click
,效果很好。以上是关于如何使用 React 测试库从选择列表中选择一个选项的主要内容,如果未能解决你的问题,请参考以下文章