Не удается найти оповещение по доступному имени
Я пишу тест на соответствие следующему бизнес-правилу:
Если мы выберем
Canada
в раскрывающемся списке страны отображать сообщения об ошибках размытия для полей провинции и почтового индекса, если они пусты.
Моя тестируемая финальная форма React:
<Form
onSubmit={onSubmit}
validate={values => {
const errors: ValidationErrors = {};
if (!values.country) {
errors.country = "Country must be selected";
}
if (values.country === "Canada" && !values.province) {
errors.province = "Province must be provided";
}
if (values.country === "Canada" && !values.postalCode) {
errors.postalCode = "Postal code must be provided";
}
return errors;
}}
render={({
...
}) => (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="country">Country</label>
<br />
<Field<string> id="country" name="country" component="select">
<option />
<option value="Canada">Canada</option>
<option value="US">US</option>
</Field>
</div>
<Condition when="country" is="Canada">
<div>
<label htmlFor="province">Province</label>
<br />
<Field id="province" name="province" component="input" />
<Error name="province" />
</div>
<div>
<label htmlFor="postalCode">Postal Code</label>
<br />
<Field id="postalCode" name="postalCode" component="input" />
<Error name="postalCode" />
</div>
</Condition>
...
</form>
)}
Тест, который я пишу, выглядит так:
describe("Contact form", () => {
test("should show errors if Canada is seledted but province and postal code are blank", async () => {
const { getByLabelText, findByRole } = render(<ContactForm />);
fireEvent.change(getByLabelText("Country"), {
target: { value: "Canada" }
});
fireEvent.change(getByLabelText("Province"), {
target: { value: "" }
});
fireEvent.change(getByLabelText("Postal Code"), {
target: { value: "" }
});
fireEvent.blur(getByLabelText("Postal Code"));
const postalAlert = await findByRole("alert", {
name: "Postal code must be provided"
});
expect(postalAlert).toBeInTheDocument();
const provinceAlert = await findByRole("alert", {
name: "Province must be provided"
});
expect(provinceAlert).toBeInTheDocument();
Я пытаюсь вызвать сообщения об ошибках, которые отображаются с помощью role="alert"
- но мой тест не проходит с: Unable to find role="alert"
Теперь, если я удалю name
свойство, которое я пытаюсь отфильтровать, то alert
найден:
const postalAlert = await findByRole("alert"); // SUCCESS
Я мог получать оповещения с помощью findAllByRole
и перебирать их, но я бы просто хотел запросить каждый из них явно с их доступным именем и подтвердить, что они есть в документе.
Я вижу элемент, когда экран отлажен, я просто хочу выяснить, как запросить его напрямую с его ролью и именем:
<span
role="alert"
style="color: rgb(153, 0, 0);"
>
Postal code must be provided
</span>
Пример формы: https://codesandbox.io/s/react-ts-unit-test-example-6scjc?file=/src/ContactForm.test.tsx
2 ответа
Есть несколько причин, по которым вы не можете пройти тест
Похоже, что span не применяет текстовое содержимое в качестве доступного имени, вы можете использовать aria-label, чтобы установить для него доступное имя, подробнее здесь
export const Error = (props: Props) => {
const {
meta: { touched, error }
} = useField(props.name, { subscription: { touched: true, error: true } });
return touched && error ? (
// add aria-label to set accessiable name for span
<span aria-label={error} role="alert" style={{ color: "#900" }}>
{error}
</span>
) : null;
};
Вы вызываете только размытие "Почтовый индекс", но ваш тест также включает ошибку провинции, реализация состоит в том, что вы показываете ошибку провинции при размытии ввода провинции, поэтому вам нужно добавить это в свой тест
import * as React from "react";
import { render, fireEvent } from "@testing-library/react";
import { ContactForm } from "./ContactForm";
describe("Contact form", () => {
test("should show errors if Canada is seledted but province and postal code are blank", async () => {
const { getByLabelText, findByRole } = render(<ContactForm />);
fireEvent.change(getByLabelText("Country"), {
target: { value: "Canada" }
});
fireEvent.change(getByLabelText("Province"), {
target: { value: "" }
});
fireEvent.change(getByLabelText("Postal Code"), {
target: { value: "" }
});
// you only blur "Postal Code"
fireEvent.blur(getByLabelText("Postal Code"));
const postalAlert = await findByRole("alert", {
name: "Postal code must be provided"
});
expect(postalAlert).toBeInTheDocument();
// This will not shown because you have not called blur Province
// comment this or add the line below to pass the test
// fireEvent.blur(getByLabelText("Province"));
const provinceAlert = await findByRole("alert", {
name: "Province must be provided"
});
expect(provinceAlert).toBeInTheDocument();
});
});
findByRole()
не работает с передачей name
. Я бы написал этот тест, используяgetByText()
. Также обратите внимание, что вы должны "размыть" поле "Провинция", чтобы отображалась его ошибка, поскольку вы показываете ошибку только при "касании" поля.