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', () => {