Skip to content

Commit 5b73964

Browse files
committed
Add case of element not found which throws for single element
- Note that for multiple element so ElementArray, there is no exception but an empty array
1 parent aec39c2 commit 5b73964

3 files changed

Lines changed: 54 additions & 27 deletions

File tree

test/__mocks__/@wdio/globals.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,48 @@ export const elementFactory = (_selector: string, index?: number, parent: Webdri
7474
element.getElement = vi.fn().mockResolvedValue(element)
7575

7676
// Note: an element found has element.elementId while a not found has element.error
77-
// element.error = new Error(`Couldn't find element with selector "${_selector}"`)
78-
// element.elementId = `elementId-${index ?? 0}-${_selector}`
77+
element.elementId = `${_selector}${index ? '-' + index : ''}`
7978

8079
return element
8180
}
8281

82+
export const notFoundElementFactory = (_selector: string, index?: number, parent: WebdriverIO.Browser | WebdriverIO.Element = browser): WebdriverIO.Element => {
83+
const partialElement = {
84+
selector: _selector,
85+
index,
86+
$,
87+
$$,
88+
isExisting: vi.fn().mockResolvedValue(false),
89+
parent
90+
} satisfies Partial<WebdriverIO.Element>
91+
92+
const element = partialElement as unknown as WebdriverIO.Element
93+
94+
// Note: an element found has element.elementId while a not found has element.error
95+
const elementId = `${_selector}${index ? '-' + index : ''}`
96+
const error = (functionName: string) => new Error(`Can't call ${functionName} on element with selector ${elementId} because element wasn't found`)
97+
98+
// Mimic element not found by throwing error on any method call beisde isExisting
99+
const notFoundElement = new Proxy(element, {
100+
get(target, prop) {
101+
if (prop in element) {
102+
const value = element[prop as keyof WebdriverIO.Element]
103+
return value
104+
}
105+
if (['then', 'catch', 'toStringTag'].includes(prop as string) || typeof prop === 'symbol') {
106+
const value = Reflect.get(target, prop)
107+
return typeof value === 'function' ? value.bind(target) : value
108+
}
109+
element.error = error(prop as string)
110+
return () => { throw element.error }
111+
}
112+
})
113+
114+
element.getElement = vi.fn().mockResolvedValue(notFoundElement)
115+
116+
return notFoundElement
117+
}
118+
83119
const $ = vi.fn((_selector: string) => {
84120
const element = elementFactory(_selector)
85121

test/matchers/element/toBeDisplayed.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { $, $$ } from '@wdio/globals'
33

44
import { toBeDisplayed } from '../../../src/matchers/element/toBeDisplayed.js'
55
import { executeCommandBe, waitUntil } from '../../../src/utils.js'
6+
import { notFoundElementFactory } from '../../__mocks__/@wdio/globals.js'
67

78
vi.mock('@wdio/globals')
89

@@ -549,4 +550,16 @@ Expect ${selectorName} to be displayed
549550
Expected: "displayed"
550551
Received: "not displayed"`)
551552
})
553+
554+
describe('not found element', async () => {
555+
let element: WebdriverIO.Element
556+
557+
beforeEach(async () => {
558+
element = notFoundElementFactory('sel')
559+
})
560+
561+
test('throws error when an element does not exists', async () => {
562+
await expect(thisContext.toBeDisplayed(element)).rejects.toThrow("Can't call isDisplayed on element with selector sel because element wasn't found")
563+
})
564+
})
552565
})

test/util/elementsUtil.test.ts

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { vi, test, describe, expect, beforeEach } from 'vitest'
22
import { $, $$, } from '@wdio/globals'
33

4-
import { awaitElementOrArray, awaitElementArray, wrapExpectedWithArray, map, isStrictlyElementArray, isElement, isElementArrayLike, isElementOrArrayLike, isElementOrNotEmptyElementArray } from '../../src/util/elementsUtil.js'
5-
import { chainableElementArrayFactory, elementArrayFactory, elementFactory } from '../__mocks__/@wdio/globals.js'
4+
import { awaitElementOrArray, awaitElementArray, wrapExpectedWithArray, map, isStrictlyElementArray, isElement, isElementArrayLike, isElementOrArrayLike } from '../../src/util/elementsUtil.js'
5+
import { chainableElementArrayFactory, elementArrayFactory, elementFactory, notFoundElementFactory } from '../__mocks__/@wdio/globals.js'
66

77
vi.mock('@wdio/globals')
88

@@ -383,6 +383,7 @@ describe('elementsUtil', () => {
383383
await $('element').getElement(),
384384
await $('element'),
385385
elementFactory('element'),
386+
notFoundElementFactory('notFoundElement')
386387
])('should return true for Element: %s', async (element) => {
387388
const isElementResult = isElement(element)
388389

@@ -478,27 +479,4 @@ describe('elementsUtil', () => {
478479
expect(result).toBe(false)
479480
})
480481
})
481-
482-
describe(isElementOrNotEmptyElementArray, async () => {
483-
test.for([
484-
await $('element'),
485-
await $$('elements'),
486-
[elementFactory('element1'), elementFactory('element2')],
487-
])('should return true for Element or non-empty ElementArray/Element[]: %s', async (element) => {
488-
const result = isElementOrNotEmptyElementArray(element)
489-
490-
expect(result).toBe(true)
491-
})
492-
test.for([
493-
[],
494-
$$('elements'),
495-
$('element'),
496-
'1',
497-
{},
498-
])('should return false for non-Element or empty array: %s', async (element) => {
499-
const result = isElementOrNotEmptyElementArray(element)
500-
501-
expect(result).toBe(false)
502-
})
503-
})
504482
})

0 commit comments

Comments
 (0)