Skip to content

Commit 48b3282

Browse files
polish(expect-webdriverio): expose contentVisibilityAuto, opacityProperty and visibilityProperty to toBeDisplayed (#1897)
* polish(expect-webdriverio): expose contentVisibilityAuto, opacityProperty and visibilityProperty to toBeDisplayed * polish(expect-webdriverio): expose contentVisibilityAuto, opacityProperty and visibilityProperty to toBeDisplayed * polish(expect-webdriverio): expose contentVisibilityAuto, opacityProperty and visibilityProperty to toBeDisplayed
1 parent 050b06f commit 48b3282

File tree

3 files changed

+172
-2
lines changed

3 files changed

+172
-2
lines changed

src/matchers/element/toBeDisplayed.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,32 @@ import { executeCommandBe } from '../../utils.js'
22
import { DEFAULT_OPTIONS } from '../../constants.js'
33
import type { WdioElementMaybePromise } from '../../types.js'
44

5+
interface ToBeDisplayedOptions {
6+
/**
7+
* `true` to check if the element is within the viewport. false by default.
8+
*/
9+
withinViewport?: boolean
10+
/**
11+
* `true` to check if the element content-visibility property has (or inherits) the value auto,
12+
* and it is currently skipping its rendering. `true` by default.
13+
* @default true
14+
*/
15+
contentVisibilityAuto?: boolean
16+
/**
17+
* `true` to check if the element opacity property has (or inherits) a value of 0. `true` by default.
18+
* @default true
19+
*/
20+
opacityProperty?: boolean
21+
/**
22+
* `true` to check if the element is invisible due to the value of its visibility property. `true` by default.
23+
* @default true
24+
*/
25+
visibilityProperty?: boolean
26+
}
27+
528
export async function toBeDisplayed(
629
received: WdioElementMaybePromise,
30+
{ withinViewport = false, contentVisibilityAuto = true, opacityProperty = true, visibilityProperty = true }: ToBeDisplayedOptions = {},
731
options: ExpectWebdriverIO.CommandOptions = DEFAULT_OPTIONS
832
) {
933
this.expectation = this.expectation || 'displayed'
@@ -13,7 +37,7 @@ export async function toBeDisplayed(
1337
options,
1438
})
1539

16-
const result = await executeCommandBe.call(this, received, el => el?.isDisplayed(), options)
40+
const result = await executeCommandBe.call(this, received, el => el?.isDisplayed({ withinViewport, contentVisibilityAuto, opacityProperty, visibilityProperty }), options)
1741

1842
await options.afterAssertion?.({
1943
matcherName: 'toBeDisplayed',

test/matchers/beMatchers.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as Matchers from '../../src/matchers.js'
55

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

8-
const ignoredMatchers = ['toBeElementsArrayOfSize', 'toBeDisabled', 'toBeRequested', 'toBeRequestedTimes', 'toBeRequestedWithResponse', 'toBeRequestedWith']
8+
const ignoredMatchers = ['toBeElementsArrayOfSize', 'toBeDisabled', 'toBeDisplayed', 'toBeRequested', 'toBeRequestedTimes', 'toBeRequestedWithResponse', 'toBeRequestedWith']
99
const beMatchers = [
1010
...Object.keys(Matchers).filter(name => name.startsWith('toBe') && !ignoredMatchers.includes(name)),
1111
'toExist'
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { vi, test, describe, expect } from 'vitest'
2+
import { $ } from '@wdio/globals'
3+
4+
import { getExpectMessage, getReceived } from '../../__fixtures__/utils.js'
5+
import { toBeDisplayed } from '../../../src/matchers/element/toBeDisplayed.js'
6+
7+
vi.mock('@wdio/globals')
8+
9+
describe('toBeDisplayed', () => {
10+
/**
11+
* result is inverted for toBeDisplayed because it inverts isEnabled result
12+
* `!await el.isEnabled()`
13+
*/
14+
test('wait for success', async () => {
15+
const el: any = await $('sel')
16+
el._attempts = 2
17+
el._value = function (): boolean {
18+
if (this._attempts > 0) {
19+
this._attempts--
20+
return false
21+
}
22+
return true
23+
}
24+
25+
const beforeAssertion = vi.fn()
26+
const afterAssertion = vi.fn()
27+
const result = await toBeDisplayed.call({}, el, {}, { beforeAssertion, afterAssertion })
28+
expect(result.pass).toBe(true)
29+
expect(el._attempts).toBe(0)
30+
expect(beforeAssertion).toBeCalledWith({
31+
matcherName: 'toBeDisplayed',
32+
options: { beforeAssertion, afterAssertion }
33+
})
34+
expect(afterAssertion).toBeCalledWith({
35+
matcherName: 'toBeDisplayed',
36+
options: { beforeAssertion, afterAssertion },
37+
result
38+
})
39+
})
40+
41+
test('wait but failure', async () => {
42+
const el: any = await $('sel')
43+
el._value = function (): boolean {
44+
throw new Error('some error')
45+
}
46+
47+
await expect(() => toBeDisplayed.call({}, el))
48+
.rejects.toThrow('some error')
49+
})
50+
51+
test('success on the first attempt', async () => {
52+
const el: any = await $('sel')
53+
el._attempts = 0
54+
el._value = function (): boolean {
55+
this._attempts++
56+
return true
57+
}
58+
59+
const result = await toBeDisplayed.call({}, el)
60+
expect(result.pass).toBe(true)
61+
expect(el._attempts).toBe(1)
62+
})
63+
64+
test('no wait - failure', async () => {
65+
const el: any = await $('sel')
66+
el._attempts = 0
67+
el._value = function (): boolean {
68+
this._attempts++
69+
return false
70+
}
71+
72+
const result = await toBeDisplayed.call({}, el, {}, { wait: 0 })
73+
expect(result.pass).toBe(false)
74+
expect(el._attempts).toBe(1)
75+
})
76+
77+
test('no wait - success', async () => {
78+
const el: any = await $('sel')
79+
el._attempts = 0
80+
el._value = function (): boolean {
81+
this._attempts++
82+
return true
83+
}
84+
85+
const result = await toBeDisplayed.call({}, el, {}, { wait: 0 })
86+
expect(result.pass).toBe(true)
87+
expect(el._attempts).toBe(1)
88+
})
89+
90+
test('not - failure', async () => {
91+
const el: any = await $('sel')
92+
el._value = function (): boolean {
93+
return true
94+
}
95+
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 0 })
96+
const received = getReceived(result.message())
97+
98+
expect(received).not.toContain('not')
99+
expect(result.pass).toBe(true)
100+
})
101+
102+
test('not - success', async () => {
103+
const el: any = await $('sel')
104+
el._value = function (): boolean {
105+
return false
106+
}
107+
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 0 })
108+
const received = getReceived(result.message())
109+
110+
expect(received).toContain('not')
111+
expect(result.pass).toBe(false)
112+
})
113+
114+
test('not - failure (with wait)', async () => {
115+
const el: any = await $('sel')
116+
el._value = function (): boolean {
117+
return true
118+
}
119+
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 1 })
120+
const received = getReceived(result.message())
121+
122+
expect(received).not.toContain('not')
123+
expect(result.pass).toBe(true)
124+
})
125+
126+
test('not - success (with wait)', async () => {
127+
const el: any = await $('sel')
128+
el._value = function (): boolean {
129+
return false
130+
}
131+
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 1 })
132+
const received = getReceived(result.message())
133+
134+
expect(received).toContain('not')
135+
expect(result.pass).toBe(false)
136+
})
137+
138+
test('message', async () => {
139+
const el: any = await $('sel')
140+
el._value = function (): boolean {
141+
return false
142+
}
143+
const result = await toBeDisplayed.call({}, el)
144+
expect(getExpectMessage(result.message())).toContain('to be displayed')
145+
})
146+
})

0 commit comments

Comments
 (0)