Skip to content

Commit c147791

Browse files
committed
feat: add verify wrapper for playwright's expect
1 parent bbccdf9 commit c147791

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

run/test/utils/conversation_order.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { expect } from '@playwright/test';
2-
31
import { DeviceWrapper } from '../../types/DeviceWrapper';
2+
import { verify } from './utilities';
43

54
// Returns the names of all conversation list items in their current DOM order
65
export const getConversationOrder = async (device: DeviceWrapper): Promise<string[]> => {
@@ -27,5 +26,5 @@ export const assertPinOrder = (
2726
}
2827
const expected = [...pinnedExpected, ...unpinnedExpected];
2928

30-
expect(afterOrder, 'Conversation order is not correct').toEqual(expected);
29+
verify(afterOrder, 'Conversation order is not correct').toEqual(expected);
3130
};

run/test/utils/utilities.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { expect } from '@playwright/test';
12
import { exec as execNotPromised } from 'child_process';
23
import * as fs from 'fs';
34
import { pick } from 'lodash';
@@ -150,3 +151,44 @@ export async function forceStopAndRestart(device: DeviceWrapper): Promise<void>
150151
// Ensure we're on the home screen again
151152
await device.waitForTextElementToBePresent(new PlusButton(device));
152153
}
154+
155+
/**
156+
* Drop-in replacement for Playwright's `expect()` that keeps Allure reports clean.
157+
*
158+
* Playwright dumps the full diff (received vs expected) into the error message, which
159+
* ends up verbatim in Allure — too technical for customers. `verify()` catches
160+
* assertion errors and rethrows with only the human-readable `message`, preserving the diffs
161+
* in the runner logs.
162+
*
163+
* @param actual - The value being asserted
164+
* @param message - Business-readable failure message — this is all Allure will show on failure.
165+
*
166+
* @example
167+
* verify(messages, 'Conversation messages are in the wrong order').toEqual(expected);
168+
* verify(isVisible, 'Blocked user banner should not be visible').not.toBe(true);
169+
*/
170+
export function verify<T>(actual: T, message: string) {
171+
const matchers = expect(actual, message);
172+
173+
function wrapMatchers(obj: typeof matchers): typeof matchers {
174+
return new Proxy(obj, {
175+
get(target, prop: string | symbol) {
176+
const val = Reflect.get(target, prop, target);
177+
if (prop === 'not') return wrapMatchers(val as typeof matchers);
178+
if (typeof val === 'function') {
179+
return (...args: unknown[]) => {
180+
try {
181+
return (val as (...a: unknown[]) => unknown).apply(target, args);
182+
} catch {
183+
console.log(`${message}\n actual: `, actual, '\n expected:', args[0]);
184+
throw new Error(message);
185+
}
186+
};
187+
}
188+
return val;
189+
},
190+
});
191+
}
192+
193+
return wrapMatchers(matchers);
194+
}

run/types/DeviceWrapper.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Constraints, DefaultCreateSessionResult } from '@appium/types';
22

33
import { getImageOccurrence } from '@appium/opencv';
4-
import { expect, TestInfo } from '@playwright/test';
4+
import { TestInfo } from '@playwright/test';
55
import { AndroidUiautomator2Driver } from 'appium-uiautomator2-driver';
66
import { W3CUiautomator2DriverCaps } from 'appium-uiautomator2-driver/build/lib/types';
77
import { W3CXCUITestDriverCaps, XCUITestDriver } from 'appium-xcuitest-driver/build/lib/driver';
@@ -78,7 +78,7 @@ import { getAdbFullPath } from '../test/utils/binaries';
7878
import { parseDataImage } from '../test/utils/check_colour';
7979
import { isSameColor } from '../test/utils/check_colour';
8080
import { SupportedPlatformsType } from '../test/utils/open_app';
81-
import { isDeviceAndroid, isDeviceIOS, runScriptAndLog } from '../test/utils/utilities';
81+
import { isDeviceAndroid, isDeviceIOS, runScriptAndLog, verify } from '../test/utils/utilities';
8282
import { CTAConfig, ctaConfigs, CTAType } from './cta';
8383
import {
8484
AccessibilityId,
@@ -1887,7 +1887,7 @@ export class DeviceWrapper {
18871887
) {
18881888
const el = await this.waitForTextElementToBePresent(element);
18891889
const received = await this.getAttribute(attribute, el.ELEMENT);
1890-
expect(received, 'Element attribute value mismatch').toBe(value);
1890+
verify(received, 'Element attribute value mismatch').toBe(value);
18911891
}
18921892

18931893
public async disappearRadioButtonSelected(
@@ -2682,7 +2682,7 @@ export class DeviceWrapper {
26822682
for (let i = 0; i < SAMPLE_SIZE; i++) {
26832683
colors.add(await this.getElementPixelColor(locator));
26842684
}
2685-
expect(
2685+
verify(
26862686
colors.size,
26872687
`Expected element to be animated but detected 1 unique color: ${[...colors][0]}`
26882688
).toBeGreaterThan(1);

0 commit comments

Comments
 (0)