enzymejs / enzyme

JavaScript Testing utilities for React
https://enzymejs.github.io/enzyme/
MIT License
19.96k stars 2.01k forks source link

Simulate failing on after updating react and enzyme version #2056

Open anmoltw opened 5 years ago

anmoltw commented 5 years ago

After updating enzyme version, a lot of tests seem to be failing for no reason. Here's a change history of my packages -

react: 16.4.2 -> 16.8.4 react-dom: 16.4.2 -> 16.8.4 enzyme: 3.3.0 -> 3.9.0 enzyme-adapter-react-16: 1.1.1 -> 1.11.2 react-test-renderer: 16.8.1 - 16.8.2

toggle = () => { this.setState(prevState => { return { visible: !prevState.visible }; }); };

ljharb commented 5 years ago

Please fill out the entire issue template; it's there for a reason.

ljharb commented 5 years ago

Thanks. Can you provide the full code for the component being tested, and the full code of the test?

anmoltw commented 5 years ago

ButtonGroup

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';

export default class ButtonGroup extends PureComponent {
  state = {
    expanded: false
  }

  toggleExpand = () => {
    this.setState(currentState => ({
      expanded: !currentState.expanded
    }));
  }

  render() {
    return (
      this.state.expanded ? this.props.values.map((value, index) => (
        <div className="button" key={value.name + index}>
          {value.name}
        </div>
      ))
        : (
          <button type="button" className="button is-icon" onClick={this.toggleExpand}>
            <span className="icon"><i className="fas fas fa-ellipsis-h" /></span>
          </button>
        )
    );
  }
}
import React from 'react';
import { shallow, mount } from 'enzyme';
import ButtonGroup from './ButtonGroup';

describe('<ButtonGroup />', () => {
  describe('render', () => {

  it('should toggle expanded state on click of button', () => {
    const props = {
      values: []
    };
    const component = shallow(<ButtonGroup {...props} />);
    expect(component.state().expanded).toBeFalsy();
    const expandButton = component.find('button');
    expect(expandButton).toHaveLength(1);
    expandButton.simulate('click');
    expect(component.state().expanded).toBeTruthy();
  });
});

Sidebar

import React, { Fragment } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';

export default class Sidebar extends React.Component {

  toggle = () => {
    this.setState(prevState => {
      return { visible: !prevState.visible };
    });
  };

  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      animating: false,
      direction: null,
      setDirection: false
    };
  }

  render() {
    const classes = classNames(this.props.className, 'sidebar', 'overlay', 'very', 'wide');

    return createPortal((
      <div className={classes} id={this.props.id}>
        <div className="sidebar-header">
          <button type="button" className="button is-plain sidebar-closer is-medium" onClick={this.close}>
            <span className="fas fa-lg fa-times" />
          </button>
          {this.props.title
          && typeof this.props.title === 'string'
            ? <h1 id="sidebar-heading" className="sidebar-title title is-1" data-testid="sidebar-title">{this.props.title}</h1>
            : <Fragment>{this.props.title}</Fragment>
          }
        </div>
        <div className="sidebar-wrapper" />
        {this.props.children}
      </div>
    ), document.querySelector('body'));
  }
}
import React from 'react';
import ReactDOM from 'react-dom';
import { shallow } from 'enzyme';
import Sidebar from './Sidebar';

describe('Sidebar component', () => {
  let sidebarComp;

  jest.useFakeTimers();

  beforeAll(() => {
    ReactDOM.createPortal = jest.fn((element) => {
      return element;
    });
  });

  beforeEach(() => {
    sidebarComp = shallow(<Sidebar />);
  });

  afterEach(() => {
    ReactDOM.createPortal.mockClear();
  });

  it('should toggle visible state value on toggle', () => {
    expect(sidebarComp.state().visible).toBeFalsy();
    sidebarComp.instance().toggle();
    sidebarComp.update();
    expect(sidebarComp.state().visible).toBeTruthy();
  });
});
pgangwani commented 5 years ago

@anmoltw : I got it. You have to wrap map(JSX) output with <Fragment> or <> where as I didnt see any issue with SideBar testing

Here you go ==> https://codesandbox.io/s/w6183xxjr8 Refer: Hello.js : Line: 19,25 (wrapping)

I prefer to use props().onClick over simulate (thats Ok for this case) when using shallow mount (which I love too) Please let me know if any other issue after suggested change.

@ljharb Please add explanation/extra details if I missed any.

anmoltw commented 5 years ago

Thanks @pgangwani . That seems to work. However, the Sidebar issue still persists. @ljharb Any thoughts on that ?

ljharb commented 5 years ago

@anmoltw sorry for the delay; can you prepare a new sandbox that highlights the remaining issue?