Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port some conveniences from @types/ember__test-helpers package #1287

Merged
merged 6 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion addon-test-support/@ember/test-helpers/dom/-get-element.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import getRootElement from './get-root-element';
import Target, { isDocument, isElement } from './-target';

function getElement<
K extends keyof (HTMLElementTagNameMap | SVGElementTagNameMap)
>(target: K): (HTMLElementTagNameMap | SVGElementTagNameMap)[K] | null;
function getElement<K extends keyof HTMLElementTagNameMap>(
target: K
): HTMLElementTagNameMap[K] | null;
function getElement<K extends keyof SVGElementTagNameMap>(
target: K
): SVGElementTagNameMap[K] | null;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These types started as copy-pasta from the built-in querySelector types, which look like this:

    /** Returns the first element that is a descendant of node that matches selectors. */
    querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
    querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
    querySelector<E extends Element = Element>(selectors: string): E | null;

...but as @chriskrycho pointed out here, those types aren't that great.

Since we're diverging from them a bit by removing the generic from the target: string overload, I decided to also fix a type bug from those types, which is this:

HTMLElementTagNameMap and SVGElementTagNameMap have some overlap in keys, e.g. a is a valid tag in both. In the built-in querySelector types, the return type for target: 'a' would always be an HTMLAnchorElement, when the actual value might actually be a SVGAElement. So I added a third overload to account for that overlap. You can see the results in the type-tests.

function getElement<E extends Element = Element>(target: string): E | null;
function getElement(target: string): Element | null;
function getElement(target: Element): Element;
function getElement(target: Document): Document;
function getElement(target: Window): Document;
Expand Down
3 changes: 3 additions & 0 deletions addon-test-support/@ember/test-helpers/dom/find-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { toArray } from '../ie-11-polyfills';
// would simply be defined as a tweaked re-export as `querySelector` is, but it
// is non-trivial (to say the least!) to preserve overloads like this while also
// changing the return type (from `NodeListOf` to `Array`).
export default function findAll<
K extends keyof (HTMLElementTagNameMap | SVGElementTagNameMap)
>(selector: K): Array<(HTMLElementTagNameMap | SVGElementTagNameMap)[K]>;
chriskrycho marked this conversation as resolved.
Show resolved Hide resolved
export default function findAll<K extends keyof HTMLElementTagNameMap>(
selector: K
): Array<HTMLElementTagNameMap[K]>;
Expand Down
7 changes: 4 additions & 3 deletions addon-test-support/@ember/test-helpers/dom/find.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import getElement from './-get-element';

// Derived from `querySelector` types.
export default function find<
K extends keyof (HTMLElementTagNameMap | SVGElementTagNameMap)
>(selector: K): (HTMLElementTagNameMap | SVGElementTagNameMap)[K] | null;
chriskrycho marked this conversation as resolved.
Show resolved Hide resolved
export default function find<K extends keyof HTMLElementTagNameMap>(
selector: K
): HTMLElementTagNameMap[K] | null;
export default function find<K extends keyof SVGElementTagNameMap>(
selector: K
): SVGElementTagNameMap[K] | null;
export default function find<E extends Element = Element>(
selector: string
): E | null;
export default function find(selector: string): Element | null;
/**
Find the first element matched by the given selector. Equivalent to calling
`querySelector()` on the test root element.
Expand Down
1 change: 1 addition & 0 deletions addon-test-support/@ember/test-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export {
default as setupRenderingContext,
render,
clearRender,
RenderingTestContext,
} from './setup-rendering-context';
export { default as rerender } from './rerender';
export {
Expand Down
14 changes: 8 additions & 6 deletions type-tests/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ import {
unsetContext,
teardownContext,
setupRenderingContext,
BaseContext,
TestContext,
RenderingTestContext,
TestMetadata,
DebugInfo as InternalDebugInfo,
getApplication,
setApplication,
setupApplicationContext,
Expand All @@ -63,6 +59,10 @@ import {
getDeprecationsDuringCallback,
getWarnings,
getWarningsDuringCallback,
BaseContext,
TestContext,
TestMetadata,
DebugInfo as InternalDebugInfo,
DeprecationFailure,
Warning,
} from '@ember/test-helpers';
Expand Down Expand Up @@ -132,11 +132,13 @@ expectTypeOf(typeIn).toEqualTypeOf<

// DOM Query Helpers
expectTypeOf(find).toEqualTypeOf<Document['querySelector']>();
expectTypeOf(find('a')).toEqualTypeOf<HTMLAnchorElement | null>();
expectTypeOf(find('a')).toEqualTypeOf<HTMLAnchorElement | SVGAElement | null>();
expectTypeOf(find('div')).toEqualTypeOf<HTMLDivElement | null>();
expectTypeOf(find('circle')).toEqualTypeOf<SVGCircleElement | null>();
expectTypeOf(find('.corkscrew')).toEqualTypeOf<Element | null>();
expectTypeOf(findAll).toEqualTypeOf<(selector: string) => Array<Element>>();
expectTypeOf(findAll('a')).toEqualTypeOf<HTMLAnchorElement[]>();
expectTypeOf(findAll('a')).toEqualTypeOf<(HTMLAnchorElement | SVGAElement)[]>();
expectTypeOf(findAll('div')).toEqualTypeOf<HTMLDivElement[]>();
expectTypeOf(findAll('circle')).toEqualTypeOf<SVGCircleElement[]>();
expectTypeOf(findAll('.corkscrew')).toEqualTypeOf<Element[]>();
expectTypeOf(getRootElement).toEqualTypeOf<() => Element | Document>();
Expand Down