Skip to content

Commit 68301a0

Browse files
umpoxjrolfs
authored andcommitted
1 parent 6efefe5 commit 68301a0

File tree

5 files changed

+179
-11
lines changed

5 files changed

+179
-11
lines changed

README.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -90,30 +90,48 @@ Unique methods, not part of `@testing-library/dom`
9090
- `queryAllByPlaceholderText`
9191
- `getByPlaceholderText`
9292
- `getAllByPlaceholderText`
93+
- `findByPlaceholderText`
94+
- `findAllByPlaceholderText`
9395
- `queryByText`
9496
- `queryAllByText`
9597
- `getByText`
9698
- `getAllByText`
99+
- `findByText`
100+
- `findAllByText`
97101
- `queryByLabelText`
98102
- `queryAllByLabelText`
99103
- `getByLabelText`
100104
- `getAllByLabelText`
105+
- `findByLabelText`
106+
- `findAllByLabelText`
101107
- `queryByAltText`
102108
- `queryAllByAltText`
103109
- `getByAltText`
104110
- `getAllByAltText`
111+
- `findByAltText`
112+
- `findAllByAltText`
105113
- `queryByTestId`
106114
- `queryAllByTestId`
107115
- `getByTestId`
108116
- `getAllByTestId`
117+
- `findByTestId`
118+
- `findAllByTestId`
109119
- `queryByTitle`
110120
- `queryAllByTitle`
111121
- `getByTitle`
112122
- `getAllByTitle`
123+
- `findByTitle`
124+
- `findAllByTitle`
125+
- `queryByDisplayValue`,
126+
- `queryAllByDisplayValue`,
127+
- `getByDisplayValue`,
128+
- `getAllByDisplayValue`,
129+
- `findByDisplayValue`,
130+
- `findAllByDisplayValue`,
113131

114132
## Known Limitations
115133

116-
- `waitForElement` method is not exposed. Playwright 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/playwright-testing-library/issues/3).
134+
- Async utilities `waitForElement`, `waitForElementToBeRemoved` and `waitForDomChange` are not exposed. Consider using a `find*` query.
117135
- `fireEvent` method is not exposed, use Playwright's built-ins instead.
118136
- `expect` assertion extensions are not available.
119137

lib/index.ts

+16
Original file line numberDiff line numberDiff line change
@@ -164,41 +164,57 @@ export function getQueriesForElement<T>(
164164
'queryAllByPlaceholderText',
165165
'getByPlaceholderText',
166166
'getAllByPlaceholderText',
167+
'findByPlaceholderText',
168+
'findAllByPlaceholderText',
167169

168170
'queryByText',
169171
'queryAllByText',
170172
'getByText',
171173
'getAllByText',
174+
'findByText',
175+
'findAllByText',
172176

173177
'queryByLabelText',
174178
'queryAllByLabelText',
175179
'getByLabelText',
176180
'getAllByLabelText',
181+
'findByLabelText',
182+
'findAllByLabelText',
177183

178184
'queryByAltText',
179185
'queryAllByAltText',
180186
'getByAltText',
181187
'getAllByAltText',
188+
'findByAltText',
189+
'findAllByAltText',
182190

183191
'queryByTestId',
184192
'queryAllByTestId',
185193
'getByTestId',
186194
'getAllByTestId',
195+
'findByTestId',
196+
'findAllByTestId',
187197

188198
'queryByTitle',
189199
'queryAllByTitle',
190200
'getByTitle',
191201
'getAllByTitle',
202+
'findByTitle',
203+
'findAllByTitle',
192204

193205
'queryByRole',
194206
'queryAllByRole',
195207
'getByRole',
196208
'getAllByRole',
209+
'findByRole',
210+
'findAllByRole',
197211

198212
'queryByDisplayValue',
199213
'queryAllByDisplayValue',
200214
'getByDisplayValue',
201215
'getAllByDisplayValue',
216+
'findByDisplayValue',
217+
'findAllByDisplayValue',
202218
]
203219
functionNames.forEach(functionName => {
204220
o[functionName] = createDelegateFor(functionName, contextFn)

lib/typedefs.ts

+113-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Matcher, MatcherOptions, SelectorMatcherOptions} from '@testing-library/dom'
1+
import {Matcher, MatcherOptions, SelectorMatcherOptions, waitForOptions} from '@testing-library/dom'
22
import {ElementHandle as PlaywrightElementHandle} from 'playwright'
33

44
export type ElementHandle = PlaywrightElementHandle<SVGElement | HTMLElement>
@@ -10,57 +10,160 @@ interface IQueryMethods {
1010
queryAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
1111
getByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
1212
getAllByPlaceholderText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
13+
findByPlaceholderText(
14+
el: Element,
15+
m: Matcher,
16+
opts?: SelectorMatcherOptions,
17+
waitForOpts?: waitForOptions,
18+
): Promise<Element>
19+
findAllByPlaceholderText(
20+
el: Element,
21+
m: Matcher,
22+
opts?: SelectorMatcherOptions,
23+
waitForOpts?: waitForOptions,
24+
): Promise<Element[]>
1325

1426
queryByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element | null>
1527
queryAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element[]>
1628
getByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element>
1729
getAllByText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element[]>
30+
findByText(
31+
el: Element,
32+
m: Matcher,
33+
opts?: SelectorMatcherOptions,
34+
waitForOpts?: waitForOptions,
35+
): Promise<Element>
36+
findAllByText(
37+
el: Element,
38+
m: Matcher,
39+
opts?: SelectorMatcherOptions,
40+
waitForOpts?: waitForOptions,
41+
): Promise<Element[]>
1842

1943
queryByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element | null>
2044
queryAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element[]>
2145
getByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element>
2246
getAllByLabelText(el: Element, m: Matcher, opts?: SelectorMatcherOptions): Promise<Element[]>
47+
findByLabelText(
48+
el: Element,
49+
m: Matcher,
50+
opts?: SelectorMatcherOptions,
51+
waitForOpts?: waitForOptions,
52+
): Promise<Element>
53+
findAllByLabelText(
54+
el: Element,
55+
m: Matcher,
56+
opts?: SelectorMatcherOptions,
57+
waitForOpts?: waitForOptions,
58+
): Promise<Element[]>
2359

2460
queryByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element | null>
2561
queryAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
2662
getByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
2763
getAllByAltText(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
64+
findByAltText(
65+
el: Element,
66+
m: Matcher,
67+
opts?: SelectorMatcherOptions,
68+
waitForOpts?: waitForOptions,
69+
): Promise<Element>
70+
findAllByAltText(
71+
el: Element,
72+
m: Matcher,
73+
opts?: SelectorMatcherOptions,
74+
waitForOpts?: waitForOptions,
75+
): Promise<Element[]>
2876

2977
queryByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element | null>
3078
queryAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
3179
getByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
3280
getAllByTestId(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
81+
findByTestId(
82+
el: Element,
83+
m: Matcher,
84+
opts?: SelectorMatcherOptions,
85+
waitForOpts?: waitForOptions,
86+
): Promise<Element>
87+
findAllByTestId(
88+
el: Element,
89+
m: Matcher,
90+
opts?: SelectorMatcherOptions,
91+
waitForOpts?: waitForOptions,
92+
): Promise<Element[]>
3393

3494
queryByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element | null>
3595
queryAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
3696
getByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
3797
getAllByTitle(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
98+
findByTitle(
99+
el: Element,
100+
m: Matcher,
101+
opts?: SelectorMatcherOptions,
102+
waitForOpts?: waitForOptions,
103+
): Promise<Element>
104+
findAllByTitle(
105+
el: Element,
106+
m: Matcher,
107+
opts?: SelectorMatcherOptions,
108+
waitForOpts?: waitForOptions,
109+
): Promise<Element[]>
38110

39111
queryByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element | null>
40112
queryAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
41113
getByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
42114
getAllByRole(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
115+
findByRole(
116+
el: Element,
117+
m: Matcher,
118+
opts?: SelectorMatcherOptions,
119+
waitForOpts?: waitForOptions,
120+
): Promise<Element>
121+
findAllByRole(
122+
el: Element,
123+
m: Matcher,
124+
opts?: SelectorMatcherOptions,
125+
waitForOpts?: waitForOptions,
126+
): Promise<Element[]>
43127

44128
queryByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element | null>
45129
queryAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
46130
getByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element>
47131
getAllByDisplayValue(el: Element, m: Matcher, opts?: MatcherOptions): Promise<Element[]>
48-
}
49-
50-
type IScopedQueryMethods = {
51-
[K in keyof IQueryMethods]: (
132+
findByDisplayValue(
133+
el: Element,
52134
m: Matcher,
53-
opts?: Parameters<IQueryMethods[K]>[2],
54-
) => ReturnType<IQueryMethods[K]>
135+
opts?: SelectorMatcherOptions,
136+
waitForOpts?: waitForOptions,
137+
): Promise<Element>
138+
findAllByDisplayValue(
139+
el: Element,
140+
m: Matcher,
141+
opts?: SelectorMatcherOptions,
142+
waitForOpts?: waitForOptions,
143+
): Promise<Element[]>
55144
}
56145

57-
export interface IScopedQueryUtils extends IScopedQueryMethods {
58-
getQueriesForElement(): IQueryUtils & IScopedQueryUtils
146+
export type BoundFunction<T> = T extends (
147+
attribute: string,
148+
element: Element,
149+
text: infer P,
150+
options: infer Q,
151+
) => infer R
152+
? (text: P, options?: Q) => R
153+
: T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer W) => infer R
154+
? (text: P, options?: Q, waitForElementOptions?: W) => R
155+
: T extends (a1: any, text: infer P, options: infer Q) => infer R
156+
? (text: P, options?: Q) => R
157+
: never
158+
export type BoundFunctions<T> = {[P in keyof T]: BoundFunction<T[P]>}
159+
160+
export interface IScopedQueryUtils extends BoundFunctions<IQueryMethods> {
161+
getQueriesForElement(): IScopedQueryUtils
59162
getNodeText(): Promise<string>
60163
}
61164

62165
export interface IQueryUtils extends IQueryMethods {
63-
getQueriesForElement(): IQueryUtils & IScopedQueryUtils
166+
getQueriesForElement(): IScopedQueryUtils
64167
getNodeText(el: Element): Promise<string>
65168
}
66169

test/extend.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,29 @@ describe('lib/extend.ts', () => {
116116
expect(await queryByText('Hello h3')).toBeTruthy()
117117
})
118118

119+
describe('deferred page', () => {
120+
beforeEach(async () => {
121+
await page.goto(`file://${path.join(__dirname, 'fixtures/late-page.html')}`)
122+
document = await page.getDocument()
123+
})
124+
125+
it('should handle the findBy* methods', async () => {
126+
expect(await document.findByText('Loaded!', {}, {timeout: 7000})).toBeTruthy()
127+
}, 9000)
128+
129+
it('should handle the findByAll* methods', async () => {
130+
const elements = await document.findAllByText(/Hello/, {}, {timeout: 7000})
131+
expect(elements).toHaveLength(2)
132+
133+
const text = await Promise.all([
134+
page.evaluate(el => el.textContent, elements[0]),
135+
page.evaluate(el => el.textContent, elements[1]),
136+
])
137+
138+
expect(text).toEqual(['Hello h1', 'Hello h2'])
139+
}, 9000)
140+
})
141+
119142
afterAll(async () => {
120143
await browser.close()
121144
})

test/fixtures/late-page.html

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
const loaded = document.createElement('span')
88
loaded.textContent = 'Loaded!'
99
document.body.appendChild(loaded)
10+
11+
const heading1 = document.createElement('h1')
12+
heading1.textContent = 'Hello h1'
13+
document.body.appendChild(heading1)
14+
15+
const heading2 = document.createElement('h2')
16+
heading2.textContent = 'Hello h2'
17+
document.body.appendChild(heading2)
1018
}, 5000)
1119
</script>
1220
</body>

0 commit comments

Comments
 (0)