Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use test-id in Material UI Textfield

I'm trying to test a material ui text field using react-testing-library.

The issue im facing is that in order to test the material ui textField i would have to use this property method

screen.getByLabelText()

which works, however i do not want to display the label on the UI, i want the label to remain hidden, as im already using Material UI <FormLabel>.

I tried using inputProps and passing data-testId on the element, using the getByTestId() method. but i get this error

TestingLibraryElementError: Found multiple elements by: [data-testid="bio"]

(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).

editForm.test.tsx

import "@testing-library/jest-dom";
import React from "react";
import { createMount } from "@material-ui/core/test-utils";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import EditProfileForm from "./editForm";
import { render as testRender, fireEvent, screen, getByText } from "@testing-library/react";
const props = {
    handleBio: jest.fn(),
};
describe("<EditProfileForm/>", () => {
    let wrapper;
    let mount;
    beforeEach(() => {
        mount = createMount();
        wrapper = mount(<EditProfileForm {...props} />);
    });

    it("should render <EditProfileForm/>", () => {
        expect(wrapper).toHaveLength(1);
    });

    it("calls handleBio on bio TextField change", () => {
        const input = screen.getByLabelText("bio");

        fireEvent.change(input, { target: { value: "new value" } });

        expect(props.handleBio).toHaveBeenCalledTimes(1);
    });
});

editForm.tsx

import Button from "@material-ui/core/Button";
import FormGroup from "@material-ui/core/FormGroup";
import FormLabel from "@material-ui/core/FormLabel";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import React from "react";
const EditProfileForm = (props: any) => (
    <form onSubmit={props.onSubmit}>
        <Typography variant="h5">Edit Profile</Typography>
        <FormGroup style={{ padding: "30px 0px" }}>
            <FormLabel style={{ display: "block" }}>Bio</FormLabel>
            <TextField
                id="outlined-name"
                style={{
                    width: "100%",
                }}
                name="bio"
                label="bio"
                multiline={true}
                rows="3"
                defaultValue={props.bio}
                onChange={props.handleBio}
                margin="normal"
                variant="outlined"
            />

        </FormGroup>
        <Button className="subBtn" variant="outlined" color="primary" type="submit">
            Submit
        </Button>
    </form>
);

export default EditProfileForm;
like image 673
BARNOWL Avatar asked May 27 '20 17:05

BARNOWL


1 Answers

I was able to resolve this issue by first moving the test function after beforeEach been called.

so it will now be

import "@testing-library/jest-dom";
import React from "react";
import { createMount } from "@material-ui/core/test-utils";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import EditProfileForm from "./editForm";
import { render as testRender, fireEvent, screen, getByText } from "@testing-library/react";
const props = {
    handleChange: jest.fn(),
    onSubmit: jest.fn(),
    bio: "test",
    gravatar: "https://i.pravatar.cc/150?img=3",
    handleBio: jest.fn(),
    handleGravatar: jest.fn(),
};
describe("<EditProfileForm/>", () => {
    let wrapper;
    let mount;
    beforeEach(() => {
        mount = createMount();
        wrapper = mount(<EditProfileForm {...props} />);
    });
    // must be called first
    it("calls handleBio on bio TextField change", () => {
        const input = screen.getByTestId("bio");

        fireEvent.change(input, { target: { value: "new value" } });

        expect(props.handleBio).toHaveBeenCalledTimes(1);
    });

    it("should render <EditProfileForm/>", () => {
        expect(wrapper).toHaveLength(1);
    });

    it("should check header title ", () => {
        expect(wrapper.find(Typography).at(0)).toHaveLength(1);
        expect(
            wrapper
                .find(Typography)
                .at(0)
                .text(),
        ).toContain("Edit Profile");
    });

    it("should test bio prop", () => {
        expect(wrapper.props().bio).toContain("test");
    });

    it("should test gravtar prop", () => {
        const link = "https://i.pravatar.cc/150?img=3";
        expect(wrapper.props().gravatar).toContain(link);
    });

    it("should test handleChange props", () => {
        const title = "Test";
        expect(
            wrapper.props().handleChange({
                target: {
                    value: title,
                },
            }),
        );
        expect(props.handleChange).toHaveBeenCalled();
    });

    it("should test onSubmit prop", () => {
        // console.log(wrapper.find(TextField).debug());
        const submit = jest.fn();
        wrapper.simulate("submit", { submit });
        expect(props.onSubmit).toBeCalled();
    });

    it("should test button click", () => {
        const button = wrapper.find(Button);
        button.simulate("click");
        expect(props.onSubmit).toBeCalled();
    });
});

And then passing data-testid as an input prop on text field like this

<TextField
    id="outlined-name"
    className="bio-test"
    style={{
        width: "100%",
    }}
    name="bio"
    inputProps={{
        "data-testid": "bio",
    }}
    multiline={true}
    rows="3"
    defaultValue={props.bio}
    onChange={props.handleBio}
    margin="normal"
    variant="outlined"
/>
like image 147
BARNOWL Avatar answered Sep 20 '22 14:09

BARNOWL