Material-ui: [Dialog][Enzyme] No way to open dialog and test actions.

Created on 17 Nov 2017  路  7Comments  路  Source: mui-org/material-ui

When testing a component that includes a

, I can successfully simulate a click and verify that the component's state is set to open. However, when I then try to find the defined action buttons, I am unable to do so.

// Code

class CustomDialog extends Component {
  ....
    this.state = {
      open: false,
    };

  handleOpen = () => {
    this.setState({ open: true });
  };

  handleDelete =() => {
    ....
  };

  handleClose = () => {
    ....
  };

  render() {
    const actions = [
      <FlatButton label="Cancel" onClick={this.handleClose} />,
      <FlatButton label="Delete" onClick={this.handleDelete} />,
    ];

    return (
      <span>
        <FlatButton label="Delete" onClick={this.handleOpen} />
        <Dialog
          actions={actions}
          open={this.state.open}
          onRequestClose={this.handleClose}
        >
          Delete? This operation cannot be reversed.
        </Dialog>
      </span>
    );
  }
}

// Tests

      expect(mountedComponent).toHaveState('open', false); <--PASS

      mountedComponent
        .find('FlatButton')
        .simulate('click');

      expect(mountedComponent).toHaveState('open', true); <--PASS

        expect(mountedComponent
          .find('FlatButton')
          .find('[label="Cancel"]')).toBePresent(); <<< FAIL

I haven't done a sandbox because Dialog works fine for me in the browser, it's only when testing that the issues arise.
I have searched the issues of this repository and believe that this is not a duplicate.

| Tech | Version |
|--------------|---------|
| Material-UI | 0.19.4 |
| React | 16.0.0 |
| enzyme | 3.1.0 |

And finally, here is my mountedComponent.debug() output:

<AreaDeleteDialog className="delete" id="Hollywood" handleAreaDelete={[Function]}>
  <span>
    <FlatButton label="Delete" onClick={[Function]} disabled={false} fullWidth={false} labelStyle={{...}} labelPosition="after" onKeyboardFocus={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} onTouchStart={[Function]} primary={false} secondary={false}>
      <EnhancedButton onClick={[Function]} onKeyboardFocus={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} onTouchStart={[Function]} disabled={false} focusRippleColor="#999999" focusRippleOpacity={0.3} style={{...}} touchRippleColor="#999999" touchRippleOpacity={0.3} containerElement="button" onBlur={[Function]} onFocus={[Function]} onKeyDown={[Function]} onKeyUp={[Function]} tabIndex={0} type="button">
        <button onMouseEnter={[Function]} onMouseLeave={[Function]} onTouchStart={[Function]} style={{...}} disabled={false} onBlur={[Function]} onFocus={[Function]} onKeyUp={[Function]} onKeyDown={[Function]} onClick={[Function]} tabIndex={0} type="button">
          <TouchRipple centerRipple={[undefined]} color="#999999" opacity={0.3} abortOnScroll={true}>
            <div onMouseUp={[Function]} onMouseDown={[Function]} onMouseLeave={[Function]} onTouchStart={[Function]} onTouchEnd={[Function]}>
              <FlatButtonLabel label="Delete" style={{...}}>
                <span style={{...}}>
                  Delete
                </span>
              </FlatButtonLabel>
            </div>
          </TouchRipple>
        </button>
      </EnhancedButton>
    </FlatButton>
    <Dialog actions={{...}} open={true} onRequestClose={[Function]} autoDetectWindowHeight={true} autoScrollBodyContent={false} modal={false} repositionOnUpdate={true}>
      <RenderToLayer render={[Function]} open={true} useLayerForClickAway={false} />
    </Dialog>
  </span>
</AreaDeleteDialog>'
duplicate

Most helpful comment

I know its closed, but did anyone find the solution to this?

All 7 comments

This is not an issue with material-ui and is more of a question about using enzyme, which is probably better suited for StackOverflow.

Here are some quick thoughts: If you're shallow rendering the Dialog, you won't be able to find the FlatButtons because they haven't been rendered. Instead, they are nothing more than a value assigned to the actions prop, unless you dive into the Dialog, which should render its children, making them accessible through the shallow wrapper:

wrapper.find(Dialog).dive().find(FlatButton)

Also, you should try using the class definition as the selector rather than its description.

// not this
mountedComponent.find('FlatButton')

// this (of course you'll need to import it into your test)
mountedComponent.find(FlatButton)

@kgregory I think it's an issue with material-ui if the interface of a component isn't suited to testing? What makes you think this is misuse of/a bug with enzyme? (I'm using a mounted component, and searching using the class definition doesn't work).

@adc17 You'll probably need to add id properties to the buttons and find them that way using the DOM. Shallow render/dive may even work. There are other resolutions mentioned on this duplicate issue #6290 and issue #7970 that references it.

@oliviertassinari can correct me if I'm wrong, but I am pretty sure that there will be no changes to the API in v0 as we're pushing for v1.

@kgregory We try to make v0.x as stable as possible. Not changing the API help.

@kgregory adding id properties to the buttons doesn't work鈥攖he buttons show up in my browser (with the ids), but they don't show up for enzyme, even though the dialog's open prop is set to true in the debugger output.

I will try a shallow render plus dive, but if that works and mount doesn't, it seems like buggy behaviour.

If the problem doesn't exist in v1, then fair enough鈥擨 will check when I get the chance.

@kgregory the shallow render diving did not work either.

console.log(wrapper.find(Dialog).dive().find(FlatButton).length);
// prints '0' with two FlatButtons in the actions prop

I know its closed, but did anyone find the solution to this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ryanflorence picture ryanflorence  路  3Comments

ghost picture ghost  路  3Comments

chris-hinds picture chris-hinds  路  3Comments

ericraffin picture ericraffin  路  3Comments

rbozan picture rbozan  路  3Comments