1
votes

I am finding it hard to work with react testing library and understand the queries I need to use in order to select the components I need to test. The queries are too simplistic when the DOM gets more and more verbose with frameworks like material ui and formik.

I have created a code sandbox to illustrate the problem. You can check the failing test there.

https://codesandbox.io/embed/px277lj1x

The issue I am getting is, the query getLabelTextBy() does not return the component. It looks like the aria label by or the for attribute is not being rendered by material ui. Not sure how to fix this error.

The code is below here for reference too

//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

1 Answers

2
votes

You must add an id to your Field because the label's for attribute expect the ID of the input element it refers to:

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

A working example:

Edit Formiq Yup Material UI and react testing library