Skip to content

Commit 9f14972

Browse files
authored
Make type Element[] work with toBeElementsArrayOfSize (#1980)
* fix: tsc error with elements matcher and type `WebdriverIO.Element[]` `WebdriverIO.Element[]` needs to also be a `ElementArrayLike` * chore: add checks:all command to eases checks everything * fix: have `toBeElementsArrayOfSize`work with type `WebdriverIO.Element[]`
1 parent 5a7c88a commit 9f14972

File tree

7 files changed

+278
-133
lines changed

7 files changed

+278
-133
lines changed

src/matchers/elements/toBeElementsArrayOfSize.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { waitUntil, enhanceError, compareNumbers, numberError } from '../../utils.js'
22
import { refetchElements } from '../../util/refetchElements.js'
33
import { DEFAULT_OPTIONS } from '../../constants.js'
4-
import type { WdioElementsMaybePromise } from '../../types.js'
4+
import type { WdioElements, WdioElementsMaybePromise } from '../../types.js'
55

66
export async function toBeElementsArrayOfSize(
77
received: WdioElementsMaybePromise,
@@ -17,17 +17,16 @@ export async function toBeElementsArrayOfSize(
1717
options,
1818
})
1919

20-
// type check
2120
let numberOptions: ExpectWebdriverIO.NumberOptions
2221
if (typeof expectedValue === 'number') {
23-
numberOptions = { eq: expectedValue } as ExpectWebdriverIO.NumberOptions
22+
numberOptions = { eq: expectedValue } satisfies ExpectWebdriverIO.NumberOptions
2423
} else if (!expectedValue || (typeof expectedValue.eq !== 'number' && typeof expectedValue.gte !== 'number' && typeof expectedValue.lte !== 'number')) {
2524
throw new Error('Invalid params passed to toBeElementsArrayOfSize.')
2625
} else {
2726
numberOptions = expectedValue
2827
}
2928

30-
let elements = await received as WebdriverIO.ElementArray
29+
let elements = await received as WdioElements
3130
const originalLength = elements.length
3231
const pass = await waitUntil(async () => {
3332
/**

src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ export type WdioElementMaybePromise =
55
WebdriverIO.Element |
66
ChainablePromiseElement
77

8+
export type WdioElements = WebdriverIO.ElementArray | WebdriverIO.Element[]
9+
810
export type WdioElementsMaybePromise =
9-
WebdriverIO.ElementArray |
11+
WdioElements |
1012
ChainablePromiseArray
1113

1214
export type RawMatcherFn<Context extends MatcherContext = MatcherContext> = {
1315
(this: Context, actual: unknown, ...expected: unknown[]): ExpectationResult;
1416
}
1517

16-
export type WdioMatchersObject = Map<string, RawMatcherFn>
18+
export type WdioMatchersObject = Map<string, RawMatcherFn>

src/util/elementsUtil.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ export const wrapExpectedWithArray = (el: WebdriverIO.Element | WebdriverIO.Elem
1111
}
1212
return expected
1313
}
14+
15+
export const isElementArray = (obj: unknown): obj is WebdriverIO.ElementArray => {
16+
return obj !== null && typeof obj === 'object' && 'selector' in obj && 'foundWith' in obj && 'parent' in obj
17+
}

src/util/formatMessage.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { printDiffOrStringify, printExpected, printReceived } from 'jest-matcher-utils'
22
import { equals } from '../jasmineUtils.js'
3+
import type { WdioElements } from '../types.js'
4+
import { isElementArray } from './elementsUtil.js'
35

46
const EXPECTED_LABEL = 'Expected'
57
const RECEIVED_LABEL = 'Received'
@@ -15,15 +17,15 @@ export const getSelector = (el: WebdriverIO.Element | WebdriverIO.ElementArray)
1517
return result
1618
}
1719

18-
export const getSelectors = (el: WebdriverIO.Element | WebdriverIO.ElementArray) => {
20+
export const getSelectors = (el: WebdriverIO.Element | WdioElements) => {
1921
const selectors = []
20-
let parent: WebdriverIO.Element | WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | undefined
22+
let parent: WebdriverIO.ElementArray['parent'] | undefined
2123

22-
if (Array.isArray(el)) {
23-
selectors.push(`${(el as WebdriverIO.ElementArray).foundWith}(\`${getSelector(el)}\`)`)
24+
if (isElementArray(el)) {
25+
selectors.push(`${(el).foundWith}(\`${getSelector(el)}\`)`)
2426
parent = el.parent
25-
} else {
26-
parent = el as WebdriverIO.Element
27+
} else if (!Array.isArray(el)) {
28+
parent = el
2729
}
2830

2931
while (parent && 'selector' in parent) {
@@ -42,7 +44,7 @@ export const not = (isNot: boolean): string => {
4244
}
4345

4446
export const enhanceError = (
45-
subject: string | WebdriverIO.Element | WebdriverIO.ElementArray,
47+
subject: string | WebdriverIO.Element | WdioElements,
4648
expected: unknown,
4749
actual: unknown,
4850
context: { isNot: boolean },

src/util/refetchElements.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { DEFAULT_OPTIONS } from '../constants.js'
2+
import type { WdioElements } from '../types.js'
3+
import { isElementArray } from './elementsUtil.js'
24

35
/**
4-
* refetch elements array
5-
* @param elements WebdriverIO.ElementArray
6+
* Refetch elements array or return when elements is not of type WebdriverIO.ElementArray
7+
* @param elements WebdriverIO.ElementArray | WebdriverIO.Element[]
68
*/
79
export const refetchElements = async (
8-
elements: WebdriverIO.ElementArray,
10+
elements: WdioElements,
911
wait = DEFAULT_OPTIONS.wait,
1012
full = false
11-
): Promise<WebdriverIO.ElementArray> => {
12-
if (elements) {
13-
if (wait > 0 && (elements.length === 0 || full)) {
14-
// @ts-ignore
15-
elements = (await elements.parent[elements.foundWith](elements.selector, ...elements.props) as WebdriverIO.ElementArray)
16-
}
13+
): Promise<WdioElements> => {
14+
if (elements && wait > 0 && (elements.length === 0 || full) && isElementArray(elements) && elements.parent && elements.foundWith && elements.foundWith in elements.parent) {
15+
const fetchFunction = elements.parent[elements.foundWith as keyof typeof elements.parent] as Function
16+
elements = await fetchFunction(elements.selector, ...elements.props)
1717
}
1818
return elements
1919
}

0 commit comments

Comments
 (0)