Ad

How Do I Unit Test Material-ui Textfield Using Enzyme?

- 1 answer

I am still learning ReactJS with Enzyme and Material-ui.

I have a component with Material-ui's TextField and I would like to unit test the following situation.

  1. When user enters a string '123' on TextField on screen, the TextField should set 'error' to 'true' and display message 'Wrong Name format.'

Component

import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";

export const NameTextField = props => {
  const { onStateChange } = props;
  const [state, setState] = useState({
    errors: [],
    onChange: false,
    pristine: false,
    touched: false,
    inProgress: false,
    value: {
      name: ""
    }
  });
  const handleOnBlur = async event => {
    const inputStringLC = String(event.target.value).toLowerCase();

    // First verify the email is in good format
    if (inputStringLC !== "123") {
      // If true, verify username is available
      const updatedState = {
        ...state,
        touched: true,
        pristine: true,
        value: {
          name: inputStringLC
        },
        inProgress: false,
        errors: []
      };
      setState(updatedState);
      onStateChange(updatedState);
    } else {
      const updatedState = {
        ...state,
        touched: true,
        pristine: false,
        value: {
          name: inputStringLC
        },
        errors: ["Wrong Name format."]
      };
      setState(updatedState);
      onStateChange(updatedState);
    }
  };

  return (
    <Grid container spacing={1}>
      <Grid item xs={12}>
        <TextField
          variant="outlined"
          required
          fullWidth
          id="name"
          label="Name"
          error={state.errors.length > 0}
          helperText={state.errors.length > 0 ? state.errors[0] : null}
          name="name"
          autoComplete="name"
          margin="dense"
          onBlur={handleOnBlur}
        />
      </Grid>
    </Grid>
  );
};

export default NameTextField;

Unit Test

import React from 'react';
import { configure, shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import NameTextField from './NameTextField';
import TextField from '@material-ui/core/TextField';
import { createShallow } from '@material-ui/core/test-utils';


configure({adapter: new Adapter()});

describe('<NameTextField />', ()=> {
  let shallow;

  beforeAll(() => {
    shallow = createShallow();
  });
  let wrapper;
  beforeEach(()=>{
    wrapper =  shallow(<NameTextField />);
  });

  it('should render one <TextField /> element.', ()=>{
    expect(wrapper.find(TextField)).toHaveLength(1);
  });


  it('should show error when entered', ()=>{
    wrapper.find('#name').simulate('change', {target: {value: '123'}});
    expect(wrapper.find("#name").props().error).toBe(
        true);
    expect(wrapper.find("#name").props().helperText).toBe(
        'Wrong Name format.');
  });


});

I get the following error. Error: expect(received).toBe(expected) // Object.is equality

Expected: true Received: false

Am I doing something wrong here?

Ad

Answer

I solved this by this. Posting solution for those in same situation.

  1. I tried using mount but it gets very complicated as material-ui has a lot of nested style components init. So I used shallow instead.
import React from 'react';
import {configure} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import NameTextField from './NameTextField';
import TextField from '@material-ui/core/TextField';
import {createShallow} from '@material-ui/core/test-utils';
import {act} from 'react-dom/test-utils';

configure({adapter: new Adapter()});

describe('<NameTextField />', () => {
  let shallow;

  beforeAll(() => {
    shallow = createShallow();
  });
  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<NameTextField onStateChange={handleStateChange}/>);
  });

  const handleStateChange = updatedState => {
  };

  it('should show no error when first entered', () => {
    expect(wrapper.find(TextField).at(0).props().error).toBe(
        false);
    expect(wrapper.find(TextField).at(0).props().helperText).toBe(
        null);
  });

  it('should show error when nothing entered', () => {
    act(() => {
      wrapper.find(TextField).at(0).simulate('blur', {target: {value: '123'}});
    });
    wrapper.update();
    expect(wrapper.find(TextField).at(0).props().error).toBe(
        true);
    expect(wrapper.find(TextField).at(0).props().helperText).toBe(
        "Wrong Name format.");
  });

  it('should show no error when correctly entered', () => {
    act(() => {
      wrapper.find(TextField).at(0).simulate('blur', {target: {value: 'James'}});
    });
    wrapper.update();
    expect(wrapper.find(TextField).at(0).props().error).toBe(
        false);
    expect(wrapper.find(TextField).at(0).props().helperText).toBe(
        null);
  });

});

Hope this helps. Thanks for all who had helped me in this.

Ad
source: stackoverflow.com
Ad