(target, key, receiver)
| 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. |
| 107 | return function __VITEST_POLL_CHAIN__(this: any, ...args: any[]) { |
| 108 | const STACK_TRACE_ERROR = new Error('STACK_TRACE_ERROR') |
| 109 | const promise = async () => { |
| 110 | chai.util.flag(assertion, '_name', key) |
| 111 | chai.util.flag(assertion, 'error', STACK_TRACE_ERROR) |
| 112 | |
| 113 | const onSettled = chai.util.flag(assertion, '_poll.onSettled') as Function | undefined |
| 114 | |
| 115 | // We use `matcher.__vitest_poll_takeover__` flag |
| 116 | // to let domain snapshot matchers take over polling logic. |
| 117 | // this is not public API yet. |
| 118 | // Need to use `getOwnPropertyDescriptor` since otherwise chai proxy breaks. |
| 119 | const pollTakeover = Object.getOwnPropertyDescriptor( |
| 120 | assertionFunction, |
| 121 | '__vitest_poll_takeover__', |
| 122 | )?.value |
| 123 | if (pollTakeover) { |
| 124 | try { |
| 125 | const output = await assertionFunction.call(assertion, ...args) |
| 126 | await onSettled?.({ assertion, status: 'pass' }) |
| 127 | return output |
| 128 | } |
| 129 | catch (err) { |
nothing calls this directly
no test coverage detected