Skip to content

Commit

Permalink
Update dependency @testing-library/dom to v8.7.1 (#265)
Browse files Browse the repository at this point in the history
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Caleb Eby <caleb.eby01@gmail.com>
  • Loading branch information
3 people authored Nov 19, 2021
1 parent 1fb7a3c commit 2b92fbc
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 45 deletions.
26 changes: 26 additions & 0 deletions .changeset/calm-houses-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
'pleasantest': minor
---

Update `@testing-library/dom` to [`v8.11.1`](https://github.com/testing-library/dom-testing-library/releases/tag/v8.11.1)

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.

Notably, we have added the ability for TypeScript users to optionally specify an element type as a type parameter for DTL queries:

```ts
import { withBrowser } from 'pleasantest';

test(
'changelog example',
withBrowser(async ({ screen }) => {
// ElementHandle<HTMLButtonElement>
const button = await screen.getByRole<HTMLButtonElement>(/button/);

// ElementHandle<HTMLButtonElement>[]
const buttons = await screen.getAllByRole<HTMLButtonElement>(/button/);
}),
);
```

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<...>>>`.
5 changes: 0 additions & 5 deletions .changeset/wise-apricots-allow.md

This file was deleted.

49 changes: 32 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@rollup/plugin-alias": "3.1.8",
"@rollup/plugin-babel": "5.3.0",
"@rollup/plugin-node-resolve": "13.0.6",
"@testing-library/dom": "8.6.0",
"@testing-library/dom": "8.11.1",
"@testing-library/jest-dom": "5.15.0",
"@types/jest": "27.0.2",
"@types/node": "12.20.37",
Expand Down
41 changes: 29 additions & 12 deletions src/pptr-testing-library.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,42 @@
import type { queries, BoundFunctions } from '@testing-library/dom';
import type { queries } from '@testing-library/dom';
import { jsHandleToArray, removeFuncFromStackTrace } from './utils';
import type { JSHandle } from 'puppeteer';
import type { ElementHandle, JSHandle } from 'puppeteer';
import { createClientRuntimeServer } from './module-server/client-runtime-server';
import type { AsyncHookTracker } from './async-hooks';

type ElementToElementHandle<Input> = Input extends Element
? import('puppeteer').ElementHandle
: Input extends Element[]
? import('puppeteer').ElementHandle[]
? ElementHandle<Input>
: Input extends (Element | ElementHandle)[]
? { [K in keyof Input]: ElementToElementHandle<Input[K]> }
: Input;

type Promisify<Input> = Input extends Promise<any> ? Input : Promise<Input>;

type UpdateReturnType<Fn> = Fn extends (...args: infer Args) => infer ReturnType
? (...args: Args) => Promisify<ElementToElementHandle<ReturnType>>
type ValueOf<Input> = Input extends any[] ? Input[number] : Input[keyof Input];
type UnArray<Input> = Input extends any[] ? Input[number] : Input;
type UnPromise<Input> = Input extends Promise<infer Inner> ? Inner : Input;
/**
* Changes type signature of an original testing library query function by:
* - Removing the `container` parameter
* - Returning a promise, always
* - Returning ElementHandles instead of Elements
*/
type ChangeDTLFn<DTLFn extends ValueOf<typeof queries>> = DTLFn extends (
container: HTMLElement,
...args: infer Args
) => infer DTLReturn
? <CustomizedReturn extends UnArray<UnPromise<DTLReturn>>>(
...args: Args
) => Promisify<
ElementToElementHandle<
UnPromise<DTLReturn> extends any[]
? CustomizedReturn[]
: CustomizedReturn
>
>
: never;

type AsyncDTLQueries = {
[K in keyof typeof queries]: UpdateReturnType<typeof queries[K]>;
export type BoundQueries = {
[K in keyof typeof queries]: ChangeDTLFn<typeof queries[K]>;
};

const queryNames = [
Expand Down Expand Up @@ -77,8 +96,6 @@ interface DTLError {
messageWithElementsStringified: string;
}

export type BoundQueries = BoundFunctions<AsyncDTLQueries>;

export const getQueriesForElement = (
page: import('puppeteer').Page,
asyncHookTracker: AsyncHookTracker,
Expand Down
3 changes: 2 additions & 1 deletion src/rollup-plugin-aria-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export const rollupPluginAriaQuery = () => ({
const getAriaQueryCode = async () => {
const q = await import('aria-query');
return `export const roles = ${stringify(q.roles)};
export const elementRoles = ${stringify(q.elementRoles)};`;
export const elementRoles = ${stringify(q.elementRoles)};
export const roleElements = ${stringify(q.roleElements)};`;
};

const stringify = (input) => {
Expand Down
8 changes: 4 additions & 4 deletions tests/jest-dom-matchers/toBePartiallyChecked.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { ElementHandle } from 'puppeteer';
import { withBrowser } from 'pleasantest';

test(
Expand Down Expand Up @@ -30,9 +29,10 @@ test(
const ariaCheckboxUnchecked = await screen.getByTestId(
'aria-checkbox-unchecked',
);
const inputCheckboxIndeterminate = (await screen.getByTestId(
'input-checkbox-indeterminate',
)) as ElementHandle<HTMLInputElement>;
const inputCheckboxIndeterminate =
await screen.getByTestId<HTMLInputElement>(
'input-checkbox-indeterminate',
);

await expect(ariaCheckboxMixed).toBePartiallyChecked();

Expand Down
5 changes: 1 addition & 4 deletions tests/jest-dom-matchers/toHaveFocus.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { ElementHandle } from 'puppeteer';
import { withBrowser } from 'pleasantest';

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

const input: ElementHandle<HTMLElement> = await screen.getByTestId(
'element-to-focus',
);
const input = await screen.getByTestId('element-to-focus');

await input.focus();
await expect(input).toHaveFocus();
Expand Down
36 changes: 35 additions & 1 deletion tests/testing-library-queries/variants-of-queries.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ElementHandle } from 'pleasantest';
import { withBrowser } from 'pleasantest';

const singleElementMarkup = `
Expand All @@ -9,12 +10,37 @@ const multipleElementMarkup = `
<h1>Hello</h1>
`;

// @ts-expect-error T1 is intentionally unused, assertType is only used at type-time
const assertType = <T1 extends true>() => {};

// Checks if two types are equal (A extends B and B extends A)
// Contains special case for ElementHandle's,
// where ElementHandle<A> extends ElementHandle<B> even if A does not extend A
type Equal<A, B> = A extends (infer T1)[]
? B extends (infer T2)[]
? Equal<T1, T2>
: false
: A extends ElementHandle<infer T1>
? B extends ElementHandle<infer T2>
? Equal<T1, T2>
: false
: B extends A
? A extends B
? true
: false
: false;

test(
'findBy',
withBrowser(async ({ screen, utils }) => {
// This should work because findByText waits for up to 1s to see the element
setTimeout(() => utils.injectHTML(singleElementMarkup), 5);
await screen.findByText(/Hello/);

const t1 = await screen.findByText(/Hello/);
assertType<Equal<ElementHandle<HTMLElement>, typeof t1>>();

const t2 = await screen.findByText<HTMLInputElement>(/Hello/);
assertType<Equal<ElementHandle<HTMLInputElement>, typeof t2>>();

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

const t1 = await screen.findAllByText(/Hello/);
assertType<Equal<ElementHandle<HTMLElement>[], typeof t1>>();

const t2 = await screen.findAllByText<HTMLHeadingElement>(/Hello/);
assertType<Equal<ElementHandle<HTMLHeadingElement>[], typeof t2>>();

assertType<Equal<typeof t1, ElementHandle<HTMLElement>[]>>();

await expect(screen.findAllByText(/Hellooooo/, {}, { timeout: 5 })).rejects
.toThrowErrorMatchingInlineSnapshot(`
"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.
Expand Down

0 comments on commit 2b92fbc

Please sign in to comment.