React-testing-library:因输入而改变
React-testing-library: changes due to input
我正在尝试测试组件是否会因输入元素的更改而更新。我使用 fireEvent.change()
函数,如果我随后检查我使用 getByPlaceholderText
找到的节点的值,它已经按预期更新了。但是我看不到反应组件本身的变化。
这可能是因为在重新渲染之前不会发生更改;我将如何测试这个? react-testing-library 的 rerender
似乎启动了组件 "from scratch"(即没有新的输入值),并且 waitForElement
永远找不到它在等待什么。
这是组件 TestForm.js:
import React from 'react';
import { withState } from 'recompose';
const initialInputValue = 'initialInputValue';
const TestForm = ({ inputValue, setInputValue }) => (
<>
{console.log('inputValue', inputValue)}
<input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="placeholder" />
{inputValue !== initialInputValue && <div>Input has changed</div>}
</>
);
export default withState('inputValue', 'setInputValue', initialInputValue)(TestForm);
这是测试,运行 使用 npx jest test.js
:
import React from 'react';
import { cleanup, fireEvent, render, waitForElement } from 'react-testing-library';
import TestForm from './TestForm';
afterEach(cleanup);
describe('TestForm', () => {
it('Change input', async () => {
const { getByPlaceholderText, getByText } = render(<TestForm />);
const inputNode = getByPlaceholderText('placeholder');
fireEvent.change(inputNode, { target: { value: 'new value' } });
console.log('inputNode.value', inputNode.value);
await waitForElement(() => getByText('Input has changed'));
});
});
这段代码对我有用:
import React from "react";
const initialInputValue = "initialInputValue";
class TestForm extends React.Component {
constructor(props) {
super(props);
this.state = { inputValue: initialInputValue };
}
render() {
const { inputValue } = this.state;
return (
<div>
{console.log("inputValue", inputValue)}
<input
value={inputValue}
onChange={e => this.setState({ inputValue: e.target.value })}
placeholder="placeholder"
/>
{inputValue !== initialInputValue && <div>Input has changed</div>}
</div>
);
}
}
import { render, cleanup, fireEvent } from "react-testing-library";
import "jest-dom/extend-expect";
afterEach(cleanup);
test("form", () => {
const { getByPlaceholderText, getByText } = render(<TestForm />);
fireEvent.change(getByPlaceholderText("placeholder"), {
target: { value: "new value" }
});
expect(getByText("Input has changed")).toBeInTheDocument();
});
尽管它在 codesandbox 中不起作用,我猜他们在保持浏览器和测试环境分离方面存在一些问题。
使用 user-event 库
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
afterEach(cleanup);
test("form", async () => {
const user = userEvent.setup();
const { getByPlaceholderText, getByText } = render(<TestForm />);
await user.type(getByPlaceholderText("placeholder"), "new value");
await waitFor(() => {
expect(getByText("Input has changed")).toBeInTheDocument();
});
});
我正在尝试测试组件是否会因输入元素的更改而更新。我使用 fireEvent.change()
函数,如果我随后检查我使用 getByPlaceholderText
找到的节点的值,它已经按预期更新了。但是我看不到反应组件本身的变化。
这可能是因为在重新渲染之前不会发生更改;我将如何测试这个? react-testing-library 的 rerender
似乎启动了组件 "from scratch"(即没有新的输入值),并且 waitForElement
永远找不到它在等待什么。
这是组件 TestForm.js:
import React from 'react';
import { withState } from 'recompose';
const initialInputValue = 'initialInputValue';
const TestForm = ({ inputValue, setInputValue }) => (
<>
{console.log('inputValue', inputValue)}
<input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="placeholder" />
{inputValue !== initialInputValue && <div>Input has changed</div>}
</>
);
export default withState('inputValue', 'setInputValue', initialInputValue)(TestForm);
这是测试,运行 使用 npx jest test.js
:
import React from 'react';
import { cleanup, fireEvent, render, waitForElement } from 'react-testing-library';
import TestForm from './TestForm';
afterEach(cleanup);
describe('TestForm', () => {
it('Change input', async () => {
const { getByPlaceholderText, getByText } = render(<TestForm />);
const inputNode = getByPlaceholderText('placeholder');
fireEvent.change(inputNode, { target: { value: 'new value' } });
console.log('inputNode.value', inputNode.value);
await waitForElement(() => getByText('Input has changed'));
});
});
这段代码对我有用:
import React from "react";
const initialInputValue = "initialInputValue";
class TestForm extends React.Component {
constructor(props) {
super(props);
this.state = { inputValue: initialInputValue };
}
render() {
const { inputValue } = this.state;
return (
<div>
{console.log("inputValue", inputValue)}
<input
value={inputValue}
onChange={e => this.setState({ inputValue: e.target.value })}
placeholder="placeholder"
/>
{inputValue !== initialInputValue && <div>Input has changed</div>}
</div>
);
}
}
import { render, cleanup, fireEvent } from "react-testing-library";
import "jest-dom/extend-expect";
afterEach(cleanup);
test("form", () => {
const { getByPlaceholderText, getByText } = render(<TestForm />);
fireEvent.change(getByPlaceholderText("placeholder"), {
target: { value: "new value" }
});
expect(getByText("Input has changed")).toBeInTheDocument();
});
尽管它在 codesandbox 中不起作用,我猜他们在保持浏览器和测试环境分离方面存在一些问题。
使用 user-event 库
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
afterEach(cleanup);
test("form", async () => {
const user = userEvent.setup();
const { getByPlaceholderText, getByText } = render(<TestForm />);
await user.type(getByPlaceholderText("placeholder"), "new value");
await waitFor(() => {
expect(getByText("Input has changed")).toBeInTheDocument();
});
});