reactjs 测试DOM-Testing-Library或React-Testing-Library中输入值的最佳方法

czfnxgou  于 2023-03-22  发布在  React
关注(0)|答案(6)|浏览(165)

测试dom-testing-library/react-testing-library<input>元素值的最佳方法是什么?
我采用的方法是通过closest()方法获取原始输入元素本身,然后直接访问value属性:

const input = getByLabelText("Some Label")
expect(input.closest("input").value).toEqual("Some Value")

我希望有一种方法可以做到这一点,而不必直接访问HTML属性。这似乎不符合测试库的精神。也许像jest-dom toHaveTextContent matcher matcher:

const input = getByLabelText("Some Label")
expect(input).toHaveTextContent("Some Value")

更新

根据注解中的请求,这里有一个代码示例,显示了我觉得需要测试输入框中的值的情况。
这是我在我的应用程序中构建的模态组件的简化版本。* 就像,非常简化。* 这里的整个想法是,模态打开时输入预先填充了一些文本,基于字符串prop。用户可以自由编辑此输入并通过按下按钮提交它。但是,如果用户关闭模态然后重新打开它,我想让文本重置为原来的字符串prop。我写了一个测试,因为以前版本的模态没有重置输入值。
我用TypeScript写这个,这样每个prop的类型都很清楚。

interface Props {
  onClose: () => void
  isOpen: boolean
  initialValue: string
}

export default function MyModal({ onClose, isOpen, initialValue }) {
  const [inputValue, setInputValue] = useState(initialValue)

  // useEffect does the reset!
  useEffect(() => {
    if (!isOpen) {
      setNameInput(initialValue)
    }
  }, [isOpen, initialValue])

  return (
    <SomeExternalLibraryModal isOpen={isOpen} onClose={onClose}>
      <form>
        <input
          value={inputValue}
          onChange={(e: ChangeEvent<HTMLInputElement>) =>
            setInputValue(e.target.value)
          }
        />
        <button onClick={onClose}>Cancel</button>
      </form>
    </SomeExternalLibraryModal>
  )
}
um6iljoc

um6iljoc1#

你对你的测试方法的怀疑是正确的,关于这个测试库希望你如何测试。这个问题最简单的答案是使用getByDisplayValue查询。它将搜索一个输入,textarea,或者选择具有你试图找到的值。例如,以你的组件为例,如果我试图验证inputValue = 'test',我会搜索像

expect(screen.getByDisplayValue('test')).toBeInTheDocument();

这就是你需要做的。我假设你的测试只是渲染MyModal组件。即使你有多个输入,在测试哲学方面也没有关系。只要getByDisplayValue找到任何具有该值的输入,它就是一个成功的测试。如果你有多个输入,并希望测试确切的输入具有该值,然后,您可以深入分析元素以确定它是正确的输入:
注意:你需要jest-dom来完成这个任务。

expect(screen.getByDisplayValue('test')).toHaveAttribute('id', 'the-id');

或(不含jest-dom):

expect(screen.getByDisplayValue('test').id).toBe('the-id');

你当然可以搜索任何你喜欢的属性。
测试值的最后一种方法是按角色查找输入。这在示例中不起作用,除非添加标签并通过htmlFor属性将其关联到输入。然后可以像这样测试:

expect(screen.getByRole('input', { name: 'the-inputs-id' })).toHaveValue('test');

或(不含jest-dom):

expect(screen.getByRole('input', { name: 'the-inputs-id' }).value).toBe('test');

我相信这是测试值的最佳方法,同时确保正确的输入具有该值。我建议使用getByRole方法,但同样,您需要在示例中添加一个标签。

kb5ga3dv

kb5ga3dv2#

您可以使用screen.getByDisplayValue()来获取具有显示值的输入元素,并将其与您的元素进行比较。

type TestElement = Document | Element | Window | Node

function hasInputValue(e: TestElement, inputValue: string) {
  return screen.getByDisplayValue(inputValue) === e
}

在您的测试中:

const input = screen.getByLabelText("Some Label")

fireEvent.change(input, { target: { value: '123' } })
expect(hasInputValue(input, "123")).toBe(true)
c90pui9n

c90pui9n3#

expect(screen.getByLabelText("Name")).toHaveValue("hello");-这会得到输入的值:)

<label class="label" for="name">
      Name
</label>
<div class="control ">
       <input
          class="input"
          for="name"
          id="name"
          name="name"
          value="hello"
       />
</div>

试验:

userEvent.type(screen.getByLabelText("Name"), "hello")
await waitFor(() => {
   expect(screen.getByLabelText("Name")).toHaveValue("hello");
});
ctzwtxfj

ctzwtxfj4#

使用@testing-library/dom(或任何wrapped libraries here
您可以:

expect(inputField).toHaveDisplayValue('some input value');

完整示例:

test('should show input with initial value set', async () => {
  render(<Input type="text" value="John Doe" data-testid="form-field-firstname" />);

  const inputField = await screen.findByTestId(`form-field-firstname`);
  await waitFor(() => expect(inputField).toHaveDisplayValue('John Doe')));
});
rsaldnfx

rsaldnfx5#

有非常干净的方法来测试它使用测试库。

//In describe
  const renderComponent = (searchInputValue, handleSearchInputValue) => {
    const wrapper = render(<yourComponentWithInput
      value={searchInputValue}
      onChange={handleSearchInputValue}
    />);
    return wrapper;
  };

//In test
    const mockHandleSearchInputValue = jest.fn();
    const { getByLabelText } = renderComponent('g', mockHandleSearchInputValue);
    const inputNode = getByLabelText('Search label'); // your  input label
    expect(inputNode.value).toBe('s'); // to test input value
    fireEvent.change(inputNode, { target: { value: 'su' } }); // triggers onChange event
    expect(mockHandleSearchInputValue).toBeCalledWith('su'); // tests if onChange handler is called with proper value
5gfr0r5j

5gfr0r5j6#

我检查了所有的答案,但没有人告诉我们,我们可以访问输入与**querySelector**这些步骤:
1.使用screen呈现和访问UI组件
1.父HTMLElement与getByTestIdgetByText或任何其他
1.使用querySelector访问输入

it('Input value should be 1'() => {
  const input = screen.getByTestId('wrapperId').querySelector('input')
  expect(input).toHaveValue(1);
})

相关问题