-
Notifications
You must be signed in to change notification settings - Fork 78
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
Better Harness and Assertion Template support for render props #529
Comments
ProblemWhen working with the testing harness there is no built in support for working with render properties and as a result requires workarounds using the
This is due to import { create, tsx } from "@dojo/framework/core/vdom";
import assertionTemplate from "@dojo/framework/testing/assertionTemplate";
import harness from "@dojo/framework/testing/harness";
import { RenderResult } from "@dojo/framework/core/interfaces";
const rendererFactory = create().properties<{
renderer: (text: string) => RenderResult;
}>();
const MyRenderingWidget = rendererFactory(function MyRenderingWidget({
properties
}) {
const { renderer } = properties();
return <div>{renderer("hello")}</div>;
});
const factory = create();
const MyWidget = factory(function MyWidget() {
return (
<div>
<span>content</span>
<MyRenderingWidget
key="renderer"
renderer={value => {
return <div>{`${value}, renderer`}</div>;
}}
/>
</div>
);
});
const baseAssertion = assertionTemplate(() => {
return (
<div>
<span>content</span>
<MyRenderingWidget key="renderer" renderer={() => undefined} />
</div>
);
});
const h = harness(() => <MyWidget />);
// base assertion does not include the renderer content
h.expect(baseAssertion);
// opaque selector for calling the renderer function, no typings for the
// functions arguments
const result = h.trigger("@renderer", "renderer", "hello");
// a second template is required to assert the renderers output
const rendererAssertion = assertionTemplate(() => <div>hello, renderer</div>);
// using expect with both an expected and actual result
// that is returned from the trigger
h.expect(rendererAssertion, () => result); ProposalDojo 7 introduces support for typed children when using function-based components, this is the recommended way to implement functionality that could previously only be done using render props. With this core support the harness should be enhanced to be able to test the expected output from the functional children in an ergonomic and typed way. To do this the harness requires a way to identify nodes in the widgets output and render resolve the functional children inline. A way to support this is to provide a wrapping function for when they want to assert the return of functional children. This wrapped value would be used in the expected tree in place of the actual expected widget. This will enable the harness to be able to take instructions for the wrapped nodes and resolve them at assertion time. It also means that the harness can provide typings for the functional children and parameters. import { create, tsx } from "@dojo/framework/core/vdom";
import assertionTemplate from "@dojo/framework/testing/assertionTemplate";
import harness, { wrap } from "@dojo/framework/testing/harness";
import { RenderResult } from "@dojo/framework/core/interfaces";
const rendererFactory = create().children<(text: string) => RenderResult>();
const MyRenderingWidget = rendererFactory(function MyRenderingWidget({ children }) {
const [renderer] = children();
return <div>{renderer("hello")}</div>;
});
const factory = create();
const MyWidget = factory(function MyWidget() {
return (
<div>
<span>content</span>
<MyRenderingWidget>{(value) => <div>{`${value}, renderer`}</div>}</MyRenderingWidget>
</div>
);
});
const WrappedMyRenderingWidget = wrap(MyRenderingWidget);
const baseAssertion = assertionTemplate(() => {
return (
<div>
<span>content</span>
<WrappedMyRenderingWidget>{() => <div>hello, renderer</div>}</WrappedMyRenderingWidget>
</div>
);
});
const h = harness(() => <MyWidget />);
// child API that instructs the harness to resolve the expected and actual child
// during the assertion. The children function parameters are typed appropriately
h.child(WrappedMyRenderingWidget, ['hello']);
// single assertion against the assertion template
h.expect(baseAssertion); Creating "wrapped" widgets enables the harness to track the required instructions and resolve them automatically during the assertion. As well as children, the wrapped widgets can be used to call node properties during the expectation providing the same type safety as provided by the |
Enhancement
Assertion Templates have made creating/modifying assertions a lot easier for testing, but it's still really difficult to call and assert against render props, which mostly involves abusing the
trigger
func and asserting rawDNode
s rather than using an Assertion Template. It would be nice to improve the ergonomics of this so a user can write these the same as any other Assertion Template.This might be more achievable with: #528
The text was updated successfully, but these errors were encountered: