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

Conversation

gitKrystan
Copy link
Collaborator

I compared the @types/ember__test-helpers package to the public API of this package to ensure we were:

  1. exporting the same things (aside from some of the missing exports I put in other PRs)
  2. not losing useful type info (e.g. the find overloads)

In the process I noticed a couple of minor issues w/ the types and fixed those as well.

LMK if you'd prefer I broke this up.

Copy link
Contributor

@chriskrycho chriskrycho left a comment

Choose a reason for hiding this comment

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

One tweak requested!

function getElement<K extends keyof SVGElementTagNameMap>(
target: K
): SVGElementTagNameMap[K] | null;
function getElement<E extends Element = Element>(target: string): E | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

I recognize these came from the DT types, but… this is terrible and we should not perpetuate its terribleness.

Suggested change
function getElement<E extends Element = Element>(target: string): E | null;
export default function getElement(selector: string): Element | null;

This change prevents people from “casting” it implicitly by writing getElement<HTMLDivElement>(). Although that's convenient, especially in tests, it's also quite misleading.

Comment on lines 10 to 12
export default function find<E extends Element = Element>(
selector: string
): E | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here!

Suggested change
export default function find<E extends Element = Element>(
selector: string
): E | null;
export default function find(selector: string): Element | null;

@@ -57,7 +57,7 @@ registerHook('triggerEvent', 'start', (target: Target, eventType: string) => {
export default function triggerEvent(
target: Target,
eventType: string,
options?: object
options?: Record<string, unknown>
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. 💙
  2. In the future, we should see if we can make this more specific, but it shouldn't block this change. Making it more accurate will "just" be a bug fix.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I did a deep dive on what the types should be, and options is just passed around willy nilly to a bunch of functions that take any, so figuring out the actual type will be a Project™️. I figured Record<string, unknown> was at least a little better than object and more consistent with another options type you specified for a similar test helper.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I could do something like Event & Record<string, unknown> bc I'm pretty sure it's mostly used for specifying details on the Event to be triggered, and I think that would at least give some hints about the types for things that exist on an Event.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Going to open a separate PR w/ the deep dive since I couldn't help myself. 😂

Copy link
Contributor

Choose a reason for hiding this comment

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

Hahaha I love it. Feels very https://xkcd.com/356/ 😂 "A Project™" sounds exactly right, though.

Comment on lines 49 to 53
BaseContext,
TestContext,
RenderingTestContext,
TestMetadata,
DebugInfo as InternalDebugInfo,
Copy link
Contributor

Choose a reason for hiding this comment

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

No harm done here, but for future reference: I try to keep things like these ordering changes separate from any meaningful changes—I just pull them into a separate commit, using git add --patch (though I always do that via a GUI because I find the text interface for it terrible)—so that it's clear what the meaningful change was. Here, for example, it took some extra reading and comparison to figure out that RenderingTestContext was the key change in this set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll just un-sort for now.

Re RenderingTestContext, should it be made public to consumers of this library? Currently it's not actually exported, so this import doesn't even work. I fix that in #1286, where the same issue came up for different reasons.

Copy link
Contributor

Choose a reason for hiding this comment

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

Per my note on #1286, I think exporting it is great. 👍🏼

): 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.

Copy link
Contributor

@chriskrycho chriskrycho left a comment

Choose a reason for hiding this comment

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

Noted one further pair of stylistic tweaks we should make, but looks good otherwise!

addon-test-support/@ember/test-helpers/dom/find-all.ts Outdated Show resolved Hide resolved
addon-test-support/@ember/test-helpers/dom/find.ts Outdated Show resolved Hide resolved
@@ -57,7 +57,7 @@ registerHook('triggerEvent', 'start', (target: Target, eventType: string) => {
export default function triggerEvent(
target: Target,
eventType: string,
options?: object
options?: Record<string, unknown>
Copy link
Contributor

Choose a reason for hiding this comment

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

Hahaha I love it. Feels very https://xkcd.com/356/ 😂 "A Project™" sounds exactly right, though.

Copy link
Contributor

@chriskrycho chriskrycho left a comment

Choose a reason for hiding this comment

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

I applied those tweaks via GH's review UI, so it's now ready to go. Thank you!

@gitKrystan
Copy link
Collaborator Author

Found a tiny bug in this one. Will fix w/o force pushing ;-)

@chriskrycho
Copy link
Contributor

All right, I fixed a merge conflict of my own creation, will merge once this is ✅ on CI!

@gitKrystan
Copy link
Collaborator Author

Should be all gouda now.

@chriskrycho chriskrycho merged commit db0df64 into emberjs:master Dec 15, 2022
@gitKrystan gitKrystan deleted the audit-types-package branch January 30, 2023 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants