From 12abae7f31dc408f7c960c592c386315071fa24e Mon Sep 17 00:00:00 2001 From: Ross Wollman Date: Fri, 1 Apr 2022 13:38:22 -0700 Subject: [PATCH] feat(test-runner): friendly expect errors for typos (#13229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you typo'd an `expect` property, you got a cryptic error message: ``` Uncaught TypeError: Cannot create proxy with a non-object as target or handler ``` Now we get this nice friendly message: ``` 1) a.spec.ts:6:9 › explodes ====================================================================== Error: expect: Property 'toBeLessThen' not found. Did you mean 'toBeLessThan'? See https://playwright.dev/docs/test-assertions for available options and documentation. 5 | const { test } = pwt; 6 | test('explodes', () => { > 7 | expect.soft(1).toBeLessThen(); | ^ 8 | }); 9 | ``` Fixes #13218 --- packages/playwright-test/src/expect.ts | 2 + packages/playwright-test/src/util.ts | 1 - tests/playwright-test/expect.spec.ts | 68 ++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) 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); + }); +});