forked from vitest-dev/vitest
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexpect-element.ts
More file actions
61 lines (48 loc) · 2.45 KB
/
expect-element.ts
File metadata and controls
61 lines (48 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import type { ExpectPollOptions, PromisifyDomAssertion } from 'vitest'
import type { Locator } from 'vitest/browser'
import { chai, expect } from 'vitest'
import { getType } from 'vitest/internal/browser'
import { matchers } from './expect'
import { processTimeoutOptions } from './tester-utils'
const kLocator = Symbol.for('$$vitest:locator')
function element<T extends HTMLElement | SVGElement | null | Locator>(elementOrLocator: T, options?: ExpectPollOptions): PromisifyDomAssertion<HTMLElement | SVGElement | null> {
if (elementOrLocator != null && !(elementOrLocator instanceof HTMLElement) && !(elementOrLocator instanceof SVGElement) && !(kLocator in elementOrLocator)) {
throw new Error(`Invalid element or locator: ${elementOrLocator}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(elementOrLocator)}`)
}
const expectElement = expect.poll<HTMLElement | SVGElement | null>(function element(this: object) {
if (elementOrLocator instanceof Element || elementOrLocator == null) {
return elementOrLocator
}
const isNot = chai.util.flag(this, 'negate') as boolean
const name = chai.util.flag(this, '_name') as string
// special case for `toBeInTheDocument` matcher
if (isNot && name === 'toBeInTheDocument') {
return elementOrLocator.query()
}
if (name === 'toHaveLength') {
// we know that `toHaveLength` requires multiple elements,
// but types generally expect a single one
return elementOrLocator.elements() as unknown as HTMLElement
}
if (name === 'toMatchScreenshot' && !chai.util.flag(this, '_poll.assert_once')) {
// `toMatchScreenshot` should only run once after the element resolves
chai.util.flag(this, '_poll.assert_once', true)
}
// element selector uses prettyDOM under the hood, which is an expensive call
// that should not be called on each failed locator attempt to avoid memory leak:
// https://github.com/vitest-dev/vitest/issues/7139
const isLastPollAttempt = chai.util.flag(this, '_isLastPollAttempt')
if (isLastPollAttempt) {
return elementOrLocator.element()
}
const result = elementOrLocator.query()
if (!result) {
throw new Error(`Cannot find element with locator: ${JSON.stringify(elementOrLocator)}`)
}
return result
}, processTimeoutOptions(options))
chai.util.flag(expectElement, '_poll.element', true)
return expectElement
}
expect.extend(matchers)
expect.element = element