【问题标题】:How to test that a dropdown selector has value set in React with React Testing Library?如何使用 React 测试库测试下拉选择器是否在 React 中设置了值?
【发布时间】:2022-01-15 12:11:53
【问题描述】:

有以下代码:

    import { useForm, Controller } from 'react-hook-form';
    ...
      const { handleSubmit, reset, control, register, watch } = useForm({
        resolver: yupResolver(schema)
      });
    
    
    const availableSensorPoolOptions = [
      { id: '0', name: 'sensor pool 0' },
      { id: '1', name: 'sensor pool 1' },
      { id: '2', name: 'sensor pool 2' }
    ];
    
    
    ...

onSubmit={handleSubmit(onAddSubmit)} // the action when the submit is called

...
  const onAddSubmit = (data) => {
    postSignalMapping(data); // the API call if all is good
    toggle();
    reset();
  };

...
    
              <div data-testid={MapSignalModalTestIds.AVAILABLE_SENSOR_POOL}>
                <Controller
                  control={control}
                  name='availableSensorPool'
                  render={({ field: { onChange } }) =>
                    <SelectInput
                      label={t('calculation-engine.available-sensor-pool')}
                      initialSelectedOption={{ id: '0', name: '' }}
                      onChange={onChange}
                      options={availableSensorPoolOptions}
                    />
                  }
                />
              </div>

有多个像 thi 的SelectInputs,但在本例中只有一个

const schema = yup.object().shape({
  availableSensorPool: yup.object().shape({
    id: yup.string(),
    name: yup.string()
  })
});

  const { handleSubmit, reset, control, register, watch } = useForm({
    resolver: yupResolver(schema)
  });

这是测试:

import { fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { renderWithClientInstance } from '@oam/shared/test-utils';

import '@testing-library/jest-dom';
import MapSignalModal from './map-signal-modal';
describe('MapSignalModal', () => {
  const title = 'title';
  const toggle = jest.fn();
  const postSignalMapping = jest.fn();

  it('should call postSignalMapping function on clicking in Save button successfully', async () => {
    const { getByTestId, getByLabelText } = renderWithClientInstance(
      <MapSignalModal title={title} open={true} toggle={toggle} />
    );

    const saveButton = getByTestId('submit-button');
    expect(saveButton).toBeInTheDocument();

    userEvent.selectOptions(
      getByLabelText('calculation-engine.available-sensor-pool'),
      'sensor pool 0'
    );

    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(postSignalMapping).toBeCalled();
    });
  });
});

它失败并出现错误:

TestingLibraryElementError:在选项中找不到值“传感器池 0”

【问题讨论】:

  • 让我们在这里做一些调试,你能告诉选项显示什么文本吗?我的意思是您在屏幕上看到的选项是什么文字?
  • 但是您不会在屏幕上看到数组,对吧?您会看到idname。在render 删除其他所有内容之后,您可以做一件事吗?只需将screen.debug() 放入您的测试。你会从'@testing-library/react'导入screen
  • 它不显示该部分,它不显示整个屏幕,我注释掉了单元和描述以查看可用传感器池。这是输出:pastebin.com/gxF7qm0A
  • 哦,所以它实际上并没有创建select DOM 节点,它由divs 和spans 组成。那我来补充一下吧

标签: reactjs unit-testing types react-testing-library react-hook-form


【解决方案1】:

因此,由于 select 行为是使用 buttonspans 实现的。

您需要先单击按钮,该按钮会在屏幕上显示所有选项,然后您需要单击其中一个选项。

然后您终于可以测试所选选项现在是否在屏幕上。

it("test dropdpwn", async () => {
  const { getByTestId, getByLabelText } = renderWithClientInstance(
    <MapSignalModal title={title} open={true} toggle={toggle} />
  );

  userEvent.click(screen.getAllByTestId("selectButton")[0]);
  userEvent.click(screen.getByText("sensor pool 1"));

  expect(
    await screen.findByText(screen.getByText("sensor pool 1"))
  ).toBeInTheDocument();
});

另外,为了确保您可以尝试以下操作,这应该会失败,因为“传感器池 1”选项最初不在屏幕上。

当文本更改为“传感器池 0”时它应该会通过,因为它最初就在屏幕上。

it("test dropdpwn", async () => {
  const { getByTestId, getByLabelText } = renderWithClientInstance(
    <MapSignalModal title={title} open={true} toggle={toggle} />
  );

  expect(screen.getByText("sensor pool 1")).toBeInTheDocument();
  // if you replace the above text to "sensor pool 0", it should work
});

为了测试postSignalMapping是否被调用,你可以模拟它,如下所示:

let mockPostSignalMapping = jest.fn();
jest.mock("../lib/hooks/use-post-signal-mapping", () => ({
  mutate: mockPostSignalMapping,
}));

it("test dropdpwn", async () => {
  // Do stuff

  await waitFor(() => {
    expect(mockPostSignalMapping).toBeCalled();
  });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2020-04-26
    • 2020-11-11
    • 2021-11-09
    • 2021-06-14
    • 1970-01-01
    • 2023-02-09
    相关资源
    最近更新 更多