1

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();
  });
});

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

Example doesn't work, button is disabled after filling the form. Just tried to run the tests in codesandbox and they fail.
0

Few things. The use of { getByLabelText, getByTestId, debug } is not advised by the creator of the library. You should use screen.getByLabelText().

If there is a change, it's possible that it doesn't wait for the new render, so it would be better to await it or wrap the expect in a waitFor method.

Also, expect(button.disabled).not.toBeDefined() should not be correct. I think you're just checking if the button is disabled or not, right? So you can use expect(button).toBeDisabled() or not.toBeDisabled()

At least to test it I think you should take off the for loop and check it normally. You can use screen.debug(component) to have the HTML shown after some action.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.