Skip to content

Instantly share code, notes, and snippets.

@adrienpoly
Last active November 3, 2024 13:14
Show Gist options
  • Save adrienpoly/862846f5882796fdeb4fc85b260b3c5a to your computer and use it in GitHub Desktop.
Save adrienpoly/862846f5882796fdeb4fc85b260b3c5a to your computer and use it in GitHub Desktop.
Capybara / Stimulus test helper to ensure JS is ready when test starts
<!DOCTYPE html>
<html>
<head>
...
</head>
<body data-controller="js">
<%= yield %>
</body>
</html>
import { Controller } from 'stimulus'
export default class extends Controller {
static values = { loaded: Boolean }
connect() {
this.loadedValue = true
}
}
# ...
scenario 'test some js behavior', js: true do
visit some_path
ensure_js_is_ready
# JS is fully loaded you can start interacting with the page
end
# ...
def ensure_js_is_ready
expect(page).to have_css('[data-js-loaded-value="true"]')
end
@rbclark
Copy link

rbclark commented Aug 30, 2023

@adrienpoly Thanks for the suggestion! I'll have to try that out and report back. For now I've just been adding this.loadedValue = true on connect for all my controllers where this problem presents itself. It works but it really litters up all my stimulus controllers. It would really be nice if stimulus were just able to handle this instead of requiring workarounds like this.

@andrewyoo
Copy link

I've been playing around with this as well. I noticed when i load all my controllers using import "controllers", they appear to load alphabetically when i put console.log in the various connect() function. So i renamed the js_controller to zz_js_controller and i'm going to try that out.

Given it's an intermittent issue only in my system tests, i can't confirm if it will fix anything. Thanks for this post though!

Copy link

ghost commented Feb 7, 2024

@andrewyoo Did it work?

@andrewyoo
Copy link

@alan-pie Yes, it works very well. I have no intermittent issues after implementing it in my CI tests and identifying the problem areas (right after a visit).

@rogerkk
Copy link

rogerkk commented Nov 3, 2024

Thanks for this idea!

We're lazy loading Stimulus controllers and this didn't fully solve our flaky tests. Since lazy loading controllers get loaded in the order in which they occur in the DOM, this solution seems to work best when referencing the controller at the very end of the document. Something like this:

<!DOCTYPE html>
<html>
  <head>
    ...
  </head>

  <body>
    <%= yield %>
  </body>
  
  <js-testing data-controller="js" />
</html>

I know this kind of self-closing is invalid HTML, but for some reason the tag needs to be self closing for the controller to be executed. Haven't had the time to dig into that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment