Пользовательский интерфейс Formik Material и библиотека тестирования react

#reactjs #material-ui #formik #react-testing-library

#reactjs #материал-пользовательский интерфейс #formik #react-testing-library

Вопрос:

Мне сложно работать с библиотекой тестирования react и понимать запросы, которые мне нужно использовать, чтобы выбрать компоненты, которые мне нужно протестировать. Запросы становятся слишком упрощенными, когда DOM становится все более подробным с такими фреймворками, как material ui и formik.

Я создал изолированную среду для кода, чтобы проиллюстрировать проблему. Там вы можете проверить неудачный тест.

https://codesandbox.io/embed/px277lj1x

Проблема, которую я получаю, заключается в том, что запрос getLabelTextBy() не возвращает компонент. Похоже, что метка aria by или атрибут for не отображаются в пользовательском интерфейсе material. Не уверен, как исправить эту ошибку.

Код также приведен ниже для справки

 //Subject under test

import React from "react";
import { Button } from "@material-ui/core";
import { TextField } from "formik-material-ui";
import { Field, Form, Formik } from "formik";
import * as yup from "yup";

const validationSchema = yup.object().shape({
  name: yup.string().required("Office name is required"),
  address: yup.string().required("Address is required")
});

export default () => (
  <Formik
    initialValues={{
      name: "",
      address: ""
    }}
    validationSchema={validationSchema}
    onSubmit={(values, { setSubmitting }) => {
      setSubmitting(false);
      console.log("form is submitted with", values);
    }}
    render={({ submitForm, isSubmitting, isValid }) => (
      <Form>
        <Field
          label="Office Name"
          name="name"
          required
          type="text"
          component={TextField}
        />
        <Field
          label="Address Line 1"
          name="addressLine1"
          type="text"
          component={TextField}
        />
        <Button
          variant="contained"
          color="primary"
          fullWidth={false}
          size="medium"
          disabled={isSubmitting || !isValid}
          onClick={submitForm}
          data-testid="submitButton"
        >
          Submit
        </Button>
      </Form>
    )}
  />
);


// Test
import React from "react";
import { render, fireEvent } from "react-testing-library";
import App from "./App";

describe("Create Office Form tests", () => {
  it("button should not be disabled when all required fields are filled up", () => {
    const { getByLabelText, getByTestId, debug } = render(<App />);
    const values = {
      "office name": "office",
      address: "address 1"
    };
    for (const key in values) {
      const input = getByLabelText(key, { exact: false, selector: "input" });
      fireEvent.change(input, { target: { value: values[key] } });
    }
    const button = getByTestId("submitButton");
    expect(button.disabled).not.toBeDefined();
  });
});

  

Ответ №1:

Вы должны добавить id в свой Field , потому что for атрибут label ожидает идентификатор элемента ввода, на который он ссылается:

         <Field
          id="myName"
          label="Office Name"   
          name="name"
          required
          type="text"
          component={TextField}
        />
  

Рабочий пример:

Редактировать пользовательский интерфейс Formiq Yup Material и библиотеку тестирования react

Комментарии:

1. Пример не работает, кнопка отключена после заполнения формы. Просто попытался запустить тесты в codesandbox, и они завершились неудачей.

Ответ №2:

Несколько вещей. Создатель библиотеки не рекомендует использовать {getByLabelText, getByTestId, debug}. Вам следует использовать screen.getByLabelText() .

Если есть изменение, возможно, оно не ожидает нового рендеринга, поэтому было бы лучше дождаться его или обернуть ожидание в метод waitFor.

Кроме того, expect(button.disabled).not.toBeDefined() не должно быть правильным. Я думаю, вы просто проверяете, отключена кнопка или нет, верно? Таким образом, вы можете использовать expect(button).toBeDisabled() или not.toBeDisabled()

По крайней мере, чтобы протестировать это, я думаю, вам следует отключить цикл for и проверить его в обычном режиме. Вы можете использовать screen.debug (компонент), чтобы отобразить HTML-код после некоторого действия.