#reactjs #unit-testing #react-testing-library #react-jsonschema-forms #user-event
#reactjs #модульное тестирование #react-testing-library #react-jsonschema-forms #пользователь-событие
Вопрос:
Я не могу написать даже самые простые тесты для формы react jsonschema. Поскольку изменения входных элементов, похоже, не отражаются в dom.
Учитывая минимальную форму, подобную этой:
const schema = {
title: "Todo", type: "object",
properties: {
title: { type: "string", title: "Title", default: "A new task" }
}
};
const formData = { title: "First task aaa" };
export class MyForm extends React.Component {
render() { return <Form schema={schema} formData={formData} />; }
}
минимальный тест будет выглядеть так
test("changes input", async () => {
render(<MyForm />);
const input = screen.getByRole("textbox");
expect(input.value).toBe("First task aaa");
await userEvent.type(input, "567890", { delay: 10 });
expect(input.value).toBe("567890");
});
(Полный пример приведен в Codesandbox.)
После ввода в поле формы текст First task aaa
должен быть заменен на 567890
. К сожалению, это не так. input.value
сохраняет значение First task aaa
.
Я использовал много вариантов запуска событий и ожидания результатов, но всегда значение входного элемента остается неизменным.
Чего мне не хватает для тестирования <MyForm />
компонента? Мне кажется довольно стандартным.
Ответ №1:
Я также могу воспроизвести вашу проблему, и похоже, что react-jsonschema-form плохо работает с fireEvent
or userEvent
.
Однако, используя функцию моделирования react-doms, это работает:
import React from "react";
import { Simulate } from 'react-dom/test-utils'
import { render } from "@testing-library/react";
import { MyForm } from "./form.js";
// Tests in codesandbox fail in Safari - use Firefox or Chrome
// click on the "Tests" tab in the upper right.
test("changes input", async () => {
const { getByLabelText } = render(<MyForm />);
const input = getByLabelText("Title");
expect(input.value).toBe("First task aaa");
Simulate.change(input, { target: { value: '567890' }})
expect(input.value).toBe("567890");
});
Ответ №2:
С точки зрения того, что вы используете fluent-ui
библиотеку форм для своего пользовательского интерфейса, и это свяжет входное значение с вашим formData.title
полем. Это может прервать userEvent.type
действие. Чтобы просто протестировать userEvent.type
функциональность, вы можете создать свой компонент формы с чистым элементом ввода и привязать значение по умолчанию к defaultValue элемента ввода.
Например:
export class MyForm extends React.Component {
render() {
return <input type="text" defaultValue="First task aaa" />;
}
}
В случае, если вы увидите ошибку ниже в своем тестовом выводе:
expect(element).toHaveValue(567890)
Expected the element to have value:
567890
Received:
First task aaa567890
13 | expect(input).toHaveValue("First task aaa");
14 | userEvent.type(input, '567890');
> 15 | expect(input).toHaveValue('567890');
| ^
16 | });
Как вы можете видеть, userEvent.type
к текущему значению будет добавлен дополнительный ввод. Итак, вы можете просто использовать Simulate.change
функциональность или использовать userEvent.clear
функцию перед своей userEvent.type
строкой, как показано ниже.
test("changes input", async () => {
render(<MyForm />);
const input = screen.getByRole("textbox");
expect(input).toHaveValue("First task aaa");
userEvent.clear(input);
userEvent.type(input, "567890");
expect(input).toHaveValue("567890");
});
Этот ответ может быть полезен для вашего вопроса.
Приветствия!