如何使用 React 测试库从 select 列表中 select 一个选项
How to select an option from a select list with React Testing Library
我有一个正常的 select 列表。我需要测试 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
并没有 return 任何东西,也许这是因为它在页面上不可见?
在选项中添加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
仅适用于显示值
这个解决方案对我不起作用,有用的是 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();
//...
})
如果您有标签(您应该这样做!),您也可以放弃必须向 select 元素添加 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();
//...
})
这似乎是进行此类测试的更佳方法。
您也可以使用 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();
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 测试库测试 select 元素的更多信息。
这对我来说似乎更简单:
userEvent.selectOptions(screen.getByLabelText('County'), 'Aberdeenshire');
我有一个正常的 select 列表。我需要测试 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
并没有 return 任何东西,也许这是因为它在页面上不可见?
在选项中添加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
仅适用于显示值
这个解决方案对我不起作用,有用的是 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();
//...
})
如果您有标签(您应该这样做!),您也可以放弃必须向 select 元素添加 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();
//...
})
这似乎是进行此类测试的更佳方法。
您也可以使用 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();
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 测试库测试 select 元素的更多信息。
这对我来说似乎更简单:
userEvent.selectOptions(screen.getByLabelText('County'), 'Aberdeenshire');