简体   繁体   中英

How to simulate on `onChange` event that updates the state

I'm writing an application in React and I'm unit testing this with Jest and Enzyme.

I have a very simple component that represents an input field, which contains the following code:

// 'Container' component definition.
class Container extends React.Component<containerProps, containerState> {
  static defaultProps = { };
  state = {
    hasValue: false
  };

  constructor(props: containerProps) {
    super(props);

    // Bind all the event handlers for the component.
    (this: any).onChange = this.onChange.bind(this);
  }

  onChange(event: MouseEvent) : void {
    this.setState(
      {
        hasValue: (event.target: window.HTMLInputElement).value !== ''
      }
    );

    // Prevent a default browser event from happening.
    event.preventDefault();
  }

  createComponentProps(): componentProps {
    return {
      cssClass: this.createComponentCssClass()
    };
  }

  // Create the CSS class to pass to the component.
  createComponentCssClass(): string {
    let className = '';

    if (this.state.hasValue) { className = className !== '' ? className + 'value' : 'value'; }
    if (this.props.errorMessage && this.props.errorMessage !== '') {
      className = className !== '' ? className + ' error' : 'error';
    }

    // Return the CSS class to apply to the component.
    return className;
  }

  // Renders the 'Container' component.
  render(): React$Element<any> {
    return (
      <Component {...this.createComponentProps()} />
    );
  }
}

So, it's a fairly simple component. Now, when the contents of the input field are changed, a state change occurs which forces a different CSS class to be applied to the component.

I can confirm that this is working since it's working in the browser as intended.

Now, I'm writing a unit test to verify that the className value is passed to the component using the following code:

it('Passes down the \'cssClass\' property to the \'Input Field\' Component.', () => {
  // Act.
  const wrapper = mount(
    <InputFieldContainer primaryThemeColor="TEAL" accentThemeColor="PINK" useAccentColor={true} />
  );
  wrapper.find('input').simulate('change', { target: { value: 'value' }});
  wrapper.update();

  // Assert.
  expect(wrapper.find(InputFieldComponent).props().cssClass).toEqual('value');
});

Thus, I'm rendering the component, I simulate a change event, and I check the CSS class property of the component, however, it's an empty string. It seems it didn't update regarding the state change (but only in unit tests).

Reading the state in Jest, using console.log(wrapper.state()) gives me a JSON object saying hasValue: true , so the state is updated, but even after calling wrapper.update() , the CSS class does not seem to be passed.

What am I missing here?

Kind regards

This seems to be an issue with Enzyme ( https://github.com/airbnb/enzyme/issues/1153 ).

After updating the wrapper and your component should be in sync.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM