(expect: ExpectStatic)
| 47 | } |
| 48 | |
| 49 | export function createExpectPoll(expect: ExpectStatic): ExpectStatic['poll'] { |
| 50 | return function poll(fn, options = {}) { |
| 51 | const state = getWorkerState() |
| 52 | const defaults = state.config.expect?.poll ?? {} |
| 53 | const { |
| 54 | interval = defaults.interval ?? 50, |
| 55 | timeout = defaults.timeout ?? 1000, |
| 56 | message, |
| 57 | } = options |
| 58 | // @ts-expect-error private poll access |
| 59 | const assertion = expect(null, message).withContext({ |
| 60 | poll: true, |
| 61 | }) as Assertion |
| 62 | fn = fn.bind(assertion) |
| 63 | // injected so that domain snapshot can take over poll implementation. |
| 64 | chai.util.flag(assertion, '_poll.fn', fn) |
| 65 | chai.util.flag(assertion, '_poll.timeout', timeout) |
| 66 | chai.util.flag(assertion, '_poll.interval', interval) |
| 67 | const test = chai.util.flag(assertion, 'vitest-test') as Test | undefined |
| 68 | if (!test) { |
| 69 | throw new Error('expect.poll() must be called inside a test') |
| 70 | } |
| 71 | const proxy: any = new Proxy(assertion, { |
| 72 | get(target, key, receiver) { |
| 73 | const assertionFunction = Reflect.get(target, key, receiver) |
| 74 | |
| 75 | if (typeof assertionFunction !== 'function') { |
| 76 | return assertionFunction instanceof chai.Assertion ? proxy : assertionFunction |
| 77 | } |
| 78 | |
| 79 | if (key === 'assert') { |
| 80 | return assertionFunction |
| 81 | } |
| 82 | |
| 83 | if (typeof key === 'string' && unsupported.includes(key)) { |
| 84 | throw new SyntaxError( |
| 85 | `expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`, |
| 86 | ) |
| 87 | } |
| 88 | |
| 89 | // Core poll stack-trace trick: |
| 90 | // 1. capture STACK_TRACE_ERROR here before entering the async poll loop |
| 91 | // 2. when the matcher eventually fails, rethrow via throwWithCause() |
| 92 | // so the final error keeps this earlier stack |
| 93 | // |
| 94 | // For example, when user writes: |
| 95 | // await expect.poll(...).toBeSomething() |
| 96 | // STACK_TRACE_ERROR.stack would look like |
| 97 | // at ...(more internal stacks)... |
| 98 | // at __VITEST_POLL_CHAIN__ .../packages/vitest/dist/... |
| 99 | // at .../my-file.test.ts:12:3 (this points to `toBeSomething()` callsite in user test file) |
| 100 | // Vitest later filters out internal stacks from `vitest/dist`, so the reported errors correctly |
| 101 | // points to the user callsite for poll assertion errors. |
| 102 | // |
| 103 | // Inline snapshots piggyback on the same idea. We pass |
| 104 | // STACK_TRACE_ERROR through `chai.util.flag(assertion, 'error', ...)`. |
| 105 | // Inline snapshot assertion access the same error stack for |
| 106 | // extracting inline snapshot location to validate and update new snapshots. |
no test coverage detected