Capybara wait_for_ajax replacement for turbo-stream responses

I’m in need of code like this:

# spec/support/wait_for_ajax.rb
module WaitForAjax
  def wait_for_ajax
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until finished_all_ajax_requests?
    end
  end

  def finished_all_ajax_requests?
    page.evaluate_script('jQuery.active').zero?
  end
end

but for turbo-stream responses.

Or is there a way to determine if a fetch request is completed?

1 Like

Does something like this solution work?

@cbandes Thanks but no that solution doesn’t do it.

Did you find a solution to wait for turbo-stream responses?

No, I haven’t found a solution yet.

How do you currently handle it? Or did you pend those specs?

Just doing a sleep 0.5. Granted, it is only in two cases that I needed to do this. Otherwise, a returned stream is modifying the DOM and I’m using proper Capybara detection methods.

I found a solution, which works for me at least.

In that article I mentioned a while back it talks about how wait_for_ajax really isn’t the right solution anyway and that the right approach was to use Capybara’s find which will wait for the elements to come into view. I didn’t really understand how this works at first, but I’ve been playing around with it, and it is starting to make sense to me.

So what I’ve been doing is this - when I want to wait for Turbo to load a new view, I identify an element that only appears on the to-be-loaded view, and I set up a find for that element - something like this

link_to_new_view.click

find('.element_that_only_exists_on_next_view')

expect(thing).to eq(value_that_we_needed_to_wait_for)

The find will wait until the element comes into view, which is pretty much what wait_for_ajax is trying to do anyway, but this is more specific and works really well once you start down this path.

I’m mostly using this with turbo-frames rather than turbo-streams but I think it will work the same way
with anything that changes the dom. You just need to know what you’re going to be looking for.

1 Like

Right but there are some (albeit rare) edge cases where the DOM doesn’t change after a stream or a fetch(). Even when you’re expecting a DOM change I’ve found that Capybara still can fail intermittently. This can occur even when bumping up the wait time e.g. assert_content "successfully created", wait: 5. Judiciously sprinkling sleep 0.5 or even a sleep 1.0 on my system tests in these cases keeps them consistently green.