diff --git a/packages/playwright-test/src/expect.ts b/packages/playwright-test/src/expect.ts index af2c055a82..05b0922f2f 100644 --- a/packages/playwright-test/src/expect.ts +++ b/packages/playwright-test/src/expect.ts @@ -168,6 +168,8 @@ class ExpectMetaInfoProxyHandler { get(target: any, prop: any, receiver: any): any { const value = Reflect.get(target, prop, receiver); + if (value === undefined) + throw new Error(`expect: Property '${prop}' not found.`); if (typeof value !== 'function') return new Proxy(value, this); return (...args: any[]) => { diff --git a/packages/playwright-test/src/util.ts b/packages/playwright-test/src/util.ts index 61d37b2e7e..32c130ff15 100644 --- a/packages/playwright-test/src/util.ts +++ b/packages/playwright-test/src/util.ts @@ -277,4 +277,3 @@ export function getPackageJsonPath(folderPath: string): string { folderToPackageJsonPath.set(folderPath, result); return result; } - diff --git a/tests/playwright-test/expect.spec.ts b/tests/playwright-test/expect.spec.ts index e3fd55b60c..b1cb90531c 100644 --- a/tests/playwright-test/expect.spec.ts +++ b/tests/playwright-test/expect.spec.ts @@ -233,3 +233,71 @@ test('should propose only the relevant matchers when custom expect matcher class }); expect(result.exitCode).toBe(0); }); + +test.describe('helpful expect errors', () => { + test('top-level', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + const { test } = pwt; + test('explodes', () => { + expect(1).nope(); + }); + ` + }); + + expect(result.output).toContain(`expect: Property 'nope' not found.`); + }); + + test('soft', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + const { test } = pwt; + test('explodes', () => { + expect.soft(1).nope(); + }); + ` + }); + + expect(result.output).toContain(`expect: Property 'nope' not found.`); + }); + + test('poll', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + const { test } = pwt; + test('explodes', () => { + expect.poll(() => {}).nope(); + }); + ` + }); + + expect(result.output).toContain(`expect: Property 'nope' not found.`); + }); + + test('not', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + const { test } = pwt; + test('explodes', () => { + expect(1).not.nope(); + }); + ` + }); + + expect(result.output).toContain(`expect: Property 'nope' not found.`); + }); + + test('bare', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + const { test } = pwt; + test('explodes', () => { + expect(''); + }); + ` + }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + }); +});