From 75cfbecd2a0ca3fa339d808d900dfd047bbb9e41 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 17 Aug 2020 16:32:43 +0100 Subject: [PATCH 1/7] Add findBy queries --- lib/index.ts | 16 ++++++++++++++++ lib/typedefs.ts | 28 ++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 510189f..7a85442 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -161,41 +161,57 @@ export function getQueriesForElement( 'queryAllByPlaceholderText', 'getByPlaceholderText', 'getAllByPlaceholderText', + 'findByPlaceholderText', + 'findAllByPlaceholderText', 'queryByText', 'queryAllByText', 'getByText', 'getAllByText', + 'findByText', + 'findAllByText', 'queryByLabelText', 'queryAllByLabelText', 'getByLabelText', 'getAllByLabelText', + 'findByLabelText', + 'findAllByLabelText', 'queryByAltText', 'queryAllByAltText', 'getByAltText', 'getAllByAltText', + 'findByAltText', + 'findAllByAltText', 'queryByTestId', 'queryAllByTestId', 'getByTestId', 'getAllByTestId', + 'findByTestId', + 'findAllByTestId', 'queryByTitle', 'queryAllByTitle', 'getByTitle', 'getAllByTitle', + 'findByTitle', + 'findAllByTitle', 'queryByRole', 'queryAllByRole', 'getByRole', 'getAllByRole', + 'findByRole', + 'findAllByRole', 'queryByDisplayValue', 'queryAllByDisplayValue', 'getByDisplayValue', 'getAllByDisplayValue', + 'findByDisplayValue', + 'findAllByDisplayValue', ] functionNames.forEach(functionName => { o[functionName] = createDelegateFor(functionName, contextFn) diff --git a/lib/typedefs.ts b/lib/typedefs.ts index c163154..9970f20 100644 --- a/lib/typedefs.ts +++ b/lib/typedefs.ts @@ -1,4 +1,4 @@ -import {Matcher, MatcherOptions, SelectorMatcherOptions} from '@testing-library/dom' +import {BoundFunctions, Matcher, MatcherOptions, SelectorMatcherOptions, WaitForElementOptions} from '@testing-library/dom' import {ElementHandle} from 'puppeteer' type Element = ElementHandle @@ -8,54 +8,66 @@ interface IQueryMethods { queryAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByPlaceholderText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByPlaceholderText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise queryAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise + findByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise queryAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise + findByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByAltText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByAltText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByTestId(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByTestId(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByTitle(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByTitle(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByRole(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByRole(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise queryByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise + findByDisplayValue(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findAllByDisplayValue(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise } -type IScopedQueryMethods = { - [K in keyof IQueryMethods]: (m: Matcher, opts?: MatcherOptions) => ReturnType -} - -export interface IScopedQueryUtils extends IScopedQueryMethods { - getQueriesForElement(): IQueryUtils & IScopedQueryUtils +export interface IScopedQueryUtils extends BoundFunctions { + getQueriesForElement(): IScopedQueryUtils getNodeText(): Promise } export interface IQueryUtils extends IQueryMethods { - getQueriesForElement(): IQueryUtils & IScopedQueryUtils + getQueriesForElement(): BoundFunctions getNodeText(el: Element): Promise } From 5081efe36dc9301357f883f823113920f0d328bb Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 17 Aug 2020 16:32:55 +0100 Subject: [PATCH 2/7] Add tests --- test/extend.test.ts | 23 +++++++++++++++++++++++ test/fixtures/late-page.html | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/test/extend.test.ts b/test/extend.test.ts index 26ef087..63d6337 100644 --- a/test/extend.test.ts +++ b/test/extend.test.ts @@ -100,6 +100,29 @@ describe('lib/extend.ts', () => { expect(await queryByText('Hello h3')).toBeTruthy() }) + describe('deferred page', () => { + beforeEach(async () => { + await page.goto(`file://${path.join(__dirname, 'fixtures/late-page.html')}`) + document = await page.getDocument() + }) + + it('should handle the findBy* methods', async () => { + expect(await document.findByText('Loaded!', {}, { timeout: 7000 })).toBeTruthy() + }, 9000) + + it('should handle the findByAll* methods', async () => { + const elements = await document.findAllByText(/Hello/, {}, { timeout: 7000 }) + expect(elements).toHaveLength(2) + + const text = await Promise.all([ + page.evaluate(el => el.textContent, elements[0]), + page.evaluate(el => el.textContent, elements[1]), + ]) + + expect(text).toEqual(['Hello h1', 'Hello h2']) + }, 9000) + }) + afterAll(async () => { await browser.close() }) diff --git a/test/fixtures/late-page.html b/test/fixtures/late-page.html index e536f9c..87f5474 100644 --- a/test/fixtures/late-page.html +++ b/test/fixtures/late-page.html @@ -7,6 +7,14 @@ const loaded = document.createElement('span') loaded.textContent = 'Loaded!' document.body.appendChild(loaded) + + const heading1 = document.createElement('h1') + heading1.textContent = 'Hello h1' + document.body.appendChild(heading1) + + const heading2 = document.createElement('h2') + heading2.textContent = 'Hello h2' + document.body.appendChild(heading2) }, 5000) From c386e82999613974474a2220759fd9cbc292f485 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 17 Aug 2020 16:42:12 +0100 Subject: [PATCH 3/7] Update README --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fd43d85..e53a71a 100644 --- a/README.md +++ b/README.md @@ -73,30 +73,41 @@ Unique methods, not part of `@testing-library/dom` - `queryAllByPlaceholderText` - `getByPlaceholderText` - `getAllByPlaceholderText` + - `findByPlaceholderText` + - `findAllByPlaceholderText` - `queryByText` - `queryAllByText` - `getByText` - `getAllByText` + - `findByText` + - `findAllByText` - `queryByLabelText` - `queryAllByLabelText` - `getByLabelText` - `getAllByLabelText` + - `findByLabelText` + - `findAllByLabelText` - `queryByAltText` - `queryAllByAltText` - `getByAltText` - `getAllByAltText` + - `findByAltText` + - `findAllByAltText` - `queryByTestId` - `queryAllByTestId` - `getByTestId` - `getAllByTestId` + - `findByTestId` + - `findAllByTestId` - `queryByTitle` - `queryAllByTitle` - `getByTitle` - `getAllByTitle` + - `findByTitle` + - `findAllByTitle` ## Known Limitations -- `waitForElement` method is not exposed. Puppeteer has its own set of wait utilities that somewhat conflict with the style used in `@testing-library/dom`. See [#3](https://github.com/testing-library/pptr-testing-library/issues/3). - `fireEvent` method is not exposed, use puppeteer's built-ins instead. - `expect` assertion extensions are not available. From 32244d75cb2a3fa6b4085a8dec2792e6ce93ce53 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 17 Aug 2020 16:47:21 +0100 Subject: [PATCH 4/7] Add missing docs --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e53a71a..9985362 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,12 @@ Unique methods, not part of `@testing-library/dom` - `getAllByTitle` - `findByTitle` - `findAllByTitle` + - `queryByDisplayValue`, + - `queryAllByDisplayValue`, + - `getByDisplayValue`, + - `getAllByDisplayValue`, + - `findByDisplayValue`, + - `findAllByDisplayValue`, ## Known Limitations From b06d1610c4cc2712cf1f456f8879c13b03dda831 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 17 Aug 2020 17:00:13 +0100 Subject: [PATCH 5/7] Cleaner --- lib/typedefs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/typedefs.ts b/lib/typedefs.ts index 9970f20..0cd35df 100644 --- a/lib/typedefs.ts +++ b/lib/typedefs.ts @@ -67,7 +67,7 @@ export interface IScopedQueryUtils extends BoundFunctions { } export interface IQueryUtils extends IQueryMethods { - getQueriesForElement(): BoundFunctions + getQueriesForElement(): IScopedQueryUtils getNodeText(el: Element): Promise } From 4d96f87343595aba2af73de4b5fa86c64696f28e Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Tue, 18 Aug 2020 09:45:03 +0100 Subject: [PATCH 6/7] Update types and docs --- README.md | 2 +- lib/typedefs.ts | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9985362..ce9df8f 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Unique methods, not part of `@testing-library/dom` - `findAllByDisplayValue`, ## Known Limitations - +- Async utilities `waitForElement`, `waitForElementToBeRemoved` and `waitForDomChange` are not exposed. Consider using a `find*` query. - `fireEvent` method is not exposed, use puppeteer's built-ins instead. - `expect` assertion extensions are not available. diff --git a/lib/typedefs.ts b/lib/typedefs.ts index 0cd35df..3de65c9 100644 --- a/lib/typedefs.ts +++ b/lib/typedefs.ts @@ -1,4 +1,4 @@ -import {BoundFunctions, Matcher, MatcherOptions, SelectorMatcherOptions, WaitForElementOptions} from '@testing-library/dom' +import {Matcher, MatcherOptions, SelectorMatcherOptions, WaitForElementOptions} from '@testing-library/dom' import {ElementHandle} from 'puppeteer' type Element = ElementHandle @@ -61,6 +61,20 @@ interface IQueryMethods { findAllByDisplayValue(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise } +export type BoundFunction = T extends ( + attribute: string, + element: Element, + text: infer P, + options: infer Q, +) => infer R + ? (text: P, options?: Q) => R + : T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer W) => infer R + ? (text: P, options?: Q, waitForElementOptions?: W) => R + : T extends (a1: any, text: infer P, options: infer Q) => infer R + ? (text: P, options?: Q) => R + : never; +export type BoundFunctions = { [P in keyof T]: BoundFunction }; + export interface IScopedQueryUtils extends BoundFunctions { getQueriesForElement(): IScopedQueryUtils getNodeText(): Promise From 8afb2e7813553dc17b6c40ff011811da5258cc4e Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Tue, 18 Aug 2020 10:45:38 +0100 Subject: [PATCH 7/7] Lint --- lib/typedefs.ts | 100 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/lib/typedefs.ts b/lib/typedefs.ts index 3de65c9..c87810c 100644 --- a/lib/typedefs.ts +++ b/lib/typedefs.ts @@ -8,57 +8,121 @@ interface IQueryMethods { queryAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByPlaceholderText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByPlaceholderText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByPlaceholderText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByPlaceholderText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise queryAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise - findByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise queryAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise getAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise - findByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByLabelText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByLabelText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByAltText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByAltText(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByAltText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByAltText( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByTestId(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByTestId(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByTestId( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByTestId( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByTitle(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByTitle(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByTitle( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByTitle( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByRole(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByRole(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByRole( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByRole( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise queryByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise queryAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise getByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise getAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise - findByDisplayValue(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise - findAllByDisplayValue(el: Element, m: Matcher, opts?: SelectorMatcherOptions, waitForOpts?: WaitForElementOptions): Promise + findByDisplayValue( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise + findAllByDisplayValue( + el: Element, + m: Matcher, + opts?: SelectorMatcherOptions, + waitForOpts?: WaitForElementOptions): Promise } export type BoundFunction = T extends ( @@ -72,8 +136,8 @@ export type BoundFunction = T extends ( ? (text: P, options?: Q, waitForElementOptions?: W) => R : T extends (a1: any, text: infer P, options: infer Q) => infer R ? (text: P, options?: Q) => R - : never; -export type BoundFunctions = { [P in keyof T]: BoundFunction }; + : never +export type BoundFunctions = { [P in keyof T]: BoundFunction } export interface IScopedQueryUtils extends BoundFunctions { getQueriesForElement(): IScopedQueryUtils