I have a Rails 5 app that uses ActionCable to register 'guest' appearances. When you visit the site, you're prompted for your name. Once entered, your appearance is broadcast to all subscribers. When you exit your window, or 'disappear', you are shown to have left. It works great; the problem I have is testing disappearances - it passes only about half the time.
Here's the relevant test:
RSpec.feature "Appearances", type: :feature, js: true do
let(:picard) { 'Picard' }
let(:riker) { 'Riker' }
scenario "A guest disappears" do
create_guest picard
new_window = within_new_incognito_window do
visit '/'
expect(page).to have_content picard
create_guest riker
end
new_window.close
expect(page).to_not have_content riker
end
And the helpers:
module GuestHelpers
def within_new_incognito_window
new_window = open_new_window
within_window new_window do
Capybara.current_session.driver.clear_cookies
yield
end
new_window
end
def create_guest(name)
within('#new_guest') do
fill_in('guest[name]', with: name)
end
click_on("Go")
expect(page).to have_content name
end
end
I've tried setting the default_max_wait_time to 100, I've tried inserting sleep(10) around closing the window, and I've tried ditching the helpers and just doing it procedurally. I think it's a timing issue around closing the window - am I missing something obvious?
To test features using RSpec which require ActiveJobs to run I find the following useful - install rspec-activejob
, set config.active_job.queue_adapter = :test
in your test.rb and then put the following file in your spec/support directory
require 'rspec/active_job'
RSpec.configure do |config|
config.include(RSpec::ActiveJob)
# clean out the queue after each spec
config.after(:each) do
ActiveJob::Base.queue_adapter.enqueued_jobs = []
ActiveJob::Base.queue_adapter.performed_jobs = []
end
config.around :each, perform_enqueued: true do |example|
@old_perform_enqueued_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_jobs
ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
example.run
ActiveJob::Base.queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs
end
config.around :each, peform_enququed_at: true do |example|
@old_perform_enqueued_at_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs
ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
example.run
ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = @old_perform_enqueued_at_jobs
end
end
which will configure different metadata you can use per test to specify whether or not you want the active jobs created to be executed during your test.
scenario "does something that needs job to run", perform_enqueued: true do
...
end