-
Notifications
You must be signed in to change notification settings - Fork 123
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
feat(qunit-dom): Ability to add custom dom
handlers
#2101
base: master
Are you sure you want to change the base?
Conversation
e21dc51
to
8384d74
Compare
Continuing this discussion after speaking with @mansona and the tooling team today: The working proposalIt sounds like we're going to iterate on this to allow the configuration of only a single assertion handler, and then will expose the built-in assertion handler so callers can wrap it, so the unit test's custom handler would look like: import { qunitDomAssertionHandler } from '../assertions';
const customHandler: DOMAssertionsHandler<u32> = {
findElements(target: u32, rootElement: RootElement) {
if (typeof target === 'number') {
return { ok: true, value: toArray(rootElement.querySelectorAll(`[data-id="${target}"]`)) };
} else {
return qunitDomAssertionHandler.findElements(target, rootElement);
}
},
findElement(target: u32, rootElement: RootElement) {
if (typeof target === 'number') {
return { ok: true, value: rootElement.querySelector(`[data-id="${target}"]`) };
} else {
return qunitDomAssertionHandler.findElement(target, rootElement);
}
},
description(target: u32) {
if (target >= 200) {
return { ok: true, value: `data-id=${target}` };
} else if (target <= 100) {
return { ok: true, value: target };
} else {
return qunitDomAssertionHandler.description(target);
}
},
}; So then the integration would involve making import { setup } from 'qunit-dom';
setup(QUnit.assert, {
customHandler: /* something goes here */
}); My open questionMy question is what is the I see a couple of options: The app/blueprintThis would involve modifying the blueprint to have the import {
setup,
qunitDomAssertionHandler,
type DOMAssertionsHandler,
} from 'qunit-dom';
import {
isDescriptor,
resolveDOMElement,
resolveDOMElements,
resolveDescription,
type IDOMElementDescriptor,
} from 'dom-element-descriptors';
type Target =
| IDOMElementDescriptor
| Parameters<(typeof qunitDomAssertionHandler)['findElement']>[0];
const customHandler: DOMAssertionsHandler<Target> = {
findElement(target, rootElement) {
return isDescriptor(target)
? { ok: true, value: resolveDOMElement(target) }
: qunitDomAssertionHandler.findElement(target, rootElement);
},
findElements(target, rootElement) {
return isDescriptor(target)
? { ok: true, value: Array.from(resolveDOMElements(target)) }
: qunitDomAssertionHandler.findElements(target, rootElement);
},
description(target) {
return isDescriptor(target)
? { ok: true, value: resolveDescription(target) || '' }
: qunitDomAssertionHandler.description(target);
},
};
setup(QUnit.assert, { customHandler }); We could improve the ergonomics of this by reorganizing the types a little, or perhaps by having the blueprint generate a separate file with the custom handler definition, but regardless, with this option we'd be adding a good deal of blueprint-generated code to applications.
|
It also looks like we'd need to add something like declare global {
interface Assert {
dom(target?: IDOMElementDescriptor, rootElement?: Element): DOMAssertions;
}
} where the integration happens in order to make the types actually work. They work in the unit test because it constructs a TestAssertions instance directly, but that has no impact on the global |
I've re-implemented the handler so the previous examples are out of date; especially since for both Typescript and overall experience we should keep only one instance of a handler as opposed to having a resolver pipeline.
That responsibility should fall upon anyone who's using the qunit-dom and wants to introduce a handler for different import { setup } from 'qunit-dom';
import { qunitDomAssertionHandler } from 'dom-element-descriptors';
setup(QUnit.assert, {
targetHandler: qunitDomAssertionHandler
}); However to my understanding that also requires the user to change their Alternatively, if the |
@@ -28,11 +28,56 @@ type CSSStyleDeclarationProperty = keyof CSSStyleDeclaration; | |||
|
|||
type ActualCSSStyleDeclaration = Partial<Record<CSSStyleDeclarationProperty, unknown>>; | |||
|
|||
type FoundElement = Element | 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 think this isn't going to work? This allows findElements()
to return an array that could have a mix of Element
s and null
, which doesn't seem right. I see the built-in handler is currently returning [null] when it is passed a null
target, but this is causing a bug in matchesSelector()
and doesNotMatchSelector()
as the tests I added in #2107 demonstrate (if they were merged/copied into this branch).
I think findElements
needs to just return Element[]
, and we need to return []
in the target === null
case of findElements()
.
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.
Good catch 👍
Okay, thanks for updating the code to the single-handler model! It looks to me like my above analysis still stands -- for Ember apps to be able to follow the RFC and use |
No description provided.