Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/matchers/element/toBeDisplayed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,32 @@ import { executeCommandBe } from '../../utils.js'
import { DEFAULT_OPTIONS } from '../../constants.js'
import type { WdioElementMaybePromise } from '../../types.js'

interface ToBeDisplayedOptions {
/**
* `true` to check if the element is within the viewport. false by default.
*/
withinViewport?: boolean
/**
* `true` to check if the element content-visibility property has (or inherits) the value auto,
* and it is currently skipping its rendering. `true` by default.
* @default true
*/
contentVisibilityAuto?: boolean
/**
* `true` to check if the element opacity property has (or inherits) a value of 0. `true` by default.
* @default true
*/
opacityProperty?: boolean
/**
* `true` to check if the element is invisible due to the value of its visibility property. `true` by default.
* @default true
*/
visibilityProperty?: boolean
}

export async function toBeDisplayed(
received: WdioElementMaybePromise,
{ withinViewport = false, contentVisibilityAuto = true, opacityProperty = true, visibilityProperty = true }: ToBeDisplayedOptions = {},
options: ExpectWebdriverIO.CommandOptions = DEFAULT_OPTIONS
) {
this.expectation = this.expectation || 'displayed'
Expand All @@ -13,7 +37,7 @@ export async function toBeDisplayed(
options,
})

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

await options.afterAssertion?.({
matcherName: 'toBeDisplayed',
Expand Down
2 changes: 1 addition & 1 deletion test/matchers/beMatchers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as Matchers from '../../src/matchers.js'

vi.mock('@wdio/globals')

const ignoredMatchers = ['toBeElementsArrayOfSize', 'toBeDisabled', 'toBeRequested', 'toBeRequestedTimes', 'toBeRequestedWithResponse', 'toBeRequestedWith']
const ignoredMatchers = ['toBeElementsArrayOfSize', 'toBeDisabled', 'toBeDisplayed', 'toBeRequested', 'toBeRequestedTimes', 'toBeRequestedWithResponse', 'toBeRequestedWith']
const beMatchers = [
...Object.keys(Matchers).filter(name => name.startsWith('toBe') && !ignoredMatchers.includes(name)),
'toExist'
Expand Down
146 changes: 146 additions & 0 deletions test/matchers/element/toBeDisplayed.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { vi, test, describe, expect } from 'vitest'
import { $ } from '@wdio/globals'

import { getExpectMessage, getReceived } from '../../__fixtures__/utils.js'
import { toBeDisplayed } from '../../../src/matchers/element/toBeDisplayed.js'

vi.mock('@wdio/globals')

describe('toBeDisplayed', () => {
/**
* result is inverted for toBeDisplayed because it inverts isEnabled result
* `!await el.isEnabled()`
*/
test('wait for success', async () => {
const el: any = await $('sel')
el._attempts = 2
el._value = function (): boolean {
if (this._attempts > 0) {
this._attempts--
return false
}
return true
}

const beforeAssertion = vi.fn()
const afterAssertion = vi.fn()
const result = await toBeDisplayed.call({}, el, {}, { beforeAssertion, afterAssertion })
expect(result.pass).toBe(true)
expect(el._attempts).toBe(0)
expect(beforeAssertion).toBeCalledWith({
matcherName: 'toBeDisplayed',
options: { beforeAssertion, afterAssertion }
})
expect(afterAssertion).toBeCalledWith({
matcherName: 'toBeDisplayed',
options: { beforeAssertion, afterAssertion },
result
})
})

test('wait but failure', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
throw new Error('some error')
}

await expect(() => toBeDisplayed.call({}, el))
.rejects.toThrow('some error')
})

test('success on the first attempt', async () => {
const el: any = await $('sel')
el._attempts = 0
el._value = function (): boolean {
this._attempts++
return true
}

const result = await toBeDisplayed.call({}, el)
expect(result.pass).toBe(true)
expect(el._attempts).toBe(1)
})

test('no wait - failure', async () => {
const el: any = await $('sel')
el._attempts = 0
el._value = function (): boolean {
this._attempts++
return false
}

const result = await toBeDisplayed.call({}, el, {}, { wait: 0 })
expect(result.pass).toBe(false)
expect(el._attempts).toBe(1)
})

test('no wait - success', async () => {
const el: any = await $('sel')
el._attempts = 0
el._value = function (): boolean {
this._attempts++
return true
}

const result = await toBeDisplayed.call({}, el, {}, { wait: 0 })
expect(result.pass).toBe(true)
expect(el._attempts).toBe(1)
})

test('not - failure', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
return true
}
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 0 })
const received = getReceived(result.message())

expect(received).not.toContain('not')
expect(result.pass).toBe(true)
})

test('not - success', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
return false
}
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 0 })
const received = getReceived(result.message())

expect(received).toContain('not')
expect(result.pass).toBe(false)
})

test('not - failure (with wait)', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
return true
}
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 1 })
const received = getReceived(result.message())

expect(received).not.toContain('not')
expect(result.pass).toBe(true)
})

test('not - success (with wait)', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
return false
}
const result = await toBeDisplayed.call({ isNot: true }, el, {}, { wait: 1 })
const received = getReceived(result.message())

expect(received).toContain('not')
expect(result.pass).toBe(false)
})

test('message', async () => {
const el: any = await $('sel')
el._value = function (): boolean {
return false
}
const result = await toBeDisplayed.call({}, el)
expect(getExpectMessage(result.message())).toContain('to be displayed')
})
})