System tests for TurboStream'd app without `sleep 1`

I am about to write system tests for my very first sandbox app with Hotwire/Turbo adopted at full scale. Is there a built-in mechanism to test without countless sleep 1s?

jaj sleep has saved many developments and tests, although not you believe it

Why do you need to use sleep at all?

Example: entity creation, the entity model broadcasts its rendered HTML view over the cable (websocket), but the POST request itself results in an empty response. Therefore there is a time lag between a form is submitted and the rendered-on-the-server HTML view appears in browser. So the sleep is needed to wait until this async process is done. Maybe I am missing something?

It depends on the tools used in your system test framework.

If using Capybara, you would just look for an element that you expect to be available after the turbo stream completes. Capybara waits until 1) it finds the element on the page or 2) Capybara times out. I believe the default timeout for Capybara is 2 seconds, which you can change using:

# spec_helper.rb
Capybara.default_wait_time = 10

There are other Capybara techniques (like one discussed on Stack Overflow
), but I’m not sure you need them with the right timeouts and selectors.

def wait_for_turbo(timeout = nil)
  if has_css?('.turbo-progress-bar', visible: true, wait: (0.25).seconds)
    has_no_css?('.turbo-progress-bar', wait: timeout.presence || 5.seconds)
  end
end

def wait_for_turbo_frame(selector = 'turbo-frame', timeout = nil)
  if has_selector?("#{selector}[busy]", visible: true, wait: (0.25).seconds)
    has_no_selector?("#{selector}[busy]", wait: timeout.presence || 5.seconds)
  end
end

FYI, I have not tested any of these methods as I’ve never needed to.

1 Like

Right, I see, instead of explicit timeout, Capybara has a smart waiting mechanism built-in, wonderful, thank you so much for sharing!