-
Notifications
You must be signed in to change notification settings - Fork 1.1k
added waitForExpect #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
cef06a8
e53d137
0a6bfaa
dc7e692
1f15dbc
91b241a
0c046ab
94faf4b
32bbae3
f4888bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ | |
[![downloads][downloads-badge]][npmtrends] | ||
[![MIT License][license-badge]][license] | ||
|
||
[](#contributors) | ||
[](#contributors) | ||
[![PRs Welcome][prs-badge]][prs] | ||
[![Code of Conduct][coc-badge]][coc] | ||
|
||
|
@@ -80,6 +80,9 @@ facilitate testing implementation details). Read more about this in | |
* [`flushPromises`](#flushpromises) | ||
* [`render`](#render) | ||
* [Custom Jest Matchers](#custom-jest-matchers) | ||
* [`toBeInTheDOM`](#tobeinthedom) | ||
* [`toHaveTextContent`](#tohavetextcontent) | ||
* [Other](#other) | ||
* [`TextMatch`](#textmatch) | ||
* [`query` APIs](#query-apis) | ||
* [Examples](#examples) | ||
|
@@ -289,6 +292,14 @@ expect(getByTestId('count-value')).not.toHaveTextContent('21') | |
// ... | ||
``` | ||
|
||
## Other | ||
|
||
#### `waitForExpect(expectation: () => void, timeout?: number, interval?: number) => Promise<{}>;` | ||
|
||
When in need to wait for non-deterministic periods of time you can use waitForExpect, | ||
to wait for your expectations to pass. Take a look at [`Is there a different way to wait for things to happen?`](#waitForExcept) part of the FAQ, | ||
or the function documentation here: [`wait-for-expect`](https://github.com/TheBrainFamily/wait-for-expect) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we add a very simple (incomplete) example of how to use the function? We can keep the FAQ too, but a simple example will help people know what this does: // ...
await waitForExpect(() => expect(queryByLabelText('username')).not.toBeNull())
getByLabelText('username').value = 'chucknorris'
// ... |
||
|
||
## `TextMatch` | ||
|
||
Several APIs accept a `TextMatch` which can be a `string`, `regex` or a | ||
|
@@ -593,6 +604,35 @@ for promises that are not already resolved by the time you attempt to flush them | |
|
||
</details> | ||
|
||
<details> | ||
|
||
<summary><a name="waitForExcept"></a>Is there a different way to wait for things to happen? For example for end to end or contract tests?</summary> | ||
Definitely! There is an abstraction called `waitForExpect` that will keep | ||
calling your expectations until a timeout or the expectation passes - whatever happens first. | ||
|
||
Please take a look at this example (taken from [`here`](https://github.com/kentcdodds/react-testing-library/blob/master/src/__tests__/end-to-end.js)): | ||
|
||
```javascript | ||
import {render, waitForExpect} from 'react-testing-library' | ||
test('it waits for the data to be loaded', async () => { | ||
const {queryByText, queryByTestId} = render(<ComponentWithLoader />) | ||
|
||
// Initially the loader shows | ||
expect(queryByText('Loading...')).toBeTruthy() | ||
|
||
// This will pass when the state of the component changes once the data is available | ||
// the loader will disappear, and the data will be shown | ||
await waitForExpect(() => { | ||
expect(queryByText('Loading...')).toBeNull() | ||
expect(queryByTestId('message').textContent).toMatch(/Hello World/) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to my comment in the test, let's update this so only the necessary assertions are inside the callback 👍 |
||
}) | ||
``` | ||
|
||
For consistency and making your tests easier to understand, you can use it instead of flushPromises. | ||
|
||
</details> | ||
|
||
## Other Solutions | ||
|
||
In preparing this project, | ||
|
@@ -634,7 +674,7 @@ Thanks goes to these people ([emoji key][emojis]): | |
<!-- prettier-ignore --> | ||
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;"/><br /><sub><b>Justin Hall</b></sub>](https://github.com/wKovacs64)<br />[📦](#platform-wKovacs64 "Packaging/porting to new platform") | | ||
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | | ||
| [<img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;"/><br /><sub><b>Anto Aravinth</b></sub>](https://github.com/antoaravinth)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Tests") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/3462296?v=4" width="100px;"/><br /><sub><b>Jonah Moses</b></sub>](https://github.com/JonahMoses)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=JonahMoses "Documentation") | | ||
| [<img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;"/><br /><sub><b>Anto Aravinth</b></sub>](https://github.com/antoaravinth)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Tests") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/3462296?v=4" width="100px;"/><br /><sub><b>Jonah Moses</b></sub>](https://github.com/JonahMoses)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=JonahMoses "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/4002543?v=4" width="100px;"/><br /><sub><b>Łukasz Gandecki</b></sub>](http://team.thebrain.pro)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Tests") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Documentation") | | ||
|
||
<!-- ALL-CONTRIBUTORS-LIST:END --> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,9 @@ | |
"keywords": [], | ||
"author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)", | ||
"license": "MIT", | ||
"dependencies": {}, | ||
"dependencies": { | ||
"wait-for-expect": "0.4.0" | ||
}, | ||
"devDependencies": { | ||
"@types/react-dom": "^16.0.4", | ||
"axios": "^0.18.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react' | ||
import {render, waitForExpect} from '../' | ||
|
||
const fetchAMessage = () => | ||
new Promise(resolve => { | ||
// we are using random timeout here to simulate a real-time example | ||
// of an async operation calling a callback at a non-deterministic time | ||
const randomTimeout = Math.floor(Math.random() * 100) | ||
setTimeout(() => { | ||
resolve({returnedMessage: 'Hello World'}) | ||
}, randomTimeout) | ||
}) | ||
|
||
class ComponentWithLoader extends React.Component { | ||
state = {loading: true} | ||
async componentDidMount() { | ||
const data = await fetchAMessage() | ||
this.setState({data, loading: false}) // eslint-disable-line | ||
} | ||
render() { | ||
if (this.state.loading) { | ||
return <div>Loading...</div> | ||
} else { | ||
return ( | ||
<div data-testid="message"> | ||
Loaded this message: {this.state.data.returnedMessage}! | ||
</div> | ||
) | ||
} | ||
} | ||
} | ||
|
||
test('it waits for the data to be loaded', async () => { | ||
const {queryByText, queryByTestId} = render(<ComponentWithLoader />) | ||
|
||
expect(queryByText('Loading...')).toBeTruthy() | ||
|
||
await waitForExpect(() => { | ||
expect(queryByText('Loading...')).toBeNull() | ||
expect(queryByTestId('message').textContent).toMatch(/Hello World/) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we're going to discourage nesting assertions, could we move this assertion to after the waitForExpect? This has the added benefit of not being waited for if it actually is broken. Maybe we should call that out actually. |
||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's actually put this right after
flushPromises
and call out a limitation offlushPromises
. Specifically that it only flushes the promises that have been queued up already and not those that will be queued up subsequently (maybe we can provide an example?)