From 6b3da61c8ea064a30f7e27b9612956676ab0530e Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Tue, 11 May 2021 09:54:34 -0500 Subject: [PATCH 01/16] Ignore vscode folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b17578f..9612758 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,5 @@ dist # TernJS port file .tern-port -lib/ \ No newline at end of file +lib/ +.vscode/ From f7ebddbbbc00c259ad0aa322fd0011ed3690968e Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Tue, 11 May 2021 09:54:46 -0500 Subject: [PATCH 02/16] Add getMessage util --- src/matchers/utils.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index 9903751..a37ca8d 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -103,4 +103,24 @@ export const getElementText = async (...args: InputArguments): Promise `'${val}'` +export const quote = (val: string | null) => + val === null ? 'null' : `'${val}'` + +export const getMessage = ( + ctx: jest.MatcherContext, + matcher: string, + expected: string, + received: string +) => { + const not = ctx.isNot ? 'not ' : '' + const matcherHint = ctx.utils.matcherHint(matcher, undefined, undefined, { + isNot: ctx.isNot, + promise: ctx.promise, + }) + + return () => + matcherHint + + '\n\n' + + `Expected: ${not}${ctx.utils.printExpected(expected)}\n` + + `Received: ${ctx.utils.printReceived(received)}` +} From 2b0df098773a1a886a44a34bc69c9a63d45ce637 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Tue, 11 May 2021 09:55:18 -0500 Subject: [PATCH 03/16] Update matcher and snapshot --- .../__snapshots__/index.test.ts.snap | 9 +++--- src/matchers/toEqualText/index.test.ts | 32 +++++++++---------- src/matchers/toEqualText/index.ts | 18 ++++------- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap index d03b6c7..67f2aae 100644 --- a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap +++ b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap @@ -1,9 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`toEqualText selector negative 1`] = `"'not-existing' does not equal 'zzzBarzzz' of '#foobar'."`; +exports[`toEqualText selector negative 1`] = ` +"expect(received).toEqualText(expected) -exports[`toEqualText selector positive 1`] = `"'Bar' does equal 'Bar'."`; - -exports[`toEqualText selector positive frame 1`] = `"'Example Domain' does equal 'Example Domain'."`; +Expected: \\"'not-existing'\\" +Received: \\"'zzzBarzzz'\\"" +`; exports[`toEqualText selector timeout should throw an error after the timeout exceeds 1`] = `"Error: Timeout exceed for element '#foobar'"`; diff --git a/src/matchers/toEqualText/index.test.ts b/src/matchers/toEqualText/index.test.ts index d75f7e2..18b331a 100644 --- a/src/matchers/toEqualText/index.test.ts +++ b/src/matchers/toEqualText/index.test.ts @@ -2,40 +2,38 @@ import { testWrapper } from "../tests/utils" import toEqualText from '.' +expect.extend({ toEqualText }) + describe("toEqualText", () => { afterEach(async () => { await page.setContent('') }) - describe("selector", () => { + describe.only("selector", () => { it("positive frame", async () => { await page.setContent(``) const iframe = await page.$("iframe") - const result = await toEqualText(iframe!, "h1", "Example Domain") - expect(result.pass).toBe(true) - expect(result.message()).toMatchSnapshot() + await expect(iframe!).toEqualText('h1', 'Example Domain') }) it("positive", async () => { await page.setContent(`
Bar
`) - const result = await toEqualText(page, "#foobar", "Bar") - expect(result.pass).toBe(true) - expect(result.message()).toMatchSnapshot() + await expect(page).toEqualText("#foobar", "Bar") }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) - expect(testWrapper(await toEqualText(page, "#foobar", "not-existing"))).toThrowErrorMatchingSnapshot() + await expect(() => expect(page).toEqualText("#foobar", "not-existing")).rejects.toThrowErrorMatchingSnapshot() }) describe("timeout", () => { it("positive: should be able to use a custom timeout", async () => { setTimeout(async () => { await page.setContent(`
Bar
`) }, 500) - expect(testWrapper(await toEqualText(page, "#foobar", "Bar"))).toBe(true) + await expect(page).toEqualText("#foobar", "Bar") }) it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toEqualText(page, "#foobar", "Bar", { + await expect(() => expect(page).toEqualText("#foobar", "Bar", { timeout: 1 * 1000 - }))).toThrowErrorMatchingSnapshot() + })).rejects.toThrowErrorMatchingSnapshot() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) @@ -45,24 +43,24 @@ describe("toEqualText", () => { it("positive", async () => { await page.setContent(`
Bar
`) const element = await page.$("#foobar") - expect(element).not.toBe(null) - expect(testWrapper(await toEqualText(element!, "Bar"))).toBe(true) + expect(element).not.toBeNull() + await expect(element!).toEqualText("Bar") }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) const element = await page.$("#foobar") - expect(element).not.toBe(null) - expect(testWrapper(await toEqualText(element!, "not-existing"))).toThrowError() + expect(element).not.toBeNull() + await expect(() => expect(element!).toEqualText("not-existing")).rejects.toThrowError() }) }) describe("page", () => { it("positive", async () => { await page.setContent(`
Bar
`) - expect(testWrapper(await toEqualText(page, "Bar"))).toBe(true) + await expect(page).toEqualText("Bar") }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) - expect(testWrapper(await toEqualText(page, "not-existing"))).toThrowError() + await expect(() => expect(page).toEqualText("not-existing")).rejects.toThrowError() }) }) }) diff --git a/src/matchers/toEqualText/index.ts b/src/matchers/toEqualText/index.ts index c537fab..370449d 100644 --- a/src/matchers/toEqualText/index.ts +++ b/src/matchers/toEqualText/index.ts @@ -1,20 +1,14 @@ import { SyncExpectationResult } from 'expect/build/types' -import { getElementText, quote, InputArguments } from '../utils' +import { getElementText, quote, InputArguments, getMessage } from '../utils' -const toEqualText = async (...args: InputArguments): Promise => { +const toEqualText: jest.CustomMatcher = async function (...args: InputArguments): Promise { try { const { elementHandle, selector, expectedValue } = await getElementText(...args) - /* istanbul ignore next */ const actualTextContent = await elementHandle.evaluate((el) => el.textContent) - if (actualTextContent === expectedValue) { - return { - pass: true, - message: () => `${quote(expectedValue)} does equal ${quote(actualTextContent)}.` - } - } + return { - pass: false, - message: () => `${quote(expectedValue)} does not equal ${quote(actualTextContent)}${selector ? ' of ' + quote(selector) + "." : '.'}` + pass: actualTextContent === expectedValue, + message: getMessage(this, 'toEqualText', quote(expectedValue), quote(actualTextContent)), } } catch (err) { return { @@ -24,4 +18,4 @@ const toEqualText = async (...args: InputArguments): Promise Date: Wed, 12 May 2021 09:17:09 -0500 Subject: [PATCH 04/16] Better not --- .../__snapshots__/index.test.ts.snap | 11 ++++++++-- src/matchers/toEqualText/index.test.ts | 21 ++++++++++++++++--- src/matchers/toEqualText/index.ts | 6 +++--- src/matchers/utils.ts | 21 ++++++++++--------- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap index 67f2aae..a130e82 100644 --- a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap +++ b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap @@ -3,8 +3,15 @@ exports[`toEqualText selector negative 1`] = ` "expect(received).toEqualText(expected) -Expected: \\"'not-existing'\\" -Received: \\"'zzzBarzzz'\\"" +Expected: \\"not-existing\\" +Received: \\"zzzBarzzz\\"" +`; + +exports[`toEqualText selector not failure 1`] = ` +"expect(received).not.toEqualText(expected) + +Expected: not \\"Bar\\" +" `; exports[`toEqualText selector timeout should throw an error after the timeout exceeds 1`] = `"Error: Timeout exceed for element '#foobar'"`; diff --git a/src/matchers/toEqualText/index.test.ts b/src/matchers/toEqualText/index.test.ts index 18b331a..c2848cb 100644 --- a/src/matchers/toEqualText/index.test.ts +++ b/src/matchers/toEqualText/index.test.ts @@ -1,5 +1,3 @@ -import { testWrapper } from "../tests/utils" - import toEqualText from '.' expect.extend({ toEqualText }) @@ -8,7 +6,7 @@ describe("toEqualText", () => { afterEach(async () => { await page.setContent('') }) - describe.only("selector", () => { + describe("selector", () => { it("positive frame", async () => { await page.setContent(``) const iframe = await page.$("iframe") @@ -22,6 +20,23 @@ describe("toEqualText", () => { await page.setContent(`
zzzBarzzz
`) await expect(() => expect(page).toEqualText("#foobar", "not-existing")).rejects.toThrowErrorMatchingSnapshot() }) + + describe('not', () => { + it("success in frame", async () => { + await page.setContent(``) + const iframe = await page.$("iframe") + await expect(iframe!).not.toEqualText('h1', 'Foo') + }) + it("success", async () => { + await page.setContent(`
Bar
`) + await expect(page).not.toEqualText("#foobar", "Foo") + }) + it("failure", async () => { + await page.setContent(`
Bar
`) + await expect(() => expect(page).not.toEqualText("#foobar", "Bar")).rejects.toThrowErrorMatchingSnapshot() + }) + }) + describe("timeout", () => { it("positive: should be able to use a custom timeout", async () => { setTimeout(async () => { diff --git a/src/matchers/toEqualText/index.ts b/src/matchers/toEqualText/index.ts index 370449d..a035b66 100644 --- a/src/matchers/toEqualText/index.ts +++ b/src/matchers/toEqualText/index.ts @@ -1,14 +1,14 @@ import { SyncExpectationResult } from 'expect/build/types' -import { getElementText, quote, InputArguments, getMessage } from '../utils' +import { getElementText, getMessage, InputArguments } from '../utils' const toEqualText: jest.CustomMatcher = async function (...args: InputArguments): Promise { try { - const { elementHandle, selector, expectedValue } = await getElementText(...args) + const { elementHandle, expectedValue } = await getElementText(...args) const actualTextContent = await elementHandle.evaluate((el) => el.textContent) return { pass: actualTextContent === expectedValue, - message: getMessage(this, 'toEqualText', quote(expectedValue), quote(actualTextContent)), + message: getMessage(this, 'toEqualText', expectedValue, actualTextContent), } } catch (err) { return { diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index a37ca8d..f74913e 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -109,18 +109,19 @@ export const quote = (val: string | null) => export const getMessage = ( ctx: jest.MatcherContext, matcher: string, - expected: string, - received: string -) => { - const not = ctx.isNot ? 'not ' : '' + expected: string | null, + received: string | null +) => () => { const matcherHint = ctx.utils.matcherHint(matcher, undefined, undefined, { isNot: ctx.isNot, promise: ctx.promise, - }) + }) + '\n\n' - return () => - matcherHint + - '\n\n' + - `Expected: ${not}${ctx.utils.printExpected(expected)}\n` + - `Received: ${ctx.utils.printReceived(received)}` + if (ctx.isNot) { + return matcherHint + `Expected: not ${ctx.utils.printExpected(expected)}\n` + } else { + return matcherHint + + `Expected: ${ctx.utils.printExpected(expected)}\n` + + `Received: ${ctx.utils.printReceived(received)}` + } } From e0000e2f67a8d1eb861504fc54d7b388b0a8760d Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Wed, 12 May 2021 09:17:47 -0500 Subject: [PATCH 05/16] Improve test messages --- src/matchers/toEqualText/index.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/matchers/toEqualText/index.test.ts b/src/matchers/toEqualText/index.test.ts index c2848cb..2622646 100644 --- a/src/matchers/toEqualText/index.test.ts +++ b/src/matchers/toEqualText/index.test.ts @@ -38,7 +38,7 @@ describe("toEqualText", () => { }) describe("timeout", () => { - it("positive: should be able to use a custom timeout", async () => { + it("success with a custom timeout", async () => { setTimeout(async () => { await page.setContent(`
Bar
`) }, 500) @@ -55,13 +55,13 @@ describe("toEqualText", () => { }) }) describe("element", () => { - it("positive", async () => { + it("success", async () => { await page.setContent(`
Bar
`) const element = await page.$("#foobar") expect(element).not.toBeNull() await expect(element!).toEqualText("Bar") }) - it("negative", async () => { + it("failure", async () => { await page.setContent(`
zzzBarzzz
`) const element = await page.$("#foobar") expect(element).not.toBeNull() @@ -69,11 +69,11 @@ describe("toEqualText", () => { }) }) describe("page", () => { - it("positive", async () => { + it("success", async () => { await page.setContent(`
Bar
`) await expect(page).toEqualText("Bar") }) - it("negative", async () => { + it("failure", async () => { await page.setContent(`
zzzBarzzz
`) await expect(() => expect(page).toEqualText("not-existing")).rejects.toThrowError() }) From 94a7808467064bfc045b47b0c70c11db27911ad4 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Wed, 12 May 2021 10:46:40 -0500 Subject: [PATCH 06/16] Merge branch 'master' into improve-matcher-hints --- .github/workflows/nodejs.yml | 43 ++--- .prettierignore | 2 + .prettierrc | 3 + README.md | 26 +-- global.d.ts | 80 ++++++---- jest.config.js | 10 +- package-lock.json | 149 +++++++++++------- package.json | 13 +- src/index.test.ts | 24 +-- src/index.ts | 39 +++-- src/matchers/index.ts | 14 +- src/matchers/tests/utils.ts | 8 +- src/matchers/toEqualText/index.test.ts | 29 ++-- src/matchers/toEqualText/index.ts | 21 ++- src/matchers/toEqualUrl/index.test.ts | 14 +- src/matchers/toEqualUrl/index.ts | 18 ++- src/matchers/toEqualValue/index.test.ts | 24 ++- src/matchers/toEqualValue/index.ts | 28 ++-- src/matchers/toHaveFocus/index.test.ts | 34 ++-- src/matchers/toHaveFocus/index.ts | 25 +-- src/matchers/toHaveSelector/index.test.ts | 36 +++-- src/matchers/toHaveSelector/index.ts | 20 ++- .../toHaveSelectorCount/index.test.ts | 22 ++- src/matchers/toHaveSelectorCount/index.ts | 29 ++-- src/matchers/toHaveText/index.test.ts | 40 +++-- src/matchers/toHaveText/index.ts | 26 ++- src/matchers/utils.test.ts | 12 +- src/matchers/utils.ts | 30 ++-- tsconfig.json | 6 +- 29 files changed, 514 insertions(+), 311 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 64f64f6..93c0db3 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,29 +1,30 @@ name: Node.js CI on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: | - sudo apt update - # chromium dependencies - sudo apt-get install libgbm1 - - name: Use Node.js - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm ci - - name: Lint - run: | - yarn run tsc --noEmit - - run: npm run build - - run: npm test - - run: npx codecov - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - uses: actions/checkout@v2 + - name: Install dependencies + run: | + sudo apt update + # chromium dependencies + npx playwright-chromium install-deps chromium + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm ci + - name: Lint + run: | + npx tsc --noEmit + npx prettier --check . + - run: npm run build + - run: npm test + - run: npx codecov + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..64be67e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +coverage/ +lib/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..cce9d3c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "semi": false +} diff --git a/README.md b/README.md index 65d4c09..c1f0b8d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ To activate it in your Jest environment you have to include it in your configura ```json { - "setupFilesAfterEnv": ["expect-playwright"] + "setupFilesAfterEnv": ["expect-playwright"] } ``` @@ -39,7 +39,7 @@ Example which should wait and compare the text content of a paragraph on the pag ```javascript // before await page.waitForSelector("#foo") -const textContent = await page.$eval("#foo", el => el.textContent) +const textContent = await page.$eval("#foo", (el) => el.textContent) expect(textContent).stringContaining("my text") // after by using expect-playwright @@ -68,7 +68,7 @@ This function waits as a maximum as the timeout exceeds for a given selector onc await expect(page).toHaveSelector("#foobar") // or via not, useful to only wait 1 second instead of for the default timeout by Playwright which is 30 seconds. await expect(page).not.toHaveSelector("#foobar", { - timeout: 1 * 1000 + timeout: 1 * 1000, }) ``` @@ -82,7 +82,7 @@ This function checks if the given selector has focus. await expect(page).toHaveFocus("#foobar") // or via not, useful to only wait 1 second instead of for the default timeout by Playwright which is 30 seconds. await expect(page).not.toHaveFocus("#foobar", { - timeout: 1 * 1000 + timeout: 1 * 1000, }) ``` @@ -131,7 +131,7 @@ Or by passing a Playwright [ElementHandle]: **expect(element: [ElementHandle]).toHaveText(value: string)** ```javascript -const element = await page.$('#my-element'); +const element = await page.$("#my-element") await expect(element).toHaveText("Playwright") ``` @@ -160,7 +160,7 @@ Or by passing a Playwright [ElementHandle]: **expect(element: [ElementHandle]).toEqualText(value: string, options?: [PageWaitForSelectorOptions](https://playwright.dev/docs/api/class-page/#pagewaitforselectorselector-options))** ```javascript -const element = await page.$('#my-element'); +const element = await page.$("#my-element") await expect(element).toEqualText("Playwright") ``` @@ -181,14 +181,14 @@ Or by passing a Playwright [ElementHandle]: **expect(element: [ElementHandle]).toEqualValue(value: string, options?: [PageWaitForSelectorOptions](https://playwright.dev/docs/api/class-page/#pagewaitforselectorselector-options))** ```javascript -const element = await page.$('#my-element'); +const element = await page.$("#my-element") await expect(element).toEqualValue("Playwright") ``` ## Examples ```typescript -import playwright from 'playwright-chromium' +import playwright from "playwright-chromium" describe("GitHub Playwright project", () => { it("should should have Playwright in the README heading", async () => { @@ -197,7 +197,9 @@ describe("GitHub Playwright project", () => { await page.goto("https://github.com/microsoft/playwright") await expect(page).toHaveText("#readme h1", "Playwright") // or also all of them via the not property - await expect(page).not.toHaveText("this-is-no-anywhere", { timeout: 1 * 1000 }) + await expect(page).not.toHaveText("this-is-no-anywhere", { + timeout: 1 * 1000, + }) await browser.close() }) }) @@ -217,6 +219,6 @@ at the top of your test file or include it globally in your `tsconfig.json`. - [expect-puppeteer](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/expect-puppeteer) -[ElementHandle]: https://github.com/microsoft/playwright/blob/master/docs/api.md#class-elementhandle -[Page]: https://github.com/microsoft/playwright/blob/master/docs/api.md#class-page -[Playwright]: https://github.com/microsoft/Playwright +[elementhandle]: https://github.com/microsoft/playwright/blob/master/docs/api.md#class-elementhandle +[page]: https://github.com/microsoft/playwright/blob/master/docs/api.md#class-page +[playwright]: https://github.com/microsoft/Playwright diff --git a/global.d.ts b/global.d.ts index ad64e9b..5cc744d 100644 --- a/global.d.ts +++ b/global.d.ts @@ -9,7 +9,7 @@ interface PageWaitForSelectorOptions { * - `'hidden'` - wait for element to be either detached from DOM, or have an empty bounding box or `visibility:hidden`. * This is opposite to the `'visible'` option. */ - state?: "attached" | "detached" | "visible" | "hidden"; + state?: "attached" | "detached" | "visible" | "hidden" /** * Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by @@ -18,55 +18,77 @@ interface PageWaitForSelectorOptions { * or [page.setDefaultTimeout(…)](https://github.com/microsoft/playwright/blob/master/docs/api.md#pagesetdefaulttimeout) * methods. */ - timeout?: number; + timeout?: number } export interface PlaywrightMatchers { /** - * Will check if the element's textContent on the page determined by the selector includes the given text. - */ - toHaveText(selector: string, value: string, options?: PageWaitForSelectorOptions): Promise; + * Will check if the element's textContent on the page determined by the selector includes the given text. + */ + toHaveText( + selector: string, + value: string, + options?: PageWaitForSelectorOptions + ): Promise /** - * Will check if the element's value includes the given text. - */ - toHaveText(value: string): Promise; + * Will check if the element's value includes the given text. + */ + toHaveText(value: string): Promise /** - * Will compare the element's textContent on the page determined by the selector with the given text. - */ - toEqualText(selector: string, value: string, options?: PageWaitForSelectorOptions): Promise; + * Will compare the element's textContent on the page determined by the selector with the given text. + */ + toEqualText( + selector: string, + value: string, + options?: PageWaitForSelectorOptions + ): Promise /** - * Will compare the element's textContent by the given text. - */ - toEqualText(value: string, options?: PageWaitForSelectorOptions): Promise; + * Will compare the element's textContent by the given text. + */ + toEqualText(value: string, options?: PageWaitForSelectorOptions): Promise /** - * Will ensure that the element is on the page. - */ - toHaveSelector(selector: string, options?: PageWaitForSelectorOptions): Promise; + * Will ensure that the element is on the page. + */ + toHaveSelector( + selector: string, + options?: PageWaitForSelectorOptions + ): Promise /** * Will ensure that the element has focus. */ - toHaveFocus(selector: string, options?: PageWaitForSelectorOptions): Promise; + toHaveFocus( + selector: string, + options?: PageWaitForSelectorOptions + ): Promise /** * Will assert that N elements with the given selector are on the page and wait for it by default. * If its 0 elements, then it will throw since the element can't be found. */ - toHaveSelectorCount(selector: string, count: number, options?: PageWaitForSelectorOptions): Promise; + toHaveSelectorCount( + selector: string, + count: number, + options?: PageWaitForSelectorOptions + ): Promise /** - * Will compare the element's value on the page determined by the selector with the given value. - */ - toEqualValue(selector: string, value: string, options?: PageWaitForSelectorOptions): Promise; + * Will compare the element's value on the page determined by the selector with the given value. + */ + toEqualValue( + selector: string, + value: string, + options?: PageWaitForSelectorOptions + ): Promise /** - * Will compare element's value with the given value. - */ - toEqualValue(value: string, options?: PageWaitForSelectorOptions): Promise; + * Will compare element's value with the given value. + */ + toEqualValue(value: string, options?: PageWaitForSelectorOptions): Promise /** - * Will assert the given URL with the page's URL - */ - toEqualUrl(value: string): Promise; + * Will assert the given URL with the page's URL + */ + toEqualUrl(value: string): Promise } declare global { namespace jest { - interface Matchers extends PlaywrightMatchers { } + interface Matchers extends PlaywrightMatchers {} } } diff --git a/jest.config.js b/jest.config.js index 5d1d51d..7e0d8d3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,10 +1,10 @@ module.exports = { - preset: 'jest-playwright-preset', - testMatch: ['**/src/**/*.test.ts'], + preset: "jest-playwright-preset", + testMatch: ["**/src/**/*.test.ts"], collectCoverage: true, collectCoverageFrom: ["**/src/**/*.ts", "!**/tests/*"], transform: { - "^.+\\.ts$": "ts-jest" + "^.+\\.ts$": "ts-jest", }, - setupFilesAfterEnv: ["/lib/index.js"] -}; \ No newline at end of file + setupFilesAfterEnv: ["/lib/index.js"], +} diff --git a/package-lock.json b/package-lock.json index cba933d..2ccca62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,17 +8,18 @@ "version": "0.3.4", "license": "MIT", "devDependencies": { - "@types/jest": "^26.0.22", - "@types/node": "^14.14.41", + "@types/jest": "^26.0.23", + "@types/node": "^15.0.2", "jest": "^26.6.3", "jest-playwright-preset": "^1.5.1", - "playwright-chromium": "^1.10.0", - "playwright-core": "^1.10.0", - "ts-jest": "^26.5.5", + "playwright-chromium": "^1.11.0", + "playwright-core": "^1.11.0", + "prettier": "^2.3.0", + "ts-jest": "^26.5.6", "typescript": "^4.2.4" }, "peerDependencies": { - "playwright-core": "^1.10.0" + "playwright-core": "^1.11.0" } }, "node_modules/@babel/code-frame": { @@ -837,9 +838,9 @@ } }, "node_modules/@types/jest": { - "version": "26.0.22", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.22.tgz", - "integrity": "sha512-eeWwWjlqxvBxc4oQdkueW5OF/gtfSceKk4OnOAGlUSwS/liBRtZppbJuz1YkgbrbfGOoeBHun9fOvXnjNwrSOw==", + "version": "26.0.23", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.23.tgz", + "integrity": "sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA==", "dev": true, "dependencies": { "jest-diff": "^26.0.0", @@ -847,9 +848,9 @@ } }, "node_modules/@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", + "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -2853,9 +2854,9 @@ } }, "node_modules/hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/html-encoding-sniffer": { @@ -4326,9 +4327,9 @@ } }, "node_modules/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.flattendeep": { @@ -5036,9 +5037,9 @@ } }, "node_modules/playwright-chromium": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.10.0.tgz", - "integrity": "sha512-ry/60/YKGJfrnaS7j5C3+xmA2DAMv6pBE351FoTHe4Llq0WU92IL0rBYK3TkK3PzSHYtp1KdCRsRjDnJhImA3g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.11.0.tgz", + "integrity": "sha512-CNV58vXoyItAXOuK9rgyESBmnwVMnQg12TBJEDq1IksJo9m2Gi1maReiMOOJAFduMhicvLGgRsQfdzm44KCcxA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -5054,13 +5055,14 @@ "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "stack-utils": "^2.0.3", - "ws": "^7.3.1" + "ws": "^7.3.1", + "yazl": "^2.5.1" }, "bin": { "playwright": "lib/cli/cli.js" }, "engines": { - "node": ">=10.17.0" + "node": ">=12" } }, "node_modules/playwright-chromium/node_modules/commander": { @@ -5073,9 +5075,9 @@ } }, "node_modules/playwright-core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.10.0.tgz", - "integrity": "sha512-SDA5KPwnJJSfnNX/b7h8y0ChwBmcbbcCofYXkZGMVuzXZsmHPGLOBRhgkwN2nzJ10Ezf4cd1OcVOeOLKPxjeRg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.11.0.tgz", + "integrity": "sha512-P5+FzindrR0wI48WVRBiJ59D1wgladPA7KzODAC+EZkwlrCQ6Pj2L0JkrKMCst/3g/x/nSLYcM+QXk2O3HJ/VQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -5091,13 +5093,14 @@ "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "stack-utils": "^2.0.3", - "ws": "^7.3.1" + "ws": "^7.3.1", + "yazl": "^2.5.1" }, "bin": { "playwright": "lib/cli/cli.js" }, "engines": { - "node": ">=10.17.0" + "node": ">=12" } }, "node_modules/playwright-core/node_modules/commander": { @@ -5136,6 +5139,18 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -6421,9 +6436,9 @@ } }, "node_modules/ts-jest": { - "version": "26.5.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.5.tgz", - "integrity": "sha512-7tP4m+silwt1NHqzNRAPjW1BswnAhopTdc2K3HEkRZjF0ZG2F/e/ypVH0xiZIMfItFtD3CX0XFbwPzp9fIEUVg==", + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -6999,6 +7014,15 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } } }, "dependencies": { @@ -7750,9 +7774,9 @@ } }, "@types/jest": { - "version": "26.0.22", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.22.tgz", - "integrity": "sha512-eeWwWjlqxvBxc4oQdkueW5OF/gtfSceKk4OnOAGlUSwS/liBRtZppbJuz1YkgbrbfGOoeBHun9fOvXnjNwrSOw==", + "version": "26.0.23", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.23.tgz", + "integrity": "sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA==", "dev": true, "requires": { "jest-diff": "^26.0.0", @@ -7760,9 +7784,9 @@ } }, "@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", + "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", "dev": true }, "@types/normalize-package-data": { @@ -9377,9 +9401,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-encoding-sniffer": { @@ -10565,9 +10589,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.flattendeep": { @@ -11127,9 +11151,9 @@ } }, "playwright-chromium": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.10.0.tgz", - "integrity": "sha512-ry/60/YKGJfrnaS7j5C3+xmA2DAMv6pBE351FoTHe4Llq0WU92IL0rBYK3TkK3PzSHYtp1KdCRsRjDnJhImA3g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.11.0.tgz", + "integrity": "sha512-CNV58vXoyItAXOuK9rgyESBmnwVMnQg12TBJEDq1IksJo9m2Gi1maReiMOOJAFduMhicvLGgRsQfdzm44KCcxA==", "dev": true, "requires": { "commander": "^6.1.0", @@ -11144,7 +11168,8 @@ "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "stack-utils": "^2.0.3", - "ws": "^7.3.1" + "ws": "^7.3.1", + "yazl": "^2.5.1" }, "dependencies": { "commander": { @@ -11156,9 +11181,9 @@ } }, "playwright-core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.10.0.tgz", - "integrity": "sha512-SDA5KPwnJJSfnNX/b7h8y0ChwBmcbbcCofYXkZGMVuzXZsmHPGLOBRhgkwN2nzJ10Ezf4cd1OcVOeOLKPxjeRg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.11.0.tgz", + "integrity": "sha512-P5+FzindrR0wI48WVRBiJ59D1wgladPA7KzODAC+EZkwlrCQ6Pj2L0JkrKMCst/3g/x/nSLYcM+QXk2O3HJ/VQ==", "dev": true, "requires": { "commander": "^6.1.0", @@ -11173,7 +11198,8 @@ "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "stack-utils": "^2.0.3", - "ws": "^7.3.1" + "ws": "^7.3.1", + "yazl": "^2.5.1" }, "dependencies": { "commander": { @@ -11202,6 +11228,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + }, "pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -12259,9 +12291,9 @@ "dev": true }, "ts-jest": { - "version": "26.5.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.5.tgz", - "integrity": "sha512-7tP4m+silwt1NHqzNRAPjW1BswnAhopTdc2K3HEkRZjF0ZG2F/e/ypVH0xiZIMfItFtD3CX0XFbwPzp9fIEUVg==", + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -12728,6 +12760,15 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } } } } diff --git a/package.json b/package.json index 364b0d8..94bead0 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,17 @@ "test": "jest" }, "peerDependencies": { - "playwright-core": "^1.10.0" + "playwright-core": "^1.11.0" }, "devDependencies": { - "@types/jest": "^26.0.22", - "@types/node": "^14.14.41", + "@types/jest": "^26.0.23", + "@types/node": "^15.0.2", "jest": "^26.6.3", "jest-playwright-preset": "^1.5.1", - "playwright-chromium": "^1.10.0", - "playwright-core": "^1.10.0", - "ts-jest": "^26.5.5", + "playwright-chromium": "^1.11.0", + "playwright-core": "^1.11.0", + "prettier": "^2.3.0", + "ts-jest": "^26.5.6", "typescript": "^4.2.4" } } diff --git a/src/index.test.ts b/src/index.test.ts index 7db94fb..94fe597 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,10 +1,10 @@ -import matchers from './matchers'; +import matchers from "./matchers" import expectPlaywright from "." describe("expect-playwright", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) it("should apply the functions", () => { for (let matcher in matchers) { @@ -24,7 +24,7 @@ describe("expect-playwright", () => { describe("expectPlaywright", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) describe("should be able to handle positive cases", () => { it("return right result for page and 2 arguments", async () => { @@ -33,24 +33,30 @@ describe("expectPlaywright", () => { }) it("return right result for page and 3 arguments", async () => { await page.setContent(`
zzzBarzzz
`) - expect(await expectPlaywright(page).toHaveText("#bar", "zzzBarzzz")).toBe(true) + expect(await expectPlaywright(page).toHaveText("#bar", "zzzBarzzz")).toBe( + true + ) }) it("return right result for element and 2 arguments", async () => { await page.setContent(`
zzzFoozzz
`) - const elem = await page.$('#foo') + const elem = await page.$("#foo") expect(await expectPlaywright(elem!).toHaveText("zzzFoozzz")).toBe(true) }) }) describe("should be able to handle negative cases", () => { it("return right result for page and 2 arguments", async () => { await page.setContent(`
zzzzz
`) - await expect(expectPlaywright(page).toHaveText("zzzBarzzz")).rejects.toThrowErrorMatchingSnapshot() + await expect( + expectPlaywright(page).toHaveText("zzzBarzzz") + ).rejects.toThrowErrorMatchingSnapshot() }) it("return right result for page and 4 arguments", async () => { await page.setContent(`
zzzBarzzz
`) - await expect(expectPlaywright(page).toHaveText("#bar", "zzzBarzzz", { - timeout: 1* 1000 - })).rejects.toThrowErrorMatchingSnapshot() + await expect( + expectPlaywright(page).toHaveText("#bar", "zzzBarzzz", { + timeout: 1 * 1000, + }) + ).rejects.toThrowErrorMatchingSnapshot() }) }) }) diff --git a/src/index.ts b/src/index.ts index 8d3f075..f94109d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,24 +1,29 @@ -import matchers from './matchers'; -import type { Page, ElementHandle } from 'playwright-core'; -import type { PlaywrightMatchers } from '../global' +import matchers from "./matchers" +import type { Page, ElementHandle } from "playwright-core" +import type { PlaywrightMatchers } from "../global" // @ts-ignore -if (typeof global.expect !== 'undefined') { +if (typeof global.expect !== "undefined") { // @ts-ignore - global.expect.extend(matchers); + global.expect.extend(matchers) } -const expectWrapper = (pageOrElement: Page | ElementHandle): PlaywrightMatchers => - Object.entries(matchers).reduce((acc, [name, matcher]) => ({ - ...acc, - [name]: async (...args: any[]) => { - // @ts-ignore - const result = await matcher(pageOrElement, ...args) - if (!result.pass) { - throw new Error(result.message()) - } - return true - } - }), {} as PlaywrightMatchers) +const expectWrapper = ( + pageOrElement: Page | ElementHandle +): PlaywrightMatchers => + Object.entries(matchers).reduce( + (acc, [name, matcher]) => ({ + ...acc, + [name]: async (...args: any[]) => { + // @ts-ignore + const result = await matcher(pageOrElement, ...args) + if (!result.pass) { + throw new Error(result.message()) + } + return true + }, + }), + {} as PlaywrightMatchers + ) export = expectWrapper diff --git a/src/matchers/index.ts b/src/matchers/index.ts index 61da8ed..7a2e13c 100644 --- a/src/matchers/index.ts +++ b/src/matchers/index.ts @@ -1,10 +1,10 @@ -import toHaveText from './toHaveText' -import toEqualText from './toEqualText' -import toHaveSelector from './toHaveSelector' -import toEqualValue from './toEqualValue' -import toHaveSelectorCount from './toHaveSelectorCount' -import toEqualUrl from './toEqualUrl' -import toHaveFocus from './toHaveFocus' +import toHaveText from "./toHaveText" +import toEqualText from "./toEqualText" +import toHaveSelector from "./toHaveSelector" +import toEqualValue from "./toEqualValue" +import toHaveSelectorCount from "./toHaveSelectorCount" +import toEqualUrl from "./toEqualUrl" +import toHaveFocus from "./toHaveFocus" export default { toHaveText, diff --git a/src/matchers/tests/utils.ts b/src/matchers/tests/utils.ts index d01ba33..13299e0 100644 --- a/src/matchers/tests/utils.ts +++ b/src/matchers/tests/utils.ts @@ -1,4 +1,4 @@ -import { SyncExpectationResult } from 'expect/build/types' +import { SyncExpectationResult } from "expect/build/types" export const testWrapper = (result: SyncExpectationResult) => { if (result.pass) { @@ -7,4 +7,8 @@ export const testWrapper = (result: SyncExpectationResult) => { return () => { throw new Error(result.message()) } -} \ No newline at end of file +} + +export const assertSnapshot = async (fn: () => Promise) => { + await expect(fn).rejects.toThrowErrorMatchingSnapshot() +} diff --git a/src/matchers/toEqualText/index.test.ts b/src/matchers/toEqualText/index.test.ts index 2622646..63dbe2a 100644 --- a/src/matchers/toEqualText/index.test.ts +++ b/src/matchers/toEqualText/index.test.ts @@ -1,16 +1,17 @@ -import toEqualText from '.' +import toEqualText from "." +import { assertSnapshot } from "../tests/utils" expect.extend({ toEqualText }) describe("toEqualText", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) describe("selector", () => { it("positive frame", async () => { await page.setContent(``) const iframe = await page.$("iframe") - await expect(iframe!).toEqualText('h1', 'Example Domain') + await expect(iframe!).toEqualText("h1", "Example Domain") }) it("positive", async () => { await page.setContent(`
Bar
`) @@ -18,14 +19,13 @@ describe("toEqualText", () => { }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) - await expect(() => expect(page).toEqualText("#foobar", "not-existing")).rejects.toThrowErrorMatchingSnapshot() + await assertSnapshot(() => expect(page).toEqualText("#foobar", "Bar")) }) - - describe('not', () => { + describe("not", () => { it("success in frame", async () => { await page.setContent(``) const iframe = await page.$("iframe") - await expect(iframe!).not.toEqualText('h1', 'Foo') + await expect(iframe!).not.toEqualText("h1", "Foo") }) it("success", async () => { await page.setContent(`
Bar
`) @@ -33,10 +33,11 @@ describe("toEqualText", () => { }) it("failure", async () => { await page.setContent(`
Bar
`) - await expect(() => expect(page).not.toEqualText("#foobar", "Bar")).rejects.toThrowErrorMatchingSnapshot() + await assertSnapshot(() => + expect(page).not.toEqualText("#foobar", "Bar") + ) }) }) - describe("timeout", () => { it("success with a custom timeout", async () => { setTimeout(async () => { @@ -46,9 +47,9 @@ describe("toEqualText", () => { }) it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - await expect(() => expect(page).toEqualText("#foobar", "Bar", { - timeout: 1 * 1000 - })).rejects.toThrowErrorMatchingSnapshot() + await assertSnapshot(() => + expect(page).toEqualText("#foobar", "Bar", { timeout: 1 * 1000 }) + ) const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) @@ -65,7 +66,7 @@ describe("toEqualText", () => { await page.setContent(`
zzzBarzzz
`) const element = await page.$("#foobar") expect(element).not.toBeNull() - await expect(() => expect(element!).toEqualText("not-existing")).rejects.toThrowError() + await assertSnapshot(() => expect(element!).toEqualText("not-existing")) }) }) describe("page", () => { @@ -75,7 +76,7 @@ describe("toEqualText", () => { }) it("failure", async () => { await page.setContent(`
zzzBarzzz
`) - await expect(() => expect(page).toEqualText("not-existing")).rejects.toThrowError() + await assertSnapshot(() => expect(page).toEqualText("not-existing")) }) }) }) diff --git a/src/matchers/toEqualText/index.ts b/src/matchers/toEqualText/index.ts index a035b66..5a97f7b 100644 --- a/src/matchers/toEqualText/index.ts +++ b/src/matchers/toEqualText/index.ts @@ -1,19 +1,28 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { getElementText, getMessage, InputArguments } from '../utils' +import { SyncExpectationResult } from "expect/build/types" +import { getElementText, getMessage, InputArguments } from "../utils" -const toEqualText: jest.CustomMatcher = async function (...args: InputArguments): Promise { +const toEqualText: jest.CustomMatcher = async function ( + ...args: InputArguments +): Promise { try { const { elementHandle, expectedValue } = await getElementText(...args) - const actualTextContent = await elementHandle.evaluate((el) => el.textContent) + const actualTextContent = await elementHandle.evaluate( + (el) => el.textContent + ) return { pass: actualTextContent === expectedValue, - message: getMessage(this, 'toEqualText', expectedValue, actualTextContent), + message: getMessage( + this, + "toEqualText", + expectedValue, + actualTextContent + ), } } catch (err) { return { pass: false, - message: () => err.toString() + message: () => err.toString(), } } } diff --git a/src/matchers/toEqualUrl/index.test.ts b/src/matchers/toEqualUrl/index.test.ts index 650064a..023210b 100644 --- a/src/matchers/toEqualUrl/index.test.ts +++ b/src/matchers/toEqualUrl/index.test.ts @@ -1,13 +1,13 @@ -import toEqualUrl from '.' +import toEqualUrl from "." describe("toEqualUrl", () => { it("should return true if it matches the Url", async () => { - await page.route("**/1.html", route => { + await page.route("**/1.html", (route) => { route.fulfill({ body: "123", headers: { - "Content-Type": "text/html" - } + "Content-Type": "text/html", + }, }) }) const myUrl = "http://i-do-not-exist.com/1.html" @@ -17,12 +17,12 @@ describe("toEqualUrl", () => { expect(result.message()).toMatchSnapshot() }) it("should return false if it does not match the Url", async () => { - await page.route("**/1.html", route => { + await page.route("**/1.html", (route) => { route.fulfill({ body: "123", headers: { - "Content-Type": "text/html" - } + "Content-Type": "text/html", + }, }) }) await page.goto("http://i-do-not-exist.com/1.html") diff --git a/src/matchers/toEqualUrl/index.ts b/src/matchers/toEqualUrl/index.ts index 5c79cbb..de807b7 100644 --- a/src/matchers/toEqualUrl/index.ts +++ b/src/matchers/toEqualUrl/index.ts @@ -1,19 +1,23 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { Page } from 'playwright-core' -import { getElementText, quote } from '../utils' +import { SyncExpectationResult } from "expect/build/types" +import { Page } from "playwright-core" +import { getElementText, quote } from "../utils" -const toEqualUrl = async (page: Page, expectedUrl: string): Promise => { +const toEqualUrl = async ( + page: Page, + expectedUrl: string +): Promise => { const actualUrl = page.url() if (actualUrl === expectedUrl) { return { pass: true, - message: () => `${quote(expectedUrl)} matches the given Url.` + message: () => `${quote(expectedUrl)} matches the given Url.`, } } return { pass: false, - message: () => `${quote(expectedUrl)} expects not the current Url: ${quote(actualUrl)}` + message: () => + `${quote(expectedUrl)} expects not the current Url: ${quote(actualUrl)}`, } } -export default toEqualUrl \ No newline at end of file +export default toEqualUrl diff --git a/src/matchers/toEqualValue/index.test.ts b/src/matchers/toEqualValue/index.test.ts index 3ad21a1..b1d1e54 100644 --- a/src/matchers/toEqualValue/index.test.ts +++ b/src/matchers/toEqualValue/index.test.ts @@ -1,10 +1,10 @@ import { testWrapper } from "../tests/utils" -import toEqualValue from '.' +import toEqualValue from "." describe("toEqualValue", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) describe("selector", () => { it("positive", async () => { @@ -15,7 +15,9 @@ describe("toEqualValue", () => { }) it("negative", async () => { await page.setContent(``) - expect(testWrapper(await toEqualValue(page, "#foobar", "not-existing"))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toEqualValue(page, "#foobar", "not-existing")) + ).toThrowErrorMatchingSnapshot() }) }) describe("element", () => { @@ -29,17 +31,23 @@ describe("toEqualValue", () => { await page.setContent(``) const element = await page.$("#foobar") expect(element).not.toBe(null) - expect(testWrapper(await toEqualValue(element!, "not-existing"))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toEqualValue(element!, "not-existing")) + ).toThrowErrorMatchingSnapshot() }) }) describe("timeout", () => { it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toEqualValue(page, "#foobar", "bar", { - timeout: 1 * 1000 - }))).toThrowErrorMatchingSnapshot() + expect( + testWrapper( + await toEqualValue(page, "#foobar", "bar", { + timeout: 1 * 1000, + }) + ) + ).toThrowErrorMatchingSnapshot() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) }) -}) \ No newline at end of file +}) diff --git a/src/matchers/toEqualValue/index.ts b/src/matchers/toEqualValue/index.ts index c8e8fb4..7b2c934 100644 --- a/src/matchers/toEqualValue/index.ts +++ b/src/matchers/toEqualValue/index.ts @@ -1,27 +1,37 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { getElementText, quote, InputArguments } from '../utils' +import { SyncExpectationResult } from "expect/build/types" +import { getElementText, quote, InputArguments } from "../utils" -const toEqualValue = async (...args: InputArguments): Promise => { +const toEqualValue = async ( + ...args: InputArguments +): Promise => { try { - const { elementHandle, selector, expectedValue } = await getElementText(...args) + const { elementHandle, selector, expectedValue } = await getElementText( + ...args + ) /* istanbul ignore next */ - const actualTextContent = await elementHandle.evaluate((el) => (el as HTMLInputElement).value) + const actualTextContent = await elementHandle.evaluate( + (el) => (el as HTMLInputElement).value + ) if (actualTextContent?.includes(expectedValue)) { return { pass: true, - message: () => `${quote(expectedValue)} does equal ${quote(actualTextContent)}.` + message: () => + `${quote(expectedValue)} does equal ${quote(actualTextContent)}.`, } } return { pass: false, - message: () => `${quote(expectedValue)} does not equal ${quote(actualTextContent)}${selector ? ' of ' + quote(selector) + "." : '.'}` + message: () => + `${quote(expectedValue)} does not equal ${quote(actualTextContent)}${ + selector ? " of " + quote(selector) + "." : "." + }`, } } catch (err) { return { pass: false, - message: () => err.toString() + message: () => err.toString(), } } } -export default toEqualValue \ No newline at end of file +export default toEqualValue diff --git a/src/matchers/toHaveFocus/index.test.ts b/src/matchers/toHaveFocus/index.test.ts index 3479c81..783d214 100644 --- a/src/matchers/toHaveFocus/index.test.ts +++ b/src/matchers/toHaveFocus/index.test.ts @@ -1,29 +1,29 @@ import { testWrapper } from "../tests/utils" -import toHaveFocus from '.' +import toHaveFocus from "." describe("toHaveFocus", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) it("positive", async () => { await page.setContent(``) - await page.keyboard.press('Tab') + await page.keyboard.press("Tab") const result = await toHaveFocus(page, "#foobar") expect(result.pass).toBe(true) expect(result.message()).toMatchSnapshot() }) it("negative: target element don't have focus", async () => { await page.setContent(``) - await page.keyboard.press('Tab') + await page.keyboard.press("Tab") const result = await toHaveFocus(page, "#bar") expect(testWrapper(result)).toThrowErrorMatchingSnapshot() }) it("negative: target element not found", async () => { await page.setContent(``) - await page.keyboard.press('Tab') + await page.keyboard.press("Tab") const result = await toHaveFocus(page, "#bar", { - timeout: 1 * 1000 + timeout: 1 * 1000, }) expect(testWrapper(result)).toThrowErrorMatchingSnapshot() }) @@ -31,17 +31,25 @@ describe("toHaveFocus", () => { it("positive: should be able to use a custom timeout", async () => { setTimeout(async () => { await page.setContent(``) - await page.keyboard.press('Tab'); + await page.keyboard.press("Tab") }, 500) - expect(testWrapper(await toHaveFocus(page, "#foobar", { - timeout: 1 * 1000 - }))).toBe(true) + expect( + testWrapper( + await toHaveFocus(page, "#foobar", { + timeout: 1 * 1000, + }) + ) + ).toBe(true) }) it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toHaveFocus(page, "#foobar", { - timeout: 1 * 1000 - }))).toThrowError() + expect( + testWrapper( + await toHaveFocus(page, "#foobar", { + timeout: 1 * 1000, + }) + ) + ).toThrowError() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) diff --git a/src/matchers/toHaveFocus/index.ts b/src/matchers/toHaveFocus/index.ts index b1b9af7..7236c1f 100644 --- a/src/matchers/toHaveFocus/index.ts +++ b/src/matchers/toHaveFocus/index.ts @@ -1,27 +1,34 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { quote } from '../utils' -import { Page } from 'playwright-core' -import { PageWaitForSelectorOptions } from '../../../global' +import { SyncExpectationResult } from "expect/build/types" +import { quote } from "../utils" +import { Page } from "playwright-core" +import { PageWaitForSelectorOptions } from "../../../global" -const toHaveFocus = async (page: Page, selector: string, options: PageWaitForSelectorOptions = {}): Promise => { +const toHaveFocus = async ( + page: Page, + selector: string, + options: PageWaitForSelectorOptions = {} +): Promise => { try { await page.waitForSelector(selector, options) /* istanbul ignore next */ - const isFocused = await page.$eval(selector, (el) => el === document.activeElement) + const isFocused = await page.$eval( + selector, + (el) => el === document.activeElement + ) if (isFocused) { return { pass: true, - message: () => `${quote(selector)} has focus on it.` + message: () => `${quote(selector)} has focus on it.`, } } return { pass: false, - message: () => `${quote(selector)} has no focus on it.` + message: () => `${quote(selector)} has no focus on it.`, } } catch (err) { return { pass: false, - message: () => `${quote(selector)} could not be found on the page.` + message: () => `${quote(selector)} could not be found on the page.`, } } } diff --git a/src/matchers/toHaveSelector/index.test.ts b/src/matchers/toHaveSelector/index.test.ts index 2debd20..36a5ab2 100644 --- a/src/matchers/toHaveSelector/index.test.ts +++ b/src/matchers/toHaveSelector/index.test.ts @@ -1,10 +1,10 @@ import { testWrapper } from "../tests/utils" -import toHaveSelector from '.' +import toHaveSelector from "." describe("toHaveSelector", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) it("positive", async () => { await page.setContent(`
Bar
`) @@ -13,26 +13,38 @@ describe("toHaveSelector", () => { expect(result.message()).toMatchSnapshot() }) it("negative", async () => { - expect(testWrapper(await toHaveSelector(page, "#foobar", { - timeout: 1 * 1000 - }))).toThrowError() + expect( + testWrapper( + await toHaveSelector(page, "#foobar", { + timeout: 1 * 1000, + }) + ) + ).toThrowError() }) describe("timeout", () => { it("positive: should be able to use a custom timeout", async () => { setTimeout(async () => { await page.setContent(`
Bar
`) }, 500) - expect(testWrapper(await toHaveSelector(page, "#foobar", { - timeout: 1 * 1000 - }))).toBe(true) + expect( + testWrapper( + await toHaveSelector(page, "#foobar", { + timeout: 1 * 1000, + }) + ) + ).toBe(true) }) it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toHaveSelector(page, "#foobar", { - timeout: 1 * 1000 - }))).toThrowError() + expect( + testWrapper( + await toHaveSelector(page, "#foobar", { + timeout: 1 * 1000, + }) + ) + ).toThrowError() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) }) -}) \ No newline at end of file +}) diff --git a/src/matchers/toHaveSelector/index.ts b/src/matchers/toHaveSelector/index.ts index 2ac4069..05654e4 100644 --- a/src/matchers/toHaveSelector/index.ts +++ b/src/matchers/toHaveSelector/index.ts @@ -1,21 +1,25 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { quote } from '../utils' -import { Page } from 'playwright-core' -import { PageWaitForSelectorOptions } from '../../../global' +import { SyncExpectationResult } from "expect/build/types" +import { quote } from "../utils" +import { Page } from "playwright-core" +import { PageWaitForSelectorOptions } from "../../../global" -const toHaveSelector = async (page: Page, selector: string, options: PageWaitForSelectorOptions = {}): Promise => { +const toHaveSelector = async ( + page: Page, + selector: string, + options: PageWaitForSelectorOptions = {} +): Promise => { try { await page.waitForSelector(selector, options) return { pass: true, - message: () => `${quote(selector)} was found on the page.` + message: () => `${quote(selector)} was found on the page.`, } } catch (err) { return { pass: false, - message: () => `${quote(selector)} could not be found on the page.` + message: () => `${quote(selector)} could not be found on the page.`, } } } -export default toHaveSelector \ No newline at end of file +export default toHaveSelector diff --git a/src/matchers/toHaveSelectorCount/index.test.ts b/src/matchers/toHaveSelectorCount/index.test.ts index 3374153..57324bf 100644 --- a/src/matchers/toHaveSelectorCount/index.test.ts +++ b/src/matchers/toHaveSelectorCount/index.test.ts @@ -1,29 +1,37 @@ import { testWrapper } from "../tests/utils" -import toHaveSelectorCount from '.' +import toHaveSelectorCount from "." describe("toHaveSelectorCount", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) describe("selector", () => { it("positive", async () => { - await page.setContent(`
Bar
`) + await page.setContent( + `
Bar
` + ) const result = await toHaveSelectorCount(page, ".foobar", 2) expect(result.pass).toBe(true) expect(result.message()).toMatchSnapshot() }) it("negative", async () => { await page.setContent(`
Bar
`) - expect(testWrapper(await toHaveSelectorCount(page, ".foobar", 2))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toHaveSelectorCount(page, ".foobar", 2)) + ).toThrowErrorMatchingSnapshot() }) }) describe("timeout", () => { it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toHaveSelectorCount(page, ".foobar", 1, { - timeout: 1 * 1000 - }))).toThrowErrorMatchingSnapshot() + expect( + testWrapper( + await toHaveSelectorCount(page, ".foobar", 1, { + timeout: 1 * 1000, + }) + ) + ).toThrowErrorMatchingSnapshot() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) diff --git a/src/matchers/toHaveSelectorCount/index.ts b/src/matchers/toHaveSelectorCount/index.ts index f035ea9..7bf62ac 100644 --- a/src/matchers/toHaveSelectorCount/index.ts +++ b/src/matchers/toHaveSelectorCount/index.ts @@ -1,27 +1,36 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { quote } from '../utils' -import { Page } from 'playwright-core' -import {PageWaitForSelectorOptions} from "../../../global"; +import { SyncExpectationResult } from "expect/build/types" +import { quote } from "../utils" +import { Page } from "playwright-core" +import { PageWaitForSelectorOptions } from "../../../global" -const toHaveSelectorCount = async (page: Page, selector: string, expectedValue: number, options: PageWaitForSelectorOptions = {}): Promise => { +const toHaveSelectorCount = async ( + page: Page, + selector: string, + expectedValue: number, + options: PageWaitForSelectorOptions = {} +): Promise => { try { - await page.waitForSelector(selector, {state: 'attached', ...options}) + await page.waitForSelector(selector, { state: "attached", ...options }) /* istanbul ignore next */ - const actualCount = await page.$$eval(selector, el => el.length) + const actualCount = await page.$$eval(selector, (el) => el.length) if (actualCount === expectedValue) { return { pass: true, - message: () => `${quote(`${expectedValue}`)} does equal ${quote(`${actualCount}`)}.` + message: () => + `${quote(`${expectedValue}`)} does equal ${quote(`${actualCount}`)}.`, } } return { pass: false, - message: () => `${quote(`${expectedValue}`)} does not equal ${quote(`${actualCount}`)}${selector ? ' of ' + quote(selector) + "." : '.'}` + message: () => + `${quote(`${expectedValue}`)} does not equal ${quote( + `${actualCount}` + )}${selector ? " of " + quote(selector) + "." : "."}`, } } catch (err) { return { pass: false, - message: () => `${quote(selector)} could not be found on the page.` + message: () => `${quote(selector)} could not be found on the page.`, } } } diff --git a/src/matchers/toHaveText/index.test.ts b/src/matchers/toHaveText/index.test.ts index 967f55f..3f92ff3 100644 --- a/src/matchers/toHaveText/index.test.ts +++ b/src/matchers/toHaveText/index.test.ts @@ -1,10 +1,10 @@ import { testWrapper } from "../tests/utils" -import toHaveText from '.' +import toHaveText from "." describe("toHaveText", () => { afterEach(async () => { - await page.setContent('') + await page.setContent("") }) describe("selector", () => { it("positive frame", async () => { @@ -16,7 +16,9 @@ describe("toHaveText", () => { }) it("empty positive with page element", async () => { await page.setContent(`
`) - const result = await toHaveText(page, "#foobar", "", { state: 'attached' }) + const result = await toHaveText(page, "#foobar", "", { + state: "attached", + }) expect(result.pass).toBe(true) expect(result.message()).toMatchSnapshot() }) @@ -36,7 +38,9 @@ describe("toHaveText", () => { }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) - expect(testWrapper(await toHaveText(page, "#foobar", "not-existing"))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toHaveText(page, "#foobar", "not-existing")) + ).toThrowErrorMatchingSnapshot() }) }) describe("element", () => { @@ -50,7 +54,9 @@ describe("toHaveText", () => { await page.setContent(`
zzzBarzzz
`) const element = await page.$("#foobar") expect(element).not.toBe(null) - expect(testWrapper(await toHaveText(element!, "not-existing"))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toHaveText(element!, "not-existing")) + ).toThrowErrorMatchingSnapshot() }) }) describe("page", () => { @@ -60,14 +66,20 @@ describe("toHaveText", () => { }) it("negative", async () => { await page.setContent(`
zzzBarzzz
`) - expect(testWrapper(await toHaveText(page, "not-existing"))).toThrowErrorMatchingSnapshot() + expect( + testWrapper(await toHaveText(page, "not-existing")) + ).toThrowErrorMatchingSnapshot() }) it("should be able to overwrite timeout", async () => { await page.setContent(`
zzzBarzzz
`) const start = new Date().getTime() - expect(testWrapper(await toHaveText(page, "not-existing", { - timeout: 2000 - }))).toThrowErrorMatchingSnapshot() + expect( + testWrapper( + await toHaveText(page, "not-existing", { + timeout: 2000, + }) + ) + ).toThrowErrorMatchingSnapshot() const duration = new Date().getTime() - start expect(duration).toBeGreaterThan(2000) }) @@ -75,9 +87,13 @@ describe("toHaveText", () => { describe("timeout", () => { it("should throw an error after the timeout exceeds", async () => { const start = new Date().getTime() - expect(testWrapper(await toHaveText(page, "#foobar", "bar", { - timeout: 1 * 1000 - }))).toThrowErrorMatchingSnapshot() + expect( + testWrapper( + await toHaveText(page, "#foobar", "bar", { + timeout: 1 * 1000, + }) + ) + ).toThrowErrorMatchingSnapshot() const duration = new Date().getTime() - start expect(duration).toBeLessThan(1500) }) diff --git a/src/matchers/toHaveText/index.ts b/src/matchers/toHaveText/index.ts index e3c11b4..57a3138 100644 --- a/src/matchers/toHaveText/index.ts +++ b/src/matchers/toHaveText/index.ts @@ -1,25 +1,35 @@ -import { SyncExpectationResult } from 'expect/build/types' -import { getElementText, quote, InputArguments } from '../utils' +import { SyncExpectationResult } from "expect/build/types" +import { getElementText, quote, InputArguments } from "../utils" -const toHaveText = async (...args: InputArguments): Promise => { +const toHaveText = async ( + ...args: InputArguments +): Promise => { try { - const { elementHandle, selector, expectedValue } = await getElementText(...args) + const { elementHandle, selector, expectedValue } = await getElementText( + ...args + ) /* istanbul ignore next */ - const actualTextContent = await elementHandle.evaluate((el) => el.textContent) + const actualTextContent = await elementHandle.evaluate( + (el) => el.textContent + ) if (actualTextContent?.includes(expectedValue)) { return { pass: true, - message: () => `${quote(expectedValue)} is included in ${quote(actualTextContent)}.` + message: () => + `${quote(expectedValue)} is included in ${quote(actualTextContent)}.`, } } return { pass: false, - message: () => `${quote(expectedValue)} is not included in ${quote(actualTextContent)}${selector ? ' of ' + quote(selector) + "." : '.'}` + message: () => + `${quote(expectedValue)} is not included in ${quote( + actualTextContent + )}${selector ? " of " + quote(selector) + "." : "."}`, } } catch (err) { return { pass: false, - message: () => err.toString() + message: () => err.toString(), } } } diff --git a/src/matchers/utils.test.ts b/src/matchers/utils.test.ts index 929e928..1251b44 100644 --- a/src/matchers/utils.test.ts +++ b/src/matchers/utils.test.ts @@ -1,13 +1,15 @@ -import { getElementText } from './utils' +import { getElementText } from "./utils" describe("utils.getElementText", () => { it("should throw an error if the specified expect element was not recognized", async () => { - class Test123 { } - // @ts-ignore - await expect(getElementText(new Test123(), "")).rejects.toThrowErrorMatchingSnapshot() + class Test123 {} + await expect( + // @ts-ignore + getElementText(new Test123(), "") + ).rejects.toThrowErrorMatchingSnapshot() }) it("should throw an error if the input length was not in range", async () => { // @ts-ignore await expect(getElementText()).rejects.toThrowErrorMatchingSnapshot() }) -}) \ No newline at end of file +}) diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index f74913e..06df2cc 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -26,9 +26,17 @@ interface getElementTextReturn { expectedValue: string } -export type InputArguments = [Page | ElementHandle, string?, (string | PageWaitForSelectorOptions)?, PageWaitForSelectorOptions?] +export type InputArguments = [ + Page | ElementHandle, + string?, + (string | PageWaitForSelectorOptions)?, + PageWaitForSelectorOptions? +] -const lastElementHasType = (args: InputArguments, type: "string" | "object"): boolean => typeof args[args.length - 1] === type +const lastElementHasType = ( + args: InputArguments, + type: "string" | "object" +): boolean => typeof args[args.length - 1] === type const getSelectorOptions = (args: InputArguments) => { let selectorOptions: PageWaitForSelectorOptions | undefined = undefined @@ -41,7 +49,9 @@ const getSelectorOptions = (args: InputArguments) => { return selectorOptions } -export const getElementText = async (...args: InputArguments): Promise => { +export const getElementText = async ( + ...args: InputArguments +): Promise => { if (args.length > 1) { const type = detectExpectType(args[0]) /** @@ -56,13 +66,13 @@ export const getElementText = async (...args: InputArguments): Promise Date: Wed, 12 May 2021 10:49:14 -0500 Subject: [PATCH 07/16] Fix .gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 9612758..b17578f 100644 --- a/.gitignore +++ b/.gitignore @@ -103,5 +103,4 @@ dist # TernJS port file .tern-port -lib/ -.vscode/ +lib/ \ No newline at end of file From c51a53b25851335a42ef1938b9fd845124ce26e8 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Wed, 12 May 2021 10:57:34 -0500 Subject: [PATCH 08/16] Update snapshots --- .../toEqualText/__snapshots__/index.test.ts.snap | 16 +++++++++++++++- src/matchers/toEqualText/index.ts | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap index a130e82..2157b8c 100644 --- a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap +++ b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap @@ -1,12 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`toEqualText selector negative 1`] = ` +exports[`toEqualText element failure 1`] = ` +"expect(received).toEqualText(expected) + +Expected: \\"not-existing\\" +Received: \\"zzzBarzzz\\"" +`; + +exports[`toEqualText page failure 1`] = ` "expect(received).toEqualText(expected) Expected: \\"not-existing\\" Received: \\"zzzBarzzz\\"" `; +exports[`toEqualText selector negative 1`] = ` +"expect(received).toEqualText(expected) + +Expected: \\"Bar\\" +Received: \\"zzzBarzzz\\"" +`; + exports[`toEqualText selector not failure 1`] = ` "expect(received).not.toEqualText(expected) diff --git a/src/matchers/toEqualText/index.ts b/src/matchers/toEqualText/index.ts index 5a97f7b..3389acd 100644 --- a/src/matchers/toEqualText/index.ts +++ b/src/matchers/toEqualText/index.ts @@ -6,6 +6,7 @@ const toEqualText: jest.CustomMatcher = async function ( ): Promise { try { const { elementHandle, expectedValue } = await getElementText(...args) + /* istanbul ignore next */ const actualTextContent = await elementHandle.evaluate( (el) => el.textContent ) From 849a9f91eae9556721ea53f87aadb54f64b18b2c Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Wed, 12 May 2021 11:01:02 -0500 Subject: [PATCH 09/16] Prettier --- .../__snapshots__/index.test.ts.snap | 3 +-- src/matchers/toEqualText/index.ts | 8 ++---- src/matchers/utils.ts | 25 ++++++++++--------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap index 2157b8c..c8b6041 100644 --- a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap +++ b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap @@ -24,8 +24,7 @@ Received: \\"zzzBarzzz\\"" exports[`toEqualText selector not failure 1`] = ` "expect(received).not.toEqualText(expected) -Expected: not \\"Bar\\" -" +Expected: not \\"Bar\\"" `; exports[`toEqualText selector timeout should throw an error after the timeout exceeds 1`] = `"Error: Timeout exceed for element '#foobar'"`; diff --git a/src/matchers/toEqualText/index.ts b/src/matchers/toEqualText/index.ts index 3389acd..cf355e2 100644 --- a/src/matchers/toEqualText/index.ts +++ b/src/matchers/toEqualText/index.ts @@ -13,12 +13,8 @@ const toEqualText: jest.CustomMatcher = async function ( return { pass: actualTextContent === expectedValue, - message: getMessage( - this, - "toEqualText", - expectedValue, - actualTextContent - ), + message: () => + getMessage(this, "toEqualText", expectedValue, actualTextContent), } } catch (err) { return { diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index 06df2cc..aa59dbe 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -114,24 +114,25 @@ export const getElementText = async ( } export const quote = (val: string | null) => - val === null ? 'null' : `'${val}'` + val === null ? "null" : `'${val}'` export const getMessage = ( - ctx: jest.MatcherContext, + { isNot, promise, utils }: jest.MatcherContext, matcher: string, expected: string | null, received: string | null -) => () => { - const matcherHint = ctx.utils.matcherHint(matcher, undefined, undefined, { - isNot: ctx.isNot, - promise: ctx.promise, - }) + '\n\n' +) => { + const matcherHint = + utils.matcherHint(matcher, undefined, undefined, { isNot, promise }) + + "\n\n" - if (ctx.isNot) { - return matcherHint + `Expected: not ${ctx.utils.printExpected(expected)}\n` + if (isNot) { + return matcherHint + `Expected: not ${utils.printExpected(expected)}` } else { - return matcherHint + - `Expected: ${ctx.utils.printExpected(expected)}\n` + - `Received: ${ctx.utils.printReceived(received)}` + return ( + matcherHint + + `Expected: ${utils.printExpected(expected)}\n` + + `Received: ${utils.printReceived(received)}` + ) } } From 1ef4af4c13bb2f5ce41afb6a620b2a6af444d689 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Wed, 12 May 2021 11:59:33 -0500 Subject: [PATCH 10/16] force color --- .github/workflows/nodejs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 93c0db3..81b7312 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -25,6 +25,10 @@ jobs: npx prettier --check . - run: npm run build - run: npm test + env: + # Used by chalk. Ensures output from Jest includes ANSI escape + # characters that are needed to match test snapshots. + FORCE_COLOR: true - run: npx codecov env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 493a361e64e4325a34b5ad8de6c378dfc3da57cf Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Thu, 20 May 2021 16:51:38 -0500 Subject: [PATCH 11/16] Update quote function --- src/matchers/toEqualText/index.test.ts | 18 +++++++++--------- src/matchers/utils.ts | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/matchers/toEqualText/index.test.ts b/src/matchers/toEqualText/index.test.ts index 63dbe2a..835f0c0 100644 --- a/src/matchers/toEqualText/index.test.ts +++ b/src/matchers/toEqualText/index.test.ts @@ -21,17 +21,17 @@ describe("toEqualText", () => { await page.setContent(`
zzzBarzzz
`) await assertSnapshot(() => expect(page).toEqualText("#foobar", "Bar")) }) - describe("not", () => { - it("success in frame", async () => { + describe("with 'not' usage", () => { + it("positive in frame", async () => { await page.setContent(``) const iframe = await page.$("iframe") await expect(iframe!).not.toEqualText("h1", "Foo") }) - it("success", async () => { + it("positive", async () => { await page.setContent(`
Bar
`) await expect(page).not.toEqualText("#foobar", "Foo") }) - it("failure", async () => { + it("negative", async () => { await page.setContent(`
Bar
`) await assertSnapshot(() => expect(page).not.toEqualText("#foobar", "Bar") @@ -39,7 +39,7 @@ describe("toEqualText", () => { }) }) describe("timeout", () => { - it("success with a custom timeout", async () => { + it("positive: should be able to use a custom timeout", async () => { setTimeout(async () => { await page.setContent(`
Bar
`) }, 500) @@ -56,13 +56,13 @@ describe("toEqualText", () => { }) }) describe("element", () => { - it("success", async () => { + it("positive", async () => { await page.setContent(`
Bar
`) const element = await page.$("#foobar") expect(element).not.toBeNull() await expect(element!).toEqualText("Bar") }) - it("failure", async () => { + it("negative", async () => { await page.setContent(`
zzzBarzzz
`) const element = await page.$("#foobar") expect(element).not.toBeNull() @@ -70,11 +70,11 @@ describe("toEqualText", () => { }) }) describe("page", () => { - it("success", async () => { + it("positive", async () => { await page.setContent(`
Bar
`) await expect(page).toEqualText("Bar") }) - it("failure", async () => { + it("negative", async () => { await page.setContent(`
zzzBarzzz
`) await assertSnapshot(() => expect(page).toEqualText("not-existing")) }) diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index aa59dbe..bd1c232 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -113,8 +113,7 @@ export const getElementText = async ( throw new Error(`Invalid input length: ${args.length}`) } -export const quote = (val: string | null) => - val === null ? "null" : `'${val}'` +export const quote = (val: string | null) => (val === null ? "" : `'${val}'`) export const getMessage = ( { isNot, promise, utils }: jest.MatcherContext, From 0e3e57b11f125ece959ef2ebab82c4ac85eb84af Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Thu, 20 May 2021 16:54:26 -0500 Subject: [PATCH 12/16] Update snap --- .../toEqualText/__snapshots__/index.test.ts.snap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap index c8b6041..d544ad6 100644 --- a/src/matchers/toEqualText/__snapshots__/index.test.ts.snap +++ b/src/matchers/toEqualText/__snapshots__/index.test.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`toEqualText element failure 1`] = ` +exports[`toEqualText element negative 1`] = ` "expect(received).toEqualText(expected) Expected: \\"not-existing\\" Received: \\"zzzBarzzz\\"" `; -exports[`toEqualText page failure 1`] = ` +exports[`toEqualText page negative 1`] = ` "expect(received).toEqualText(expected) Expected: \\"not-existing\\" @@ -21,10 +21,10 @@ Expected: \\"Bar\\" Received: \\"zzzBarzzz\\"" `; -exports[`toEqualText selector not failure 1`] = ` +exports[`toEqualText selector timeout should throw an error after the timeout exceeds 1`] = `"Error: Timeout exceed for element '#foobar'"`; + +exports[`toEqualText selector with 'not' usage negative 1`] = ` "expect(received).not.toEqualText(expected) Expected: not \\"Bar\\"" `; - -exports[`toEqualText selector timeout should throw an error after the timeout exceeds 1`] = `"Error: Timeout exceed for element '#foobar'"`; From 56c415c77b976f5ac827d3e054cc151f7c267762 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Thu, 20 May 2021 17:16:12 -0500 Subject: [PATCH 13/16] Update docs --- README.md | 12 ++++++--- src/index.test.ts | 62 ----------------------------------------------- src/index.ts | 22 +---------------- 3 files changed, 9 insertions(+), 87 deletions(-) delete mode 100644 src/index.test.ts diff --git a/README.md b/README.md index c1f0b8d..8fe38dd 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,16 @@ To activate it in your Jest environment you have to include it in your configura } ``` -### Without Jest +### With Playwright test runner -```javascript -import expect from "expect-playwright" +To activate with the Playwright test runner, use `expect.extend` to add the `expect-playwright` matchers. -await expect(page).toHaveText("#foo", "my text") +```js +// folio.config.ts +import { expect } from "@playwright/test" +import matchers from "expect-playwright" + +expect.extend(matchers) ``` ## Why do I need it diff --git a/src/index.test.ts b/src/index.test.ts deleted file mode 100644 index 94fe597..0000000 --- a/src/index.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import matchers from "./matchers" - -import expectPlaywright from "." - -describe("expect-playwright", () => { - afterEach(async () => { - await page.setContent("") - }) - it("should apply the functions", () => { - for (let matcher in matchers) { - // @ts-ignore - expect(expect(null)[matcher]).not.toBeUndefined() - } - }) - it("should be possible to use a not selector", async () => { - await page.setContent(`
zzzBarzzz
`) - await expect(page).not.toHaveText("This is definitely not there") - }) - it("should be possible to use a normal selector", async () => { - await page.setContent(`
zzzBarzzz
`) - await expect(page).toHaveText("zzzBarzzz") - }) -}) - -describe("expectPlaywright", () => { - afterEach(async () => { - await page.setContent("") - }) - describe("should be able to handle positive cases", () => { - it("return right result for page and 2 arguments", async () => { - await page.setContent(`
zzzBarzzz
`) - expect(await expectPlaywright(page).toHaveText("zzzBarzzz")).toBe(true) - }) - it("return right result for page and 3 arguments", async () => { - await page.setContent(`
zzzBarzzz
`) - expect(await expectPlaywright(page).toHaveText("#bar", "zzzBarzzz")).toBe( - true - ) - }) - it("return right result for element and 2 arguments", async () => { - await page.setContent(`
zzzFoozzz
`) - const elem = await page.$("#foo") - expect(await expectPlaywright(elem!).toHaveText("zzzFoozzz")).toBe(true) - }) - }) - describe("should be able to handle negative cases", () => { - it("return right result for page and 2 arguments", async () => { - await page.setContent(`
zzzzz
`) - await expect( - expectPlaywright(page).toHaveText("zzzBarzzz") - ).rejects.toThrowErrorMatchingSnapshot() - }) - it("return right result for page and 4 arguments", async () => { - await page.setContent(`
zzzBarzzz
`) - await expect( - expectPlaywright(page).toHaveText("#bar", "zzzBarzzz", { - timeout: 1 * 1000, - }) - ).rejects.toThrowErrorMatchingSnapshot() - }) - }) -}) diff --git a/src/index.ts b/src/index.ts index f94109d..ff69f7d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ import matchers from "./matchers" -import type { Page, ElementHandle } from "playwright-core" -import type { PlaywrightMatchers } from "../global" // @ts-ignore if (typeof global.expect !== "undefined") { @@ -8,22 +6,4 @@ if (typeof global.expect !== "undefined") { global.expect.extend(matchers) } -const expectWrapper = ( - pageOrElement: Page | ElementHandle -): PlaywrightMatchers => - Object.entries(matchers).reduce( - (acc, [name, matcher]) => ({ - ...acc, - [name]: async (...args: any[]) => { - // @ts-ignore - const result = await matcher(pageOrElement, ...args) - if (!result.pass) { - throw new Error(result.message()) - } - return true - }, - }), - {} as PlaywrightMatchers - ) - -export = expectWrapper +export default matchers From c0d6d21d6bab6df73bb9a64f2b89ad30553bc84d Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Thu, 20 May 2021 17:22:17 -0500 Subject: [PATCH 14/16] Remove snap --- src/__snapshots__/index.test.ts.snap | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/__snapshots__/index.test.ts.snap diff --git a/src/__snapshots__/index.test.ts.snap b/src/__snapshots__/index.test.ts.snap deleted file mode 100644 index 34dbd55..0000000 --- a/src/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`expectPlaywright should be able to handle negative cases return right result for page and 2 arguments 1`] = `"'zzzBarzzz' is not included in 'zzzzz'."`; - -exports[`expectPlaywright should be able to handle negative cases return right result for page and 4 arguments 1`] = `"Error: Timeout exceed for element '#bar'"`; From c23ef1894a56e032db3372af9fb865c4798f4551 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Fri, 21 May 2021 10:12:04 -0500 Subject: [PATCH 15/16] Simplify `getMessage` return value --- src/matchers/utils.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/matchers/utils.ts b/src/matchers/utils.ts index bd1c232..4ea35cb 100644 --- a/src/matchers/utils.ts +++ b/src/matchers/utils.ts @@ -121,17 +121,14 @@ export const getMessage = ( expected: string | null, received: string | null ) => { - const matcherHint = - utils.matcherHint(matcher, undefined, undefined, { isNot, promise }) + - "\n\n" - - if (isNot) { - return matcherHint + `Expected: not ${utils.printExpected(expected)}` - } else { - return ( - matcherHint + - `Expected: ${utils.printExpected(expected)}\n` + + const message = isNot + ? `Expected: not ${utils.printExpected(expected)}` + : `Expected: ${utils.printExpected(expected)}\n` + `Received: ${utils.printReceived(received)}` - ) - } + + return ( + utils.matcherHint(matcher, undefined, undefined, { isNot, promise }) + + "\n\n" + + message + ) } From 31b1100867a49e9f73d40930ea9e9f38031668e3 Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Fri, 21 May 2021 10:34:48 -0500 Subject: [PATCH 16/16] Don't use default export since it might be confusing since it used to default export `expect` --- README.md | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8fe38dd..db4b0e6 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ To activate with the Playwright test runner, use `expect.extend` to add the `exp ```js // folio.config.ts import { expect } from "@playwright/test" -import matchers from "expect-playwright" +import { matchers } from "expect-playwright" expect.extend(matchers) ``` diff --git a/src/index.ts b/src/index.ts index ff69f7d..1cad6e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,4 +6,4 @@ if (typeof global.expect !== "undefined") { global.expect.extend(matchers) } -export default matchers +export { matchers }