Facundo Espinosa

June 4, 2024

Ensuring Turbo Frames are complete in System Specs

When writing system specs, especially those visiting pages using Turbo Frames, you might encounter a common issue: ensuring all Turbo Frames are fully loaded before proceeding to the next steps of your tests. Turbo Frames allow for seamless partial page updates, but their asynchronous nature can sometimes lead to race conditions in your tests (for example: dom_id's on elements that were already ereased).

To handle this, I wrote a simple helper method, ensure_turbo_frames_are_complete. This method ensures that all Turbo Frames on the screen are marked as complete before your test moves forward. Here’s a closer look at how it works:

def ensure_turbo_frames_are_complete
  frames = page.all("turbo-frame")
  page.assert_selector("turbo-frame[complete]", minimum: frames.count)
end

How It Works

  1. Selecting All Turbo Frames: The method begins by selecting all Turbo Frames present on the current page using page.all("turbo-frame"). This gives us a collection of all Turbo Frame elements.

  2. Checking for Completion: Next, it uses page.assert_selector to assert that each Turbo Frame has the complete attribute. The minimum: frames.count option ensures that the number of Turbo Frames marked as complete is at least equal to the total number of Turbo Frames initially found.

Why this can be helpful?

In tests, Turbo Frames can lead to scenarios where the test proceeds before all frames have finished loading, causing intermittent failures or false positives (accessing to records that were altered while the async request was being executed).

Example Usage

Here’s how you can use this helper method in a typical system spec:

it "displays the content in all turbo frames" do
  visit some_path
  ensure_turbo_frames_are_complete

  ...
end