使用TypeScript的React Testing Library:设置输入值

时间:2018-11-07 18:13:34

标签: reactjs typescript unit-testing htmlelements react-testing-library

我正在使用TypeScript构建一个React应用程序。我使用React Testing Library进行组件测试。

假设您的表单很简单:

    CTScaling ctScaling = ...
    ...
    CTValAx ctValAx = ctPlotArea.addNewValAx(); 
    ctValAx.addNewAxId().setVal(123457); //id of the val axis
    ctScaling = ctValAx.addNewScaling();
    ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

    ctScaling.addNewMin().setVal(0.2);
    ctScaling.addNewMax().setVal(0.7);

    ctValAx.addNewDelete().setVal(false);
    ctValAx.addNewAxPos().setVal(STAxPos.L);
    ctValAx.addNewCrossAx().setVal(123456); //id of the cat axis
    ctValAx.addNewCrosses().setVal(STCrosses.AUTO_ZERO); //this val axis crosses the cat axis at zero
    ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
    ...

this video中,Kent(库的创建者)展示了如何测试表单输入。测试看起来像这样:

import React from 'react'

function Login({onSubmit}) {
  return (
    <div>
      <form
        onSubmit={e => {
          e.preventDefault()
          const {username, password} = e.target.elements
          onSubmit({
            username: username.value,
            password: password.value,
          })
        }}
      >
        <label htmlFor="username">Username</label>
        <input id="username" />
        <label htmlFor="password">Password</label>
        <input id="password" type="password" />
        <br />
        <button type="submit">Submit</button>
      </form>
    </div>
  )
}

export {Login}

问题在于他使用纯JavaScript做到了。当这样做 在他设置import React from 'react' import {renderIntoDocument, cleanup} from 'react-testing-library' import {Login} from '../login' afterEach(cleanup) test('calls onSubmit with username and password', () => { const handleSubmit = jest.fn() const {getByLabelText, getByText} = renderIntoDocument( <Login onSubmit={handleSubmit} />, ) getByLabelText(/username/i).value = 'chuck' getByLabelText(/password/i).value = 'norris' getByText(/submit/i).click() expect(handleSubmit).toHaveBeenCalledTimes(1) expect(handleSubmit).toHaveBeenCalledWith({ username: 'chuck', password: 'norris', }) }) 的行中键入TypeScript会引发以下错误

.value

如何使用React Testing Library使用TypeScript测试此功能?您将如何设置输入的值?

1 个答案:

答案 0 :(得分:7)

该库提供的类型将getByLabelText的返回值键入为HTMLElement。并非所有HTML元素都具有value属性,只有HTMLInputElement之类的属性。

getByLabelText也没有通用类型,您可能无法通过该通用类型来影响输出类型,因此从本质上讲,您将需要不安全地将结果强制转换为类型HTMLInputElement,否则您将需要构建一个帮助函数,该函数告诉TypeScript对象是否为正确的类型:

  1. 不安全的投射。您真正需要做的就是将对getByLabelText的任何调用更新为具有value属性的类型,以:

    (getByLabelText(/username/i) as HTMLInputElement).value = 'chuck';
    
  2. 类型验证。此方法较为安全,因为您可以提供类型验证功能,该功能将导致TypeScript更新类型:

    function isElementInput<T extends HTMLElement>(element: T): T is HTMLInputElement {
        // Validate that element is actually an input
        return element instanceof HTMLInputElement;
    }
    
    // Update your attempted value sets:
    const elem = getByLabelText(/username/i);
    if (isElementInput(elem)) {
        elem.value = 'chuck';
    } else {
        // Handle failure here...
    }