From 4bac55e9befbea36eb39889287caffad2cfb4ff2 Mon Sep 17 00:00:00 2001 From: dprevost-perso Date: Sun, 4 Jan 2026 16:51:00 -0500 Subject: [PATCH 1/2] fix failure msg with `enhanceErrorBe` + code refactoring simplification - Fix double negation in `Expected` with `isNot` when using `enhanceErrorBe` - Fix incorrect Received value with `isNot` when using `enhanceErrorBe` - Code refactoring simplify to better understand the code --- src/util/formatMessage.ts | 55 ++-- src/utils.ts | 5 +- test/__fixtures__/utils.ts | 12 +- test/matchers.test.ts | 28 +- test/matchers/beMatchers.test.ts | 15 +- test/matchers/browserMatchers.test.ts | 14 +- test/matchers/element/toBeDisabled.test.ts | 8 +- test/matchers/element/toBeDisplayed.test.ts | 4 +- .../element/toHaveComputedLabel.test.ts | 21 +- test/matchers/element/toHaveHeight.test.ts | 9 +- test/matchers/element/toHaveStyle.test.ts | 15 + test/matchers/element/toHaveWidth.test.ts | 1 - test/matchers/mock/toBeRequestedWith.test.ts | 23 +- test/util/formatMessage.test.ts | 300 ++++++++++++------ 14 files changed, 306 insertions(+), 204 deletions(-) diff --git a/src/util/formatMessage.ts b/src/util/formatMessage.ts index d5bf2b665..0d668593a 100644 --- a/src/util/formatMessage.ts +++ b/src/util/formatMessage.ts @@ -3,11 +3,6 @@ import { equals } from '../jasmineUtils.js' import type { WdioElements } from '../types.js' import { isElementArray } from './elementsUtil.js' -const EXPECTED_LABEL = 'Expected' -const RECEIVED_LABEL = 'Received' -const NOT_SUFFIX = ' [not]' -const NOT_EXPECTED_LABEL = EXPECTED_LABEL + NOT_SUFFIX - export const getSelector = (el: WebdriverIO.Element | WebdriverIO.ElementArray) => { let result = typeof el.selector === 'string' ? el.selector : '' if (Array.isArray(el) && (el as WebdriverIO.ElementArray).props.length > 0) { @@ -39,22 +34,20 @@ export const getSelectors = (el: WebdriverIO.Element | WdioElements) => { return selectors.reverse().join('.') } -export const not = (isNot: boolean): string => { - return `${isNot ? 'not ' : ''}` -} +const not = (isNot: boolean): string => `${isNot ? 'not ' : ''}` export const enhanceError = ( subject: string | WebdriverIO.Element | WdioElements, expected: unknown, actual: unknown, - context: { isNot: boolean }, + context: { isNot: boolean, useNotInLabel?: boolean }, verb: string, expectation: string, - arg2 = '', { + expectedValueArgument2 = '', { message = '', containing = false - }): string => { - const { isNot = false } = context + } = {}): string => { + const { isNot = false, useNotInLabel = true } = context subject = typeof subject === 'string' ? subject : getSelectors(subject) @@ -67,37 +60,43 @@ export const enhanceError = ( verb += ' ' } - let diffString = isNot && equals(actual, expected) - ? `${EXPECTED_LABEL}: ${printExpected(expected)}\n${RECEIVED_LABEL}: ${printReceived(actual)}` - : printDiffOrStringify(expected, actual, EXPECTED_LABEL, RECEIVED_LABEL, true) - - if (isNot) { - diffString = diffString - .replace(EXPECTED_LABEL, NOT_EXPECTED_LABEL) - .replace(RECEIVED_LABEL, RECEIVED_LABEL + ' '.repeat(NOT_SUFFIX.length)) + const label = { + expected: isNot && useNotInLabel ? 'Expected [not]' : 'Expected', + received: isNot && useNotInLabel ? 'Received ' : 'Received' } + // Using `printDiffOrStringify()` with equals values output `Received: serializes to the same string`, so we need to tweak. + const diffString = equals(actual, expected) ?`\ +${label.expected}: ${printExpected(expected)} +${label.received}: ${printReceived(actual)}` + : printDiffOrStringify(expected, actual, label.expected, label.received, true) + if (message) { message += '\n' } - if (arg2) { - arg2 = ` ${arg2}` + if (expectedValueArgument2) { + expectedValueArgument2 = ` ${expectedValueArgument2}` } - const msg = `${message}Expect ${subject} ${not(isNot)}to ${verb}${expectation}${arg2}${contain}\n\n${diffString}` + const msg = `\ +${message}Expect ${subject} ${not(isNot)}to ${verb}${expectation}${expectedValueArgument2}${contain} + +${diffString}` + return msg } export const enhanceErrorBe = ( subject: string | WebdriverIO.Element | WebdriverIO.ElementArray, - pass: boolean, - context: { isNot: boolean }, - verb: string, - expectation: string, + context: { isNot: boolean, verb: string, expectation: string }, options: ExpectWebdriverIO.CommandOptions ) => { - return enhanceError(subject, not(context.isNot) + expectation, not(!pass) + expectation, context, verb, expectation, '', options) + const { isNot, verb, expectation } = context + const expected = `${not(isNot)}${expectation}` + const actual = `${not(!isNot)}${expectation}` + + return enhanceError(subject, expected, actual, { ...context, useNotInLabel: false }, verb, expectation, '', options) } export const numberError = (options: ExpectWebdriverIO.NumberOptions = {}): string | number => { diff --git a/src/utils.ts b/src/utils.ts index 8720b86cc..eb61be539 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -72,8 +72,6 @@ async function executeCommandBe( command: (el: WebdriverIO.Element) => Promise, options: ExpectWebdriverIO.CommandOptions ): ExpectWebdriverIO.AsyncAssertionResult { - const { expectation, verb = 'be' } = this - let el = await received?.getElement() const pass = await waitUntil( async () => { @@ -89,7 +87,8 @@ async function executeCommandBe( options ) - const message = enhanceErrorBe(el, pass, this, verb, expectation, options) + const { verb = 'be' } = this + const message = enhanceErrorBe(el, { ...this, verb }, options) return { pass, diff --git a/test/__fixtures__/utils.ts b/test/__fixtures__/utils.ts index 95bca72a4..8fb349aca 100644 --- a/test/__fixtures__/utils.ts +++ b/test/__fixtures__/utils.ts @@ -1,8 +1,4 @@ -export function matcherNameToString(matcherName: string) { - return matcherName.replace(/([A-Z])/g, ' $1').toLowerCase() -} - -export function matcherLastWordName(matcherName: string) { +export function matcherNameLastWords(matcherName: string) { return matcherName.replace(/^toHave/, '').replace(/^toBe/, '') .replace(/([A-Z])/g, ' $1').trim().toLowerCase() } @@ -22,9 +18,3 @@ export function getReceived(msg: string) { function getReceivedOrExpected(msg: string, type: string) { return msg.split('\n').find((line, idx) => idx > 1 && line.startsWith(type)) } - -export function removeColors(msg: string) { - // eslint-disable-next-line no-control-regex - const s = msg.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '') - return s -} diff --git a/test/matchers.test.ts b/test/matchers.test.ts index 7cb19b8aa..a70950512 100644 --- a/test/matchers.test.ts +++ b/test/matchers.test.ts @@ -111,43 +111,43 @@ describe('Custom Wdio Matchers Integration Tests', async () => { await expect(() => expectLib(el).not.toBeDisplayed({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be displayed -Expected [not]: "not displayed" -Received : "displayed"` +Expected: "not displayed" +Received: "displayed"` ) await expect(() => expectLib(el).not.toBeExisting({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be existing -Expected [not]: "not existing" -Received : "existing"` +Expected: "not existing" +Received: "existing"` ) await expect(() => expectLib(el).not.toBeEnabled({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be enabled -Expected [not]: "not enabled" -Received : "enabled"` +Expected: "not enabled" +Received: "enabled"` ) await expect(() => expectLib(el).not.toBeClickable({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be clickable -Expected [not]: "not clickable" -Received : "clickable"` +Expected: "not clickable" +Received: "clickable"` ) await expect(() => expectLib(el).not.toBeFocused({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be focused -Expected [not]: "not focused" -Received : "focused"` +Expected: "not focused" +Received: "focused"` ) await expect(() => expectLib(el).not.toBeSelected({ wait: 1 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be selected -Expected [not]: "not selected" -Received : "selected"` +Expected: "not selected" +Received: "selected"` ) }) @@ -423,8 +423,8 @@ Received: 100`) await expect(() => expectLib(el).not.toBeDisplayed({ wait: 300, interval: 100 })).rejects.toThrow(`\ Expect $(\`selector\`) not to be displayed -Expected [not]: "not displayed" -Received : "displayed"`) +Expected: "not displayed" +Received: "displayed"`) expect(el.isDisplayed).toHaveBeenCalledTimes(6) }) diff --git a/test/matchers/beMatchers.test.ts b/test/matchers/beMatchers.test.ts index c2eba4864..f1af6187c 100644 --- a/test/matchers/beMatchers.test.ts +++ b/test/matchers/beMatchers.test.ts @@ -1,6 +1,6 @@ import { vi, test, describe, expect } from 'vitest' import { $ } from '@wdio/globals' -import { matcherLastWordName } from '../__fixtures__/utils.js' +import { matcherNameLastWords } from '../__fixtures__/utils.js' import * as Matchers from '../../src/matchers.js' vi.mock('@wdio/globals') @@ -78,6 +78,7 @@ describe('be* matchers', () => { el[elementFnName] = vi.fn().mockResolvedValue(true) const result = await matcherFn.call({}, el, { wait: 0 }) as ExpectWebdriverIO.AssertionResult + expect(result.pass).toBe(true) expect(el[elementFnName]).toHaveBeenCalledTimes(1) }) @@ -89,10 +90,10 @@ describe('be* matchers', () => { expect(result.pass).toBe(true) // failure, boolean is inverted later because of `.not` expect(result.message()).toEqual(`\ -Expect $(\`sel\`) not to be ${matcherLastWordName(matcherName)} +Expect $(\`sel\`) not to be ${matcherNameLastWords(matcherName)} -Expected [not]: "not ${matcherLastWordName(matcherName)}" -Received : "${matcherLastWordName(matcherName)}"` +Expected: "not ${matcherNameLastWords(matcherName)}" +Received: "${matcherNameLastWords(matcherName)}"` ) }) @@ -129,10 +130,10 @@ Received : "${matcherLastWordName(matcherName)}"` const result = await matcherFn.call({}, el, { wait: 1 }) as ExpectWebdriverIO.AssertionResult expect(result.pass).toBe(false) expect(result.message()).toBe(`\ -Expect $(\`sel\`) to be ${matcherLastWordName(matcherName)} +Expect $(\`sel\`) to be ${matcherNameLastWords(matcherName)} -Expected: "${matcherLastWordName(matcherName)}" -Received: "not ${matcherLastWordName(matcherName)}"` +Expected: "${matcherNameLastWords(matcherName)}" +Received: "not ${matcherNameLastWords(matcherName)}"` ) }) }) diff --git a/test/matchers/browserMatchers.test.ts b/test/matchers/browserMatchers.test.ts index f017b5674..4aee8e94d 100644 --- a/test/matchers/browserMatchers.test.ts +++ b/test/matchers/browserMatchers.test.ts @@ -1,7 +1,7 @@ import { vi, test, describe, expect } from 'vitest' import { browser } from '@wdio/globals' -import { getExpectMessage, matcherNameToString, matcherLastWordName } from '../__fixtures__/utils.js' +import { matcherNameLastWords } from '../__fixtures__/utils.js' import * as Matchers from '../../src/matchers.js' vi.mock('@wdio/globals') @@ -67,7 +67,7 @@ describe('browser matchers', () => { expect(result.pass).toBe(true) // failure, boolean is inverted later because of `.not` expect(result.message()).toEqual(`\ -Expect window not to have ${matcherLastWordName(matcherName)} +Expect window not to have ${matcherNameLastWords(matcherName)} Expected [not]: " Valid Text " Received : " Valid Text "` @@ -89,7 +89,7 @@ Received : " Valid Text "` expect(result.pass).toBe(true) // failure, boolean is inverted later because of `.not` expect(result.message()).toEqual(`\ -Expect window not to have ${matcherLastWordName(matcherName)} +Expect window not to have ${matcherNameLastWords(matcherName)} Expected [not]: " Valid Text " Received : " Valid Text "` @@ -106,7 +106,13 @@ Received : " Valid Text "` test('message', async () => { const result = await matcherFn.call({}, browser) as ExpectWebdriverIO.AssertionResult - expect(getExpectMessage(result.message())).toContain(matcherNameToString(matcherName)) + + expect(result.pass).toBe(false) + expect(result.message()).toEqual(`\ +Expect window to have ${matcherNameLastWords(matcherName)} + +Expected: undefined +Received: " Wrong Text "`) }) }) }) diff --git a/test/matchers/element/toBeDisabled.test.ts b/test/matchers/element/toBeDisabled.test.ts index 1b0dac3e4..6766d53f2 100644 --- a/test/matchers/element/toBeDisabled.test.ts +++ b/test/matchers/element/toBeDisabled.test.ts @@ -78,8 +78,8 @@ describe('toBeDisabled', () => { expect(result.message()).toEqual(`\ Expect $(\`sel\`) not to be disabled -Expected [not]: "not disabled" -Received : "disabled"` +Expected: "not disabled" +Received: "disabled"` ) }) @@ -102,8 +102,8 @@ Received : "disabled"` expect(result.message()).toEqual(`\ Expect $(\`sel\`) not to be disabled -Expected [not]: "not disabled" -Received : "disabled"` +Expected: "not disabled" +Received: "disabled"` ) }) diff --git a/test/matchers/element/toBeDisplayed.test.ts b/test/matchers/element/toBeDisplayed.test.ts index 250ead0bd..541fccc76 100644 --- a/test/matchers/element/toBeDisplayed.test.ts +++ b/test/matchers/element/toBeDisplayed.test.ts @@ -147,8 +147,8 @@ describe('toBeDisplayed', () => { expect(result.message()).toEqual(`\ Expect $(\`sel\`) not to be displayed -Expected [not]: "not displayed" -Received : "displayed"` +Expected: "not displayed" +Received: "displayed"` ) }) diff --git a/test/matchers/element/toHaveComputedLabel.test.ts b/test/matchers/element/toHaveComputedLabel.test.ts index 02f95a5b2..8ff094469 100644 --- a/test/matchers/element/toHaveComputedLabel.test.ts +++ b/test/matchers/element/toHaveComputedLabel.test.ts @@ -1,7 +1,7 @@ import { vi, test, describe, expect, beforeEach } from 'vitest' import { $ } from '@wdio/globals' -import { getExpectMessage, getReceived, getExpected } from '../../__fixtures__/utils.js' +import { getExpectMessage } from '../../__fixtures__/utils.js' import { toHaveComputedLabel } from '../../../src/matchers/element/toHaveComputedLabel.js' vi.mock('@wdio/globals') @@ -271,18 +271,25 @@ Received : "WebdriverIO"` test('failure if no match', async () => { const result = await toHaveComputedLabel.call({}, el, /Webdriver/i) + expect(result.pass).toBe(false) - expect(getExpectMessage(result.message())).toContain('to have computed label') - expect(getExpected(result.message())).toContain('/Webdriver/i') - expect(getReceived(result.message())).toContain('This is example computed label') + expect(result.message()).toEqual(`\ +Expect $(\`sel\`) to have computed label + +Expected: /Webdriver/i +Received: "This is example computed label"`) }) test('failure if array does not match with computed label', async () => { const result = await toHaveComputedLabel.call({}, el, ['div', /Webdriver/i]) + expect(result.pass).toBe(false) - expect(getExpectMessage(result.message())).toContain('to have computed label') - expect(getExpected(result.message())).toContain('/Webdriver/i') - expect(getExpected(result.message())).toContain('div') + expect(result.message()).toEqual(`\ +Expect $(\`sel\`) to have computed label + +Expected: ["div", /Webdriver/i] +Received: "This is example computed label"` + ) }) }) }) diff --git a/test/matchers/element/toHaveHeight.test.ts b/test/matchers/element/toHaveHeight.test.ts index 8f6134cf7..bb75e3bb2 100755 --- a/test/matchers/element/toHaveHeight.test.ts +++ b/test/matchers/element/toHaveHeight.test.ts @@ -1,7 +1,5 @@ import { vi, test, describe, expect } from 'vitest' import { $ } from '@wdio/globals' - -import { getExpectMessage } from '../../__fixtures__/utils.js' import { toHaveHeight } from '../../../src/matchers/element/toHaveHeight.js' vi.mock('@wdio/globals') @@ -48,7 +46,6 @@ describe('toHaveHeight', () => { const result = await toHaveHeight.call({}, el, 32, {}) - expect(result.message()).toEqual('Expect $(`sel`) to have height\n\nExpected: 32\nReceived: serializes to the same string') expect(result.pass).toBe(true) expect(el.getSize).toHaveBeenCalledTimes(1) }) @@ -130,6 +127,10 @@ Received : 32` const result = await toHaveHeight.call({}, el, 50) - expect(getExpectMessage(result.message())).toContain('to have height') + expect(result.message()).toEqual(`\ +Expect $(\`sel\`) to have height + +Expected: 50 +Received: null`) }) }) diff --git a/test/matchers/element/toHaveStyle.test.ts b/test/matchers/element/toHaveStyle.test.ts index 225e5204e..0beed3ba2 100644 --- a/test/matchers/element/toHaveStyle.test.ts +++ b/test/matchers/element/toHaveStyle.test.ts @@ -124,7 +124,22 @@ Received : {"color": "#000", "font-family": "Faktum", "font-size": "26px"}` } const result = await toHaveStyle.bind({ })(el, wrongStyle, { wait: 1 }) + expect(result.pass).toBe(false) + expect(result.message()).toEqual(`\ +Expect $(\`sel\`) to have style + +- Expected - 3 ++ Received + 3 + + Object { +- "color": "#fff", +- "font-family": "Incorrect Font", +- "font-size": "100px", ++ "color": "#000", ++ "font-family": "Faktum", ++ "font-size": "26px", + }`) }) test('should return true if styles match', async () => { diff --git a/test/matchers/element/toHaveWidth.test.ts b/test/matchers/element/toHaveWidth.test.ts index 8a13f0700..375c5c752 100755 --- a/test/matchers/element/toHaveWidth.test.ts +++ b/test/matchers/element/toHaveWidth.test.ts @@ -44,7 +44,6 @@ describe('toHaveWidth', () => { const result = await toHaveWidth.call({}, el, 50, {}) - expect(result.message()).toEqual('Expect $(`sel`) to have width\n\nExpected: 50\nReceived: serializes to the same string') expect(result.pass).toBe(true) expect(el.getSize).toHaveBeenCalledTimes(1) }) diff --git a/test/matchers/mock/toBeRequestedWith.test.ts b/test/matchers/mock/toBeRequestedWith.test.ts index d4c8adab2..5e5e0b8bd 100644 --- a/test/matchers/mock/toBeRequestedWith.test.ts +++ b/test/matchers/mock/toBeRequestedWith.test.ts @@ -2,7 +2,6 @@ import { vi, test, describe, expect, beforeEach, afterEach } from 'vitest' import { toBeRequestedWith } from '../../../src/matchers/mock/toBeRequestedWith.js' import type { local } from 'webdriver' -import { removeColors, getExpectMessage, getExpected, getReceived } from '../../__fixtures__/utils.js' vi.mock('@wdio/globals') @@ -457,27 +456,21 @@ Received : {}` postData: expect.anything(), response: [...Array(50).keys()].map((_, id) => ({ id, name: `name_${id}` })), }) - const wasNotCalled = removeColors(requested.message()) - expect(getExpectMessage(wasNotCalled)).toBe('Expect mock to be called with') - expect(getExpected(wasNotCalled)).toBe( - 'Expected: {' + - '"method": ["DELETE", "PUT"], ' + - '"postData": "Anything ", ' + - '"requestHeaders": {"Accept": "*", "Authorization": "Bearer ..2222222", "foo": "bar"}, ' + - '"response": [{"id": 0, "name": "name_0"}, "... 49 more items"], ' + - '"responseHeaders": {}, ' + - '"url": "() => false"}' + expect(requested.pass).toBe(false) + expect(requested.message()).toEqual(`\ +Expect mock to be called with + +Expected: {"method": ["DELETE", "PUT"], "postData": "Anything ", "requestHeaders": {"Accept": "*", "Authorization": "Bearer ..2222222", "foo": "bar"}, "response": [{"id": 0, "name": "name_0"}, "... 49 more items"], "responseHeaders": {}, "url": "() => false"} +Received: "was not called"` ) - expect(getReceived(wasNotCalled)).toBe('Received: "was not called"') mock.calls.push(mockPost) - const notRequested = await toBeRequestedWith.call({ isNot: true }, mock, { url: () => true, method: mockPost.request.method, }) - const wasCalled = removeColors(notRequested.message()) - expect(wasCalled).toBe( + + expect(notRequested.message()).toBe( `Expect mock not to be called with - Expected [not] - 1 diff --git a/test/util/formatMessage.test.ts b/test/util/formatMessage.test.ts index 0bfcdd287..f75db27dc 100644 --- a/test/util/formatMessage.test.ts +++ b/test/util/formatMessage.test.ts @@ -1,170 +1,223 @@ import { test, describe, beforeEach, expect } from 'vitest' -import { printDiffOrStringify, printExpected, printReceived } from 'jest-matcher-utils' +import { printDiffOrStringify } from 'jest-matcher-utils' -import { enhanceError, numberError } from '../../src/util/formatMessage.js' +import { enhanceError, enhanceErrorBe, numberError } from '../../src/util/formatMessage.js' describe('formatMessage', () => { - describe('enhanceError', () => { + describe(enhanceError, () => { describe('default', () => { - let actual: string + let actualFailureMessage: string + const expected = 'Test Expected Value' + const actual = 'Test Actual Value' beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Expected', - 'Test Actual', + actualFailureMessage = enhanceError( + 'window', + expected, + actual, { isNot: false }, - 'Test Verb', - 'Test Expectation', - '', - { message: '', containing: false } + 'have', + 'title', ) }) - test('starting message', () => { - expect(actual).toMatch('Expect Test Subject to Test Verb Test Expectation') + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window to have title + +Expected: "Test Expected Value" +Received: "Test Actual Value"`) }) test('diff string', () => { - const diffString = printDiffOrStringify('Test Expected', 'Test Actual', 'Expected', 'Received', true) - expect(actual).toMatch(diffString) + const diffString = printDiffOrStringify('Test Expected Value', 'Test Actual Value', 'Expected', 'Received', true) + expect(diffString).toEqual(`\ +Expected: "Test Expected Value" +Received: "Test Actual Value"`) + expect(actualFailureMessage).toMatch(diffString) }) }) describe('isNot', () => { - let actual: string + let actualFailureMessage: string + const isNot = true + + describe('same', () => { + const expected = 'Test Same' + const actual = expected - describe('different', () => { beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Expected', - 'Test Actual', - { isNot: true }, - 'Test Verb', - 'Test Expectation', - '', - { message: '', containing: false } + actualFailureMessage = enhanceError( + 'window', + expected, + actual, + { isNot }, + 'have', + 'title' ) }) - test('starting message', () => { - expect(actual).toMatch('Expect Test Subject not to Test Verb Test Expectation') + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window not to have title + +Expected [not]: "Test Same" +Received : "Test Same"`) }) test('diff string', () => { - const diffString = printDiffOrStringify('Test Expected', 'Test Actual', 'Expected [not]', 'Received ', true) - expect(actual).toMatch(diffString) + const diffString = `\ +Expected [not]: "Test Same" +Received : "Test Same"` + expect(actualFailureMessage).toMatch(diffString) }) }) + }) + + describe('containing', () => { + let actualFailureMessage: string + + describe('isNot false', () => { + const expected = 'Test Expected Value' + const actual = 'Test Actual Value' + const isNot = false - describe('same', () => { beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Same', - 'Test Same', - { isNot: true }, - 'Test Verb', - 'Test Expectation', + actualFailureMessage = enhanceError( + 'window', + expected, + actual, + { isNot }, + 'have', + 'title', '', - { message: '', containing: false } + { message: '', containing: true } ) }) - test('starting message', () => { - expect(actual).toMatch('Expect Test Subject not to Test Verb Test Expectation') - }) + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window to have title containing - test('diff string', () => { - const diffString = `Expected [not]: ${printExpected('Test Same')}\n` + - `Received : ${printReceived('Test Same')}` - expect(actual).toMatch(diffString) +Expected: "Test Expected Value" +Received: "Test Actual Value"`) }) }) - }) - - describe('containing', () => { - let actual: string + describe('isNot true', () => { + const expected = 'same value' + const actual = expected + const isNot = true - beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Expected', - 'Test Actual', - { isNot: false }, - 'Test Verb', - 'Test Expectation', - '', - { message: '', containing: true } - ) - }) + beforeEach(() => { + actualFailureMessage = enhanceError( + 'window', + expected, + actual, + { isNot }, + 'have', + 'title', + '', + { message: '', containing: true } + ) + }) - test('starting message', () => { - expect(actual).toMatch('Expect Test Subject to Test Verb Test Expectation containing') - }) + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window not to have title containing - test('diff string', () => { - const diffString = printDiffOrStringify('Test Expected', 'Test Actual', 'Expected', 'Received', true) - expect(actual).toMatch(diffString) +Expected [not]: "same value" +Received : "same value"`) + }) }) }) - describe('message', () => { - let actual: string + describe('custom message', () => { + let actualFailureMessage: string + const customPrefixMessage = 'Test Message' beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Expected', - 'Test Actual', + actualFailureMessage = enhanceError( + 'window', + 'Test Expected Value', + 'Test Actual Value', { isNot: false }, - 'Test Verb', - 'Test Expectation', + 'have', + 'title', '', - { message: 'Test Message', containing: false } + { message: customPrefixMessage, containing: false } ) }) - test('starting message', () => { - expect(actual).toMatch('Test Message\nExpect Test Subject to Test Verb Test Expectation') - }) + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Test Message +Expect window to have title - test('diff string', () => { - const diffString = printDiffOrStringify('Test Expected', 'Test Actual', 'Expected', 'Received', true) - expect(actual).toMatch(diffString) +Expected: "Test Expected Value" +Received: "Test Actual Value"`) }) }) - describe('arg2', () => { - let actual: string + describe('Expected Value Argument 2', () => { + let actualFailureMessage: string + const expectedArg2 = 'myPropertyName' - beforeEach(() => { - actual = enhanceError( - 'Test Subject', - 'Test Expected', - 'Test Actual', - { isNot: false }, - 'Test Verb', - 'Test Expectation', - 'Test Arg2', - { message: 'Test Message', containing: false } - ) - }) + describe('isNot false', () => { + const expected = 'Expected Property Value' + const actual = 'Actual Property Value' + const isNot = false + + beforeEach(() => { + actualFailureMessage = enhanceError( + 'window', + expected, + actual, + { isNot }, + 'have', + 'property', + expectedArg2, + ) + }) - test('starting message', () => { - expect(actual).toMatch('Expect Test Subject to Test Verb Test Expectation Test Arg2') + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window to have property myPropertyName + +Expected: "Expected Property Value" +Received: "Actual Property Value"`) + }) }) - test('diff string', () => { - const diffString = printDiffOrStringify('Test Expected', 'Test Actual', 'Expected', 'Received', true) - expect(actual).toMatch(diffString) + describe('isNot true', () => { + const expected = 'Expected Property Value' + const actual = 'Actual Property Value' + const isNot = true + + beforeEach(() => { + actualFailureMessage = enhanceError( + 'window', + expected, + actual, + { isNot }, + 'have', + 'property', + expectedArg2, + ) + }) + + test('message', () => { + expect(actualFailureMessage).toEqual(`\ +Expect window not to have property myPropertyName + +Expected [not]: "Expected Property Value" +Received : "Actual Property Value"`) + }) }) }) }) - describe('numberError', () => { + describe(numberError, () => { test('should return correct message', () => { expect(numberError()).toBe('no params') expect(numberError({ eq: 0 })).toBe(0) @@ -173,4 +226,43 @@ describe('formatMessage', () => { expect(numberError({ gte: 2, lte: 1 })).toBe('>= 2 && <= 1') }) }) + + describe(enhanceErrorBe, () => { + const subject = 'element' + const verb = 'be' + const expectation = 'displayed' + const options = {} + + const isNot = false + test('when isNot is false', () => { + const message = enhanceErrorBe(subject, { isNot, verb, expectation }, options ) + expect(message).toEqual(`\ +Expect element to be displayed + +Expected: "displayed" +Received: "not displayed"`) + }) + + test('with custom message', () => { + const customMessage = 'Custom Error Message' + const message = enhanceErrorBe(subject, { isNot, verb, expectation }, { ...options, message: customMessage }) + expect(message).toEqual(`\ +Custom Error Message +Expect element to be displayed + +Expected: "displayed" +Received: "not displayed"`) + }) + + test('when isNot is true', () => { + const isNot = true + const message = enhanceErrorBe(subject, { isNot, verb, expectation }, options) + expect(message).toEqual(`\ +Expect element not to be displayed + +Expected: "not displayed" +Received: "displayed"`) + + }) + }) }) From dea015a8c1ee460cd1a6c348396f79bf79a8d0a2 Mon Sep 17 00:00:00 2001 From: dprevost-perso Date: Sun, 1 Feb 2026 08:08:53 -0500 Subject: [PATCH 2/2] Fix merge problem --- src/utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 038dadc98..d1637bfa8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -89,7 +89,7 @@ async function executeCommandBe( command: (el: WebdriverIO.Element) => Promise, options: ExpectWebdriverIO.CommandOptions ): ExpectWebdriverIO.AsyncAssertionResult { - const { isNot, expectation, verb = 'be' } = this + const { isNot, verb = 'be' } = this let el = await received?.getElement() const pass = await waitUntil( @@ -107,7 +107,6 @@ async function executeCommandBe( options ) - const { verb = 'be' } = this const message = enhanceErrorBe(el, { ...this, verb }, options) return {