React Testing Library with TypeScript:设置输入值
React Testing Library with TypeScript: Set an input's value
我正在使用 TypeScript 构建一个 React 应用程序。我使用 React 测试库进行组件测试。
假设您有这样的简单形式:
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}
在 this video 中,Kent(库的创建者)展示了如何测试表单输入。测试看起来像这样:
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',
})
})
问题是他是用普通的 JavaScript 做的。这样做时
TypeScript 他设置 .value
的行抛出以下错误
[ts] Property 'value' does not exist on type 'HTMLElement'.
如何使用 React 测试库通过 TypeScript 测试这一功能?您将如何设置输入的值?
该库提供的类型将 getByLabelText
的 return 值键入为类型:HTMLElement
。并非所有 HTML 元素都具有 value
属性,只有 HTMLInputElement
这样的元素才具有。
getByLabelText
也没有通用类型,您可以通过它影响输出类型,因此基本上您需要将结果不安全地转换为 HTMLInputElement
类型,或者您将需要构建一个辅助函数来告诉 TypeScript 对象的类型是否正确:
不安全的转换。您真正需要做的就是将对 getByLabelText
的任何调用更新为 value
属性 的类型:
(getByLabelText(/username/i) as HTMLInputElement).value = 'chuck';
类型验证。这种方法更安全一些,因为您可以提供一个类型验证函数,它会导致 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...
}
我正在使用 TypeScript 构建一个 React 应用程序。我使用 React 测试库进行组件测试。
假设您有这样的简单形式:
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}
在 this video 中,Kent(库的创建者)展示了如何测试表单输入。测试看起来像这样:
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',
})
})
问题是他是用普通的 JavaScript 做的。这样做时
TypeScript 他设置 .value
的行抛出以下错误
[ts] Property 'value' does not exist on type 'HTMLElement'.
如何使用 React 测试库通过 TypeScript 测试这一功能?您将如何设置输入的值?
该库提供的类型将 getByLabelText
的 return 值键入为类型:HTMLElement
。并非所有 HTML 元素都具有 value
属性,只有 HTMLInputElement
这样的元素才具有。
getByLabelText
也没有通用类型,您可以通过它影响输出类型,因此基本上您需要将结果不安全地转换为 HTMLInputElement
类型,或者您将需要构建一个辅助函数来告诉 TypeScript 对象的类型是否正确:
不安全的转换。您真正需要做的就是将对
getByLabelText
的任何调用更新为value
属性 的类型:(getByLabelText(/username/i) as HTMLInputElement).value = 'chuck';
类型验证。这种方法更安全一些,因为您可以提供一个类型验证函数,它会导致 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... }