sajad torkamani

Suppose you have some JavaScript that needs to finish executing before a part of your DOM is ready to be interacted with. Let’s assume you’re using a library like Alpine.js to create a dropdown component. In this case, you need Capybara to wait for Alpine to initialize before your test can interact with the DOM.

Find out when your JavaScript has finished executing

Depending on what libraries you’re using, or how your JS code is executed, you’ll want to do something like this:

document.addEventListener('alpine:initialized', () => {
  document.querySelector('body').classList.add('alpine-initialized')
})

You can then define a RSpec helper method:

def wait_for_alpine
  expect(page).to have_selector('body.alpine-initialized')
end

Now, you can use this helper whenever you need Capybara to wait until Alpine has finished initialized before doing anything. For example:

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Logout', type: :feature do
  it 'User can logout using the logout button', driver: :selenium_headless do
    user = create(:user)
    login_as(user)

    visit root_path
    wait_for_alpine # Waiting...
    click_on user.truncated_email
    click_on 'Logout'

    expect(page).to have_content I18n.t('devise.sessions.signed_out')
  end
end