-
-
Notifications
You must be signed in to change notification settings - Fork 260
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
Conversation
e.g. convenient overloads for `find`
There was a problem hiding this 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; |
There was a problem hiding this comment.
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.
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.
export default function find<E extends Element = Element>( | ||
selector: string | ||
): E | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here!
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 💙
- 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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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. 😂
There was a problem hiding this comment.
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.
type-tests/api.ts
Outdated
BaseContext, | ||
TestContext, | ||
RenderingTestContext, | ||
TestMetadata, | ||
DebugInfo as InternalDebugInfo, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this 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!
@@ -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> |
There was a problem hiding this comment.
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.
There was a problem hiding this 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!
Found a tiny bug in this one. Will fix w/o force pushing ;-) |
All right, I fixed a merge conflict of my own creation, will merge once this is ✅ on CI! |
Should be all gouda now. |
I compared the
@types/ember__test-helpers
package to the public API of this package to ensure we were: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.