docs(test-assertions): optimize custom matcher to handle negative assertions efficiently (#35599)

This commit is contained in:
Marcin Szafranek 2025-04-14 21:07:01 +02:00 committed by GitHub
parent ac2d9e62da
commit b32a9a05e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 5 deletions

View File

@ -258,7 +258,7 @@ In this example we add a custom `toHaveAmount` function. Custom matcher should r
```js title="fixtures.ts" ```js title="fixtures.ts"
import { expect as baseExpect } from '@playwright/test'; import { expect as baseExpect } from '@playwright/test';
import type { Page, Locator } from '@playwright/test'; import type { Locator } from '@playwright/test';
export { test } from '@playwright/test'; export { test } from '@playwright/test';
@ -268,13 +268,18 @@ export const expect = baseExpect.extend({
let pass: boolean; let pass: boolean;
let matcherResult: any; let matcherResult: any;
try { try {
await baseExpect(locator).toHaveAttribute('data-amount', String(expected), options); const expectation = this.isNot ? baseExpect(locator).not : baseExpect(locator);
await expectation.toHaveAttribute('data-amount', String(expected), options);
pass = true; pass = true;
} catch (e: any) { } catch (e: any) {
matcherResult = e.matcherResult; matcherResult = e.matcherResult;
pass = false; pass = false;
} }
if (this.isNot) {
pass =!pass;
}
const message = pass const message = pass
? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) + ? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
'\n\n' + '\n\n' +

View File

@ -762,13 +762,18 @@ test('should chain expect matchers and expose matcher utils (TSC)', async ({ run
let pass: boolean; let pass: boolean;
let matcherResult: any; let matcherResult: any;
try { try {
await baseExpect(baseAmount).toHaveAttribute('data-amount', expected, options); const expectation = this.isNot ? baseExpect(baseAmount).not : baseExpect(baseAmount);
await expectation.toHaveAttribute('data-amount', expected, options);
pass = true; pass = true;
} catch (e: any) { } catch (e: any) {
matcherResult = e.matcherResult; matcherResult = e.matcherResult;
pass = false; pass = false;
} }
if (this.isNot) {
pass = !pass;
}
const expectOptions = { const expectOptions = {
isNot: this.isNot, isNot: this.isNot,
}; };
@ -842,13 +847,18 @@ test('should chain expect matchers and expose matcher utils', async ({ runInline
let pass: boolean; let pass: boolean;
let matcherResult: any; let matcherResult: any;
try { try {
await baseExpect(baseAmount).toHaveAttribute('data-amount', expected, options); const expectation = this.isNot ? baseExpect(baseAmount).not : baseExpect(baseAmount);
await expectation.toHaveAttribute('data-amount', expected, options);
pass = true; pass = true;
} catch (e: any) { } catch (e: any) {
matcherResult = e.matcherResult; matcherResult = e.matcherResult;
pass = false; pass = false;
} }
if (this.isNot) {
pass = !pass;
}
const expectOptions = { const expectOptions = {
isNot: this.isNot, isNot: this.isNot,
}; };
@ -888,7 +898,7 @@ test('should chain expect matchers and expose matcher utils', async ({ runInline
}, { workers: 1 }); }, { workers: 1 });
const output = stripAnsi(result.output); const output = stripAnsi(result.output);
expect(output).toContain(`await expect(page.locator('div')).toHaveAmount('3', { timeout: 1000 });`); expect(output).toContain(`await expect(page.locator('div')).toHaveAmount('3', { timeout: 1000 });`);
expect(output).toContain('a.spec.ts:60'); expect(output).toContain('a.spec.ts:65');
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });