Skip to content

Commit 2b92fbc

Browse files
renovate[bot]renovate-botcalebeby
authored
Update dependency @testing-library/dom to v8.7.1 (#265)
Co-authored-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: Caleb Eby <caleb.eby01@gmail.com>
1 parent 1fb7a3c commit 2b92fbc

9 files changed

Lines changed: 130 additions & 45 deletions

File tree

.changeset/calm-houses-do.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
'pleasantest': minor
3+
---
4+
5+
Update `@testing-library/dom` to [`v8.11.1`](https://github.com/testing-library/dom-testing-library/releases/tag/v8.11.1)
6+
7+
Read their [release notes](https://github.com/testing-library/dom-testing-library/releases) for all the versions between 8.1.0 and 8.11.1 to see the full changes.
8+
9+
Notably, we have added the ability for TypeScript users to optionally specify an element type as a type parameter for DTL queries:
10+
11+
```ts
12+
import { withBrowser } from 'pleasantest';
13+
14+
test(
15+
'changelog example',
16+
withBrowser(async ({ screen }) => {
17+
// ElementHandle<HTMLButtonElement>
18+
const button = await screen.getByRole<HTMLButtonElement>(/button/);
19+
20+
// ElementHandle<HTMLButtonElement>[]
21+
const buttons = await screen.getAllByRole<HTMLButtonElement>(/button/);
22+
}),
23+
);
24+
```
25+
26+
The return type is automatically determined based on the specified element type. Since Pleasantest DTL queries return `ElementHandle`s, the return type will be wrapped with `Promise<ElementHandle<...>>`. For queries which return arrays of elements, the singular version of the element type is accepted as the type parameter, and the return type will automatically be wrapped with `Promise<Array<ElementHandle<...>>>`.

.changeset/wise-apricots-allow.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

package-lock.json

Lines changed: 32 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"@rollup/plugin-alias": "3.1.8",
2020
"@rollup/plugin-babel": "5.3.0",
2121
"@rollup/plugin-node-resolve": "13.0.6",
22-
"@testing-library/dom": "8.6.0",
22+
"@testing-library/dom": "8.11.1",
2323
"@testing-library/jest-dom": "5.15.0",
2424
"@types/jest": "27.0.2",
2525
"@types/node": "12.20.37",

src/pptr-testing-library.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
import type { queries, BoundFunctions } from '@testing-library/dom';
1+
import type { queries } from '@testing-library/dom';
22
import { jsHandleToArray, removeFuncFromStackTrace } from './utils';
3-
import type { JSHandle } from 'puppeteer';
3+
import type { ElementHandle, JSHandle } from 'puppeteer';
44
import { createClientRuntimeServer } from './module-server/client-runtime-server';
55
import type { AsyncHookTracker } from './async-hooks';
66

77
type ElementToElementHandle<Input> = Input extends Element
8-
? import('puppeteer').ElementHandle
9-
: Input extends Element[]
10-
? import('puppeteer').ElementHandle[]
8+
? ElementHandle<Input>
9+
: Input extends (Element | ElementHandle)[]
10+
? { [K in keyof Input]: ElementToElementHandle<Input[K]> }
1111
: Input;
1212

1313
type Promisify<Input> = Input extends Promise<any> ? Input : Promise<Input>;
14-
15-
type UpdateReturnType<Fn> = Fn extends (...args: infer Args) => infer ReturnType
16-
? (...args: Args) => Promisify<ElementToElementHandle<ReturnType>>
14+
type ValueOf<Input> = Input extends any[] ? Input[number] : Input[keyof Input];
15+
type UnArray<Input> = Input extends any[] ? Input[number] : Input;
16+
type UnPromise<Input> = Input extends Promise<infer Inner> ? Inner : Input;
17+
/**
18+
* Changes type signature of an original testing library query function by:
19+
* - Removing the `container` parameter
20+
* - Returning a promise, always
21+
* - Returning ElementHandles instead of Elements
22+
*/
23+
type ChangeDTLFn<DTLFn extends ValueOf<typeof queries>> = DTLFn extends (
24+
container: HTMLElement,
25+
...args: infer Args
26+
) => infer DTLReturn
27+
? <CustomizedReturn extends UnArray<UnPromise<DTLReturn>>>(
28+
...args: Args
29+
) => Promisify<
30+
ElementToElementHandle<
31+
UnPromise<DTLReturn> extends any[]
32+
? CustomizedReturn[]
33+
: CustomizedReturn
34+
>
35+
>
1736
: never;
1837

19-
type AsyncDTLQueries = {
20-
[K in keyof typeof queries]: UpdateReturnType<typeof queries[K]>;
38+
export type BoundQueries = {
39+
[K in keyof typeof queries]: ChangeDTLFn<typeof queries[K]>;
2140
};
2241

2342
const queryNames = [
@@ -77,8 +96,6 @@ interface DTLError {
7796
messageWithElementsStringified: string;
7897
}
7998

80-
export type BoundQueries = BoundFunctions<AsyncDTLQueries>;
81-
8299
export const getQueriesForElement = (
83100
page: import('puppeteer').Page,
84101
asyncHookTracker: AsyncHookTracker,

src/rollup-plugin-aria-query.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export const rollupPluginAriaQuery = () => ({
1313
const getAriaQueryCode = async () => {
1414
const q = await import('aria-query');
1515
return `export const roles = ${stringify(q.roles)};
16-
export const elementRoles = ${stringify(q.elementRoles)};`;
16+
export const elementRoles = ${stringify(q.elementRoles)};
17+
export const roleElements = ${stringify(q.roleElements)};`;
1718
};
1819

1920
const stringify = (input) => {

tests/jest-dom-matchers/toBePartiallyChecked.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { ElementHandle } from 'puppeteer';
21
import { withBrowser } from 'pleasantest';
32

43
test(
@@ -30,9 +29,10 @@ test(
3029
const ariaCheckboxUnchecked = await screen.getByTestId(
3130
'aria-checkbox-unchecked',
3231
);
33-
const inputCheckboxIndeterminate = (await screen.getByTestId(
34-
'input-checkbox-indeterminate',
35-
)) as ElementHandle<HTMLInputElement>;
32+
const inputCheckboxIndeterminate =
33+
await screen.getByTestId<HTMLInputElement>(
34+
'input-checkbox-indeterminate',
35+
);
3636

3737
await expect(ariaCheckboxMixed).toBePartiallyChecked();
3838

tests/jest-dom-matchers/toHaveFocus.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { ElementHandle } from 'puppeteer';
21
import { withBrowser } from 'pleasantest';
32

43
test(
@@ -8,9 +7,7 @@ test(
87
`<div><input type="text" data-testid="element-to-focus" /></div>`,
98
);
109

11-
const input: ElementHandle<HTMLElement> = await screen.getByTestId(
12-
'element-to-focus',
13-
);
10+
const input = await screen.getByTestId('element-to-focus');
1411

1512
await input.focus();
1613
await expect(input).toHaveFocus();

tests/testing-library-queries/variants-of-queries.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ElementHandle } from 'pleasantest';
12
import { withBrowser } from 'pleasantest';
23

34
const singleElementMarkup = `
@@ -9,12 +10,37 @@ const multipleElementMarkup = `
910
<h1>Hello</h1>
1011
`;
1112

13+
// @ts-expect-error T1 is intentionally unused, assertType is only used at type-time
14+
const assertType = <T1 extends true>() => {};
15+
16+
// Checks if two types are equal (A extends B and B extends A)
17+
// Contains special case for ElementHandle's,
18+
// where ElementHandle<A> extends ElementHandle<B> even if A does not extend A
19+
type Equal<A, B> = A extends (infer T1)[]
20+
? B extends (infer T2)[]
21+
? Equal<T1, T2>
22+
: false
23+
: A extends ElementHandle<infer T1>
24+
? B extends ElementHandle<infer T2>
25+
? Equal<T1, T2>
26+
: false
27+
: B extends A
28+
? A extends B
29+
? true
30+
: false
31+
: false;
32+
1233
test(
1334
'findBy',
1435
withBrowser(async ({ screen, utils }) => {
1536
// This should work because findByText waits for up to 1s to see the element
1637
setTimeout(() => utils.injectHTML(singleElementMarkup), 5);
17-
await screen.findByText(/Hello/);
38+
39+
const t1 = await screen.findByText(/Hello/);
40+
assertType<Equal<ElementHandle<HTMLElement>, typeof t1>>();
41+
42+
const t2 = await screen.findByText<HTMLInputElement>(/Hello/);
43+
assertType<Equal<ElementHandle<HTMLInputElement>, typeof t2>>();
1844

1945
await expect(screen.findByText(/Hellooooo/, {}, { timeout: 5 })).rejects
2046
.toThrowErrorMatchingInlineSnapshot(`
@@ -106,6 +132,14 @@ test(
106132
setTimeout(() => utils.injectHTML(singleElementMarkup), 5);
107133
expect(await screen.findAllByText(/Hello/)).toHaveLength(1);
108134

135+
const t1 = await screen.findAllByText(/Hello/);
136+
assertType<Equal<ElementHandle<HTMLElement>[], typeof t1>>();
137+
138+
const t2 = await screen.findAllByText<HTMLHeadingElement>(/Hello/);
139+
assertType<Equal<ElementHandle<HTMLHeadingElement>[], typeof t2>>();
140+
141+
assertType<Equal<typeof t1, ElementHandle<HTMLElement>[]>>();
142+
109143
await expect(screen.findAllByText(/Hellooooo/, {}, { timeout: 5 })).rejects
110144
.toThrowErrorMatchingInlineSnapshot(`
111145
"Unable to find an element with the text: /Hellooooo/. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

0 commit comments

Comments
 (0)