How to tell if Stimulus is loaded for injected HTML


#1

We’re writing some Rails system test (capybara) and one of the problems we’re coming across is intermittent test failures when there’s dynamic HTML injected.

For example, let’s say we fetch the following HTML and inject it into the DOM:

<div data-controller="foo">
  <button data-action="foo.perform">Go</button>
</div>

The moment it’s injected, the “foo” Stimulus controller gets attached via MutationObserver callback. However, during system tests, there a possibility that click_button("Go") is performed before the controller’s actions are even registered. This results in the click not performing the action perform().

So, is there a way to know when Stimulus is finished working its magic for newly injected content?

Thanks!


#2

Stimulus responds to document changes in the next tick of the microtask queue.

In JavaScript, the easiest way to queue a microtask is to wait on an empty promise:

document.body.insertAdjacentHTML("beforeend", "...")

Promise.resolve().then(() => {
  // Stimulus has responded to the change by now
})

In Capybara, you’ll probably just want to sleep for a very small amount of time after each DOM modification. (I’m not an expert with Capybara, so feel free to chime in here if you are!)