reactjsantdreact-testing-library

Antd Select component does not show more than 2 options in tests


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?


Solution

  • "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.