diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index bd288ed04d..26c30b4c40 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -1406,7 +1406,7 @@ export class Frame extends SdkObject { // expect(locator).not.conditionThatDoesMatch progress.setIntermediateResult(result.received); if (!Array.isArray(result.received)) - progress.log(` unexpected value "${result.received}"`); + progress.log(` unexpected value "${progress.injectedScript.renderUnexpectedValue(options.expression, result.received)}"`); return progress.continuePolling; } diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 8e762d0226..c1c4200c9f 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -1205,6 +1205,30 @@ export class InjectedScript { throw this.createStacklessError('Unknown expect matcher: ' + expression); } + renderUnexpectedValue(expression: string, received: any): string { + if (expression === 'to.be.checked') + return received ? 'checked' : 'unchecked'; + if (expression === 'to.be.unchecked') + return received ? 'unchecked' : 'checked'; + if (expression === 'to.be.visible') + return received ? 'visible' : 'hidden'; + if (expression === 'to.be.hidden') + return received ? 'hidden' : 'visible'; + if (expression === 'to.be.enabled') + return received ? 'enabled' : 'disabled'; + if (expression === 'to.be.disabled') + return received ? 'disabled' : 'enabled'; + if (expression === 'to.be.editable') + return received ? 'editable' : 'readonly'; + if (expression === 'to.be.readonly') + return received ? 'readonly' : 'editable'; + if (expression === 'to.be.empty') + return received ? 'empty' : 'not empty'; + if (expression === 'to.be.focused') + return received ? 'focused' : 'not focused'; + return received; + } + expectArray(elements: Element[], options: FrameExpectParams): { matches: boolean, received?: any } { const expression = options.expression; diff --git a/tests/page/expect-boolean.spec.ts b/tests/page/expect-boolean.spec.ts index 92e1dfe776..8b9e325b5e 100644 --- a/tests/page/expect-boolean.spec.ts +++ b/tests/page/expect-boolean.spec.ts @@ -86,6 +86,16 @@ test.describe('toBeChecked', () => { }); } }); + + test('friendly log', async ({ page }) => { + await page.setContent(''); + const message1 = await expect(page.locator('input')).toBeChecked({ timeout: 1000 }).catch(e => e.message); + expect(message1).toContain('unexpected value "unchecked"'); + + await page.setContent(''); + const message2 = await expect(page.locator('input')).toBeChecked({ checked: false, timeout: 1000 }).catch(e => e.message); + expect(message2).toContain('unexpected value "checked"'); + }); }); test.describe('toBeEditable', () => {