|
1 | 1 | # Retryable assertions |
2 | 2 |
|
3 | | -- Use `expect.poll` to retry any assertion. |
4 | | -- Use `expect.element()` in the Browser Mode for built-in polling + element-based assertions. |
5 | | - |
6 | | ---- |
7 | | - |
8 | 3 | I will start from removing the `vi.waitFor()` block I have in the test: |
9 | 4 |
|
10 | 5 | ```ts filename=src/client.test.ts remove=8-10 |
@@ -47,25 +42,49 @@ Similar to `vi.waitFor()`, the `expect.poll()` call _returns a Promise_ that you |
47 | 42 |
|
48 | 43 | You might be wondering: How is this different from `vi.waitFor()`? |
49 | 44 |
|
50 | | -... |
| 45 | +On the surface, two approaches simply differ syntactically, but there's more to it. `vi.waitFor()` isn't really meant to be used with assertions. The way assertion errors are nested in the callback make it somewhat harder for Vitest to process them. `expect.poll()`, on the other hand, is tailored exclusively for eventual assertions. |
| 46 | + |
| 47 | +This makes the distinction between the two APIs a bit more clear. |
51 | 48 |
|
52 | | -- [ ] Explain the difference between `vi.waitFor()` and `expect.poll()` and when you'd want to use each. |
| 49 | +| `vi.waitFor()` | `expect.poll()` | |
| 50 | +| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------- | |
| 51 | +| Use to wait for a side effect or a state transition not directly related to the expectation you're testing. | Use to describe an eventual expectation. | |
| 52 | + |
| 53 | +<callout-success>In Vitest Browser Mode, `expect.element()` is built around `expect.poll()` so you don't need to poll for values manually. When testing your components, prefer `expect.element()` instead.</callout-success> |
| 54 | + |
| 55 | +Here's how you would apply each API: |
53 | 56 |
|
54 | 57 | ```ts |
55 | | -await vi.waitFor(() => { |
56 | | - expect(fn).toHaveBeenCalled() |
| 58 | +// Let's say this `action` is your starting interaction with the system. |
| 59 | +// (i.e. it begins the state transition) |
| 60 | +await action() |
| 61 | + |
| 62 | +// Wait for certain side effects to complete. |
| 63 | +// These are not related to what you're testing but are rather |
| 64 | +// required before you proceed with your test. |
| 65 | +await vi.waitFor(async () => { |
| 66 | + // You can still use `expect()` here as a shorthand for resolving |
| 67 | + // when a condition is met and rejecting when it's not. You can also |
| 68 | + // use things like `invariant` or throwing errors manually. |
| 69 | + await sideEffect() |
57 | 70 | }) |
58 | 71 |
|
59 | | -// is the same as this: |
| 72 | +// Now that the system is in the correct next state, |
| 73 | +// continue interacting with it as the user would. |
| 74 | +await anotherAction() |
60 | 75 |
|
61 | | -await expect.poll(() => fn).toHaveBeenCalled() |
| 76 | +// Finally, write assertions that reflect your expectations. |
| 77 | +// In this case, an eventual expectation for the `state` to |
| 78 | +// become `expected`. |
| 79 | +await expect.poll(state).toBe(expected) |
62 | 80 | ``` |
63 | 81 |
|
64 | 82 | ## Limitations of `expect.poll()` |
65 | 83 |
|
66 | | -- `expect.poll()` doesn't work with all matchers (no support for snapshot matchers, e.g.); |
67 | | -- `expect.poll()` always awaits the given promise, which means there's no `.rejects` or `.resolves`; |
68 | | -- `expect.poll()` won't work with `.toThrow()` so don't use it for negative assertions. |
| 84 | +That being said, `expect.poll()` comes with a few limitations that you have to keep in mind when using it. |
| 85 | + |
| 86 | +1. It doesn't work with all matchers (e.g. doesn't support snapshot matchers); |
| 87 | +1. The Promise it returns _can only resolve_, which means there's no `.rejects.` or `.resolves.` chaining after `expect.poll()`. For example, you cannot use it with `.toThrow(error)` for negative assertions. |
69 | 88 |
|
70 | 89 | ## Related materials |
71 | 90 |
|
|
0 commit comments