Closed lcpriest closed 5 years ago
There is not a super easy API for doing this yet, although it's being worked on and is high priority once all of the recent performance-related work stabilizes.
If you have the appetite for hacking on low-level VM APIs, there is theoretically a way to do this today.
The core Glimmer "initial render loop" happens when you create a template iterator and call .next()
on it until it is done. (example)
The template iterator encapsulates a few different pieces of state required to perform the render. One of these things is the "main" or "root" template—the entry point where Glimmer starts rendering. Note that this is a very simple template only; there's no associated component. (example, glimmer.js main template)
So if there's no component, how does the template get data? If I type {{someVal}}
in the root template, where does someVal
come from?
Specifically for the root template, that comes from a special Reference
we call "self."
In Glimmer.js apps, self
is a reference that contains an array, _roots
, which is a list of metadata for every component that you've rendered via renderComponent
. (example)
If we combine these concepts, it should be possible to build a test helper that:
<FeedbackForm @rating={{rating}} />
.self
reference that wraps { rating: 10 }
(or whatever args you might want to pass).self
plus the other state/configuration in the example above into a new template iterator and renders it.I wanted to write down how this stuff works in case someone is highly motivated to dig in themselves, but I'll be upfront that it's a non-trivial amount of work involving low-level parts of the VM. It might be a fun project, but if you're just wanting to get work done, the best answer might be to wait for the renderComponent
API that can take arbitrary arguments to get finished. 😁
Feature added here: https://github.com/glimmerjs/glimmer-test-helpers/pull/4
Bump @glimmer/test-helpers (major update)
Small update here:
The update in the PR I linked unregistered the main ComponentManager which we needed. https://github.com/glimmerjs/glimmer-test-helpers/pull/5 Fixes that. I've confirmed in my own project that on "@glimmer/test-helpers": "0.31.1"
You can write tests like this:
test('should call preloadImages on didInsertElement', async function(assert) {
assert.expect(1);
this.images = [{ retinaSource: 'foo', source: 'bar' }];
await this.render(hbs`<PreloadImages @images={{this.images}} />`);
// assertion occurs in a spy
});
This is currently working. The issue can be closed.
Hi team!
Is it possible to pass arguments into components while rendering them for testing?
I understand that this is a contrived example as I could just pass "10" directly, but I would also like to be able to pass closure actions (not in current documentation, I found an example here).