{"action":"created","issue":{"url":"https://api.github.com/repos/airbnb/enzyme/issues/1581","repository_url":"https://api.github.com/repos/airbnb/enzyme","labels_url":"https://api.github.com/repos/airbnb/enzyme/issues/1581/labels{/name}","comments_url":"https://api.github.com/repos/airbnb/enzyme/issues/1581/comments","events_url":"https://api.github.com/repos/airbnb/enzyme/issues/1581/events","html_url":"https://github.com/airbnb/enzyme/issues/1581","id":305691495,"number":1581,"title":"How to test component with async componentDidMount ","user":{"login":"spplante","id":8792854,"avatar_url":"https://avatars1.githubusercontent.com/u/8792854?v=4","gravatar_id":"","url":"https://api.github.com/users/spplante","html_url":"https://github.com/spplante","followers_url":"https://api.github.com/users/spplante/followers","following_url":"https://api.github.com/users/spplante/following{/other_user}","gists_url":"https://api.github.com/users/spplante/gists{/gist_id}","starred_url":"https://api.github.com/users/spplante/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spplante/subscriptions","organizations_url":"https://api.github.com/users/spplante/orgs","repos_url":"https://api.github.com/users/spplante/repos","events_url":"https://api.github.com/users/spplante/events{/privacy}","received_events_url":"https://api.github.com/users/spplante/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":17,"created_at":"2018-03-15T19:34:58Z","updated_at":"2018-05-07T11:48:53Z","closed_at":"2018-03-17T18:57:10Z","author_association":"NONE","body":"### Current behavior\r\n\r\nI have a really typical dummy component which :\r\n\r\n- Initially renders a progress icon\r\n- Once the **componentDidMount**, executes an **async** callback from its properties to get it's data\r\n- Once the data came back from the callback's promise, updates the state\r\n- Re-renders with the data and without the progress\r\n\r\nTypically, these are the relevant parts of the dummy component :\r\n```typescript\r\nconstructor(props: IMyComponentProperties, state: IMyComponentState) {\r\n    super(props);\r\n    this.state = { loading: true, data: null, error: null };\r\n}\r\n```\r\n\r\n```typescript\r\npublic componentDidMount() {\r\n    this.props.loadData().then((result) => {\r\n        this.setState({ loading: false, data: result, error: null });\r\n    }) \r\n    .catch((error: any) => {\r\n        this.setState({ loading: false, data: null, error: error });\r\n    });\r\n}\r\n```\r\n\r\n```typescript\r\npublic render() {\r\n    const loading = this.state.loading ? <Spinner label='Loading...' /> : <div />;\r\n    const error = this.state.error != null ? <div>There was an error...</div> : <div />;\r\n\r\n    return (\r\n        <div>\r\n            {loading}\r\n\r\n\t    { !this.state.loading && !this.state.error && \t\t\t\t\r\n\t         // Rendering this.state.data here...\r\n            }\r\n\r\n            {error}\r\n        </div>\r\n    );\r\n}\r\n```\r\n\r\nLooking at the code above, the following test is executing just fine :\r\n\r\n```typescript\r\nit('Should render a progress component while loading data', () => {\r\n    shallowWrapper = shallow(<MyComponent loadData={mockedCallback} />);\r\n    const containsSpinner = shallowWrapper.containsMatchingElement(<Spinner />);\r\n    expect(containsSpinner).to.be.true;\r\n});\r\n```\r\n\r\nIn fact, the shallow **does** render with a spinner because the promise within **componentDidMount** didn't resolve immediately, which is totally fine for this test.\r\n\r\nNow If I want to test the opposite, which is to make sure the Spinner does **NOT** render after the data has been loaded, what would be the best way to do this? I guess I could listen to the **componentDidUpdate** and validate once it has been called, but how would I do this? Here is an awefull bit of code that currently works just to illustrate the problem :\r\n\r\n```typescript\r\nit('Should NOT render a progress component when loading data is done', () => {\r\n    shallowWrapper = shallow(<MyComponent loadData={mockedCallback} />);\r\n\r\n    setTimeout(() => {\r\n        shallowWrapper.update();\r\n        let containsSpinner = shallowWrapper.containsMatchingElement(<Spinner />);\r\n        expect(containsSpinner).to.be.false;\r\n    }, 2000);\r\n});\r\n```\r\n\r\nThe test above works correctly, I just wait 2 seconds in order to wait for the promise to be completed, then I update the shallow and confirm that the progress isn't there anymore, but I do hope there is a cleaner way to do this as this is quite awful.\r\n\r\nThe pattern used by this dummy component really is typical, but somehow I just can't find any relevant documentation on how to test this kind of scenario :|\r\n\r\nWould appreciate if someone could help 👍 \r\n\r\nThanks!\r\n\r\n\r\n#### API\r\n\r\n- [x] shallow\r\n- [ ] mount\r\n- [ ] render\r\n\r\n#### Version\r\n\r\n| library         | version\r\n| ---------------- | -------\r\n| Enzyme           | 3.3.0\r\n| React            |  15\r\n\r\n#### Adapter\r\n\r\n- [ ] enzyme-adapter-react-16\r\n- [x] enzyme-adapter-react-15\r\n- [ ] enzyme-adapter-react-15.4\r\n- [ ] enzyme-adapter-react-14\r\n- [ ] enzyme-adapter-react-13\r\n- [ ] enzyme-adapter-react-helper\r\n- [ ] others ( ) \r\n"},"comment":{"url":"https://api.github.com/repos/airbnb/enzyme/issues/comments/387040435","html_url":"https://github.com/airbnb/enzyme/issues/1581#issuecomment-387040435","issue_url":"https://api.github.com/repos/airbnb/enzyme/issues/1581","id":387040435,"user":{"login":"spplante","id":8792854,"avatar_url":"https://avatars1.githubusercontent.com/u/8792854?v=4","gravatar_id":"","url":"https://api.github.com/users/spplante","html_url":"https://github.com/spplante","followers_url":"https://api.github.com/users/spplante/followers","following_url":"https://api.github.com/users/spplante/following{/other_user}","gists_url":"https://api.github.com/users/spplante/gists{/gist_id}","starred_url":"https://api.github.com/users/spplante/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spplante/subscriptions","organizations_url":"https://api.github.com/users/spplante/orgs","repos_url":"https://api.github.com/users/spplante/repos","events_url":"https://api.github.com/users/spplante/events{/privacy}","received_events_url":"https://api.github.com/users/spplante/received_events","type":"User","site_admin":false},"created_at":"2018-05-07T11:48:53Z","updated_at":"2018-05-07T11:48:53Z","author_association":"NONE","body":"Hard to tell honestly I would expect both of the codes to work"}}
{"actor":{"display_login":"spplante"}}