From d918b3f094a4fe30dcdc8a3cb492ec39a419e6c9 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 26 Jan 2021 20:46:28 +0100 Subject: [PATCH 1/3] fix(render): Default to HTMLElement in returned container --- types/index.d.ts | 24 +++++++++++++++++------- types/test.tsx | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 8e0d1c02..574ded26 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -6,12 +6,16 @@ import { BoundFunction, prettyFormat, } from '@testing-library/dom' +import {Renderer} from 'react-dom' import {act as reactAct} from 'react-dom/test-utils' export * from '@testing-library/dom' -export type RenderResult = { - container: Element +export type RenderResult< + Q extends Queries = typeof queries, + Container extends Element | DocumentFragment = HTMLElement +> = { + container: Container baseElement: Element debug: ( baseElement?: @@ -26,8 +30,11 @@ export type RenderResult = { asFragment: () => DocumentFragment } & {[P in keyof Q]: BoundFunction} -export interface RenderOptions { - container?: Element +export interface RenderOptions< + Q extends Queries = typeof queries, + Container extends Element | DocumentFragment = HTMLElement +> { + container?: Container baseElement?: Element hydrate?: boolean queries?: Q @@ -43,10 +50,13 @@ export function render( ui: React.ReactElement, options?: Omit, ): RenderResult -export function render( +export function render< + Q extends Queries, + Container extends Element | DocumentFragment = HTMLElement +>( ui: React.ReactElement, - options: RenderOptions, -): RenderResult + options: RenderOptions, +): RenderResult /** * Unmounts React trees that were mounted with render. diff --git a/types/test.tsx b/types/test.tsx index 1366caac..58c122f4 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -17,6 +17,7 @@ export async function testRender() { // helpers const {container, rerender, debug} = page + expectType(container) return {container, rerender, debug} } @@ -35,13 +36,18 @@ export async function testPureRender() { // helpers const {container, rerender, debug} = page + expectType(container) return {container, rerender, debug} } export function testRenderOptions() { const container = document.createElement('div') const options = {container} - render(
, options) + const {container: returnedContainer} = render(
, options) + // Unclear why TypeScript infers `HTMLElement` here when the the input `container` is `HTMLDivElement` + // Hopefully this breaks someday and we can switch to + // expectType(returnedContainer) + expectType(returnedContainer) } export function testSVGRenderOptions() { @@ -50,7 +56,8 @@ export function testSVGRenderOptions() { 'svg', ) const options = {container} - render(, options) + const {container: returnedContainer} = render(, options) + expectType(returnedContainer) } export function testFireEvent() { @@ -87,3 +94,27 @@ eslint testing-library/no-debug: "off", testing-library/prefer-screen-queries: "off" */ + +// https://stackoverflow.com/questions/53807517/how-to-test-if-two-types-are-exactly-the-same +type IfEquals = (() => G extends T + ? 1 + : 2) extends () => G extends U ? 1 : 2 + ? Yes + : No + +/** + * Issues a type error if `Expected` is not identical to `Actual`. + * + * `Expected` should be declared when invoking `expectType`. + * `Actual` should almost always we be a `typeof value` statement. + * + * Source: https://github.com/mui-org/material-ui/blob/6221876a4b468a3330ffaafa8472de7613933b87/packages/material-ui-types/index.d.ts#L73-L84 + * + * @example `expectType(value)` + * TypeScript issues a type error since `value is not assignable to never`. + * This means `typeof value` is not identical to `number | string` + * @param actual + */ +declare function expectType( + actual: IfEquals, +): void From b9836da4d4d2c26494f53b3b6cb629799774615b Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 27 Jan 2021 22:48:43 +0100 Subject: [PATCH 2/3] Clarify difference between rendered element and container --- types/test.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/types/test.tsx b/types/test.tsx index 58c122f4..0d3f172b 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -3,7 +3,7 @@ import {render, fireEvent, screen, waitFor} from '.' import * as pure from './pure' export async function testRender() { - const page = render(
) + const page = render(