After going crazy around a test that refuses to pass, I realized that the Select component in the Antd library does not handle more than 2 options. I wrote the following test to explore the issue:
import { Select } from 'antd';
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('Select', () => {
let user: ReturnType<typeof userEvent.setup>;
beforeAll(() => {
user = userEvent.setup();
});
it('shows more than 2 options', () => {
function Tmp() {
return (
<Select>
<Select.Option value='1'>1</Select.Option>
<Select.Option value='2'>2</Select.Option>
<Select.Option value='3'>3</Select.Option>
</Select>
);
}
render(<Tmp />);
await user.click(screen.getByRole('combobox'));
const options = screen.getAllByRole('option');
expect(options).toHaveLength(3);
expect(within(options[0]).getByText('1')).toBeInTheDocument();
expect(within(options[1]).getByText('2')).toBeInTheDocument();
expect(within(options[2]).getByText('3')).toBeInTheDocument();
});
});
This test fails. First it fails at the following line:
expect(options).toHaveLength(3);
It says that options
only have a length of 2.
When I remove that line, the test fails at the last expect:
expect(within(options[2]).getByText('3')).toBeInTheDocument();
It says that options[2]
is not an element. How can I make more options in the Select component available inside a test?
"antd": "^5.14.2"
The reason is virtual
prop for <Select/>
component is true
by default. It will use virtual list. The test will work if virtual
prop is set to false
.
Besides, you forget to use async
import { Select } from 'antd';
import { render, screen, within } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';
import React from 'react';
describe('Select', () => {
let user: ReturnType<typeof userEvent.setup>;
beforeAll(() => {
user = userEvent.setup();
});
it('shows more than 2 options', async () => {
function Tmp() {
return (
<Select virtual={false}>
<Select.Option value="1">1</Select.Option>
<Select.Option value="2">2</Select.Option>
<Select.Option value="3">3</Select.Option>
</Select>
);
}
render(<Tmp />);
await user.click(screen.getByRole('combobox'));
const options = screen.getAllByRole('option');
expect(options).toHaveLength(3);
expect(within(options[0]).getByText('1')).toBeInTheDocument();
expect(within(options[1]).getByText('2')).toBeInTheDocument();
expect(within(options[2]).getByText('3')).toBeInTheDocument();
});
});
Test result:
Select
√ shows more than 2 options (306 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.426 s, estimated 3 s
Ran all test suites related to changed files.