Search code examples
ruby-on-railsrubyrspecactioncableturbo

Why is Turbo Action Cable within a job not working in system Rspec tests?


I am building a project in Rails with Turbo and Action Cable. The project is working fine in development environment so far. However, my system test is the only thing that is not working. Surprisingly action cable does not respond.

This is my system test

# spec/system/grids_spec.rb
RSpec.describe 'Grids', type: :system do
  it 'creates grid' do
    visit root_path

    click_on 'Create Grid'

    expect do
      sleep 0.2
    end.to change { find('#grid').html }
  end
end

My controller performs a job

# app/controllers/grids_controller.rb
class GridsController < ApplicationController
  def create
    @grid_data = GridData.new(**grid_params)

    if @grid_data.valid?
      play
    else
      render :new, status: :unprocessable_entity
    end
  end

  private
  
  def play
    render :play, status: :created
    PlayJob.perform_later(**@grid_data.attributes)
  end
end

This is the job

# app/jobs/play_job.rb
class PlayJob < ApplicationJob
  queue_as :default

  def perform(**grid_attributes)
    GridData.new(grid_attributes).to_grid.play
  end
end

It calls method play which broadcasts to Turbo Channel.

# lib/grid.rb
class Grid
  def play
    print
    2.upto(@phases) do
      sleep(@phase_duration)
      next_phase
      print
    end
  end

  def print
    Turbo::StreamsChannel.broadcast_update_to(
      'play',
      target: 'grid',
      partial: 'grids/grid',
      locals: { grid: self }
    )
  end
end

All this stuff works well in development environment but not in system test.

I found out that jobs are not performed, not even enqueued, in system test.

  it 'creates grid' do
    ActiveJob::Base.queue_adapter = :test
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true

    visit root_path

    click_on 'Create Grid'

    expect(PlayJob).to have_been_enqueued
  end
Failure/Error: expect(PlayJob).to have_been_enqueued
       expected to enqueue exactly 1 jobs, but enqueued 0

Then I put a byebug in action create and no variables were found!

This is all my source code: https://github.com/chiaraani/life-game-web

Why are jobs not enqueued in system test? How can I get jobs performed?


Solution

  • I had to make play method wait.

    # lib/grid.rb
    class Grid
      def play
        sleep 1
        print
        2.upto(@phases) do
          sleep(@phase_duration)
          next_phase
          print
        end
      end
    end
    

    I set async adapter.

    # spec/system/grids_spec.rb
    RSpec.describe 'Grids', type: :system do
      it 'creates grid' do
        ActiveJob::Base.queue_adapter = :async
        visit root_path
    
        click_on 'Create Grid'
    
        expect do
          sleep 0.2
        end.to change { find('#grid').html }
      end
    end