Skip to content

Does capybara-lockstep support Turbo Rails (Hotwire) frame loading synchronization? #29

@navidemad

Description

@navidemad

Thank you for your gem !

Description

We've implemented capybara-lockstep for test synchronization and need clarification on Turbo Rails support.

Question

Does capybara-lockstep provide built-in support for Turbo Rails/Hotwire patterns, specifically:

  1. Waiting for <turbo-frame> elements to finish loading (indicated by the [busy] attribute)?
  2. Handling Turbo Drive navigation completion?
  3. Detecting Turbo Streams being applied to the DOM?

Context

We have custom wait methods that were added before capybara-lockstep:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  def visit(...)
    super
    wait_until_all_turbo_frames_busy_and_network_ready
  end

  def wait_until_all_turbo_frames_busy_and_network_ready
    # Skip if no turbo frames
    return if !page.has_selector?("turbo-frame[busy]", visible: :visible, wait: 0)

    # Wait for turbo frames with shorter timeout
    assert_no_selector("turbo-frame[busy]", wait: 10)

    begin
      # Reduce network idle timeout for faster tests
      # Only wait 2 seconds for network to be idle
      page.driver.wait_for_network_idle(timeout: ENV.fetch("CAPYBARA_NETWORK_TIMEOUT", "2").to_f)
    rescue Ferrum::TimeoutError
    end
  end
end

We're evaluating whether these are now redundant with capybara-lockstep, or if they're still necessary for Turbo-specific patterns.

Issue

Your README states capybara-lockstep waits for:

  • "resources have loaded (images, CSS, fonts, frames)"
  • "client-side JavaScript to render or hydrate DOM elements"
  • "any pending AJAX requests to finish and their callbacks to be called"

However, it doesn't explicitly mention Turbo, which uses a different pattern than traditional AJAX:

  • Turbo uses fetch-based navigation (not fetch() API, but Turbo.visit())
  • Turbo Frames have their own [busy] state
  • Turbo Streams deliver HTML via WebSocket/SSE

Question: Are these Turbo patterns covered by capybara-lockstep's existing synchronization, or do they require custom handling?

Expected Behavior

Ideally, capybara-lockstep would either:

  1. Confirm built-in support - Update docs to mention Turbo/Hotwire explicitly
  2. Recommend custom signaling - Show how to signal Turbo events to capybara-lockstep if needed
  3. Consider it a feature - Add explicit Turbo Frame/Drive/Stream support

Environment

  • capybara-lockstep: latest
  • Turbo Rails: 8.x
  • Driver: Cuprite with Ferrum
  • Rails: 8.x with Turbo Streams enabled

Related

The README covers general AJAX synchronization but doesn't address modern Hotwire patterns, which many Rails apps now use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions