sbrocos
sbrocos

Reputation: 1

rails 7, Active Storage, Factory Bot, freeze my RSPECs

After a lot hours tried to resolve by myself this problem.

All works very well when I do it everything in browsers. The problem its only when execute the test (with spec) that use the next class:

class Album < ApplicationRecord
  has_one_attached :cover do |attachable|
    attachable.variant :thumb, resize: '100x100'
    attachable.variant :medium, resize: '400x400'
  end

  # Associations
  has_many :songs, dependent: :destroy

  # Validations
  validates :title, :artist_name, presence: true
  validates :cover, attached: true
end

class Song < ApplicationRecord
  # Attachments
  has_one_attached :audio

  # Associations
  belongs_to :album

  # Scopes
  scope :ordered, -> { order(disk_number: :asc, track_number: :asc) }
end

When I do the test for Albums, I don't have any problem with the test, I suppose because it's a basic test. But the problem its with the test of songs:

RSpec.describe Song do
 subject(:song) { create(:song, album:) }

 let(:album) { create(:album, cover: file_fixture('cover.jpg')) }

 describe 'associations' do
   it { expect(song).to belong_to('album') }
 end

 describe 'validates' do
   it do
     expect(album).to validate_presence_of(:title)
     expect(album).to validate_presence_of(:artist_name)
   end
 end

 describe '#ordered' do
   subject(:ordered) { described_class.ordered }

   context 'when have only one disc' do
     let(:song1) { create(:song, track_number: 1, album:) }
     let(:song2) { create(:song, track_number: 2, album:) }
    
     it 'returns array with correct ordered songs' do
       expect(ordered).to eq([song, song2])
     end
    end
    
    context 'when you have two disc and the same track number' do
      let(:song1) { create(:song, track_number: 1, disk_number: 1, album:) }
      let(:song2) { create(:song, track_number: 1, disk_number: 2, album:) }
    
      it 'returns array with ordered by track and disc' do
        expect(ordered).to eq([song1, song2])
      end
    end
 end

...

end

When execute this... I get next result:

Song
  associations
    is expected to belong to album required: true
  validates
    is expected to validate that :artist_name cannot be empty/falsy
  #ordered
    when have only one disc

I see this article, where I read about use only File.open ins rails 7, because with other options I have the same problem.

And when Arrive this point, the test is freezing the 90% of time (in and Intel processor and 60% in an ARM processor). I tray a lot of things. But only its failed when in the FactoryBot I try to attach the image in the cover attribute:

FactoryBot.define do
  factory :album do
    title { 'MyString' }
    artist_name { 'Artist' }
    label { 'MyString' }
    upc { 'MyString' }
    release_date { '2024-03-24 13:14:12' }
    cover { File.open('spec/fixtures/cover.jpg') }
  end
end

I've also tried to use a "trait" to define the "cover" attribute, but I get the same results. But If I don't use the attachment, then the test works perfectly.

The test.log has this message (its a resume because its very long):

 Error performing ActiveStorage::AnalyzeJob (Job ID: ee23c48f-38ed-4a96-a3f5-a3b11645a028) from Async(default) in 5.02ms: ActiveJob::DeserializationError (Error while trying to deserialize arguments: undefined method `clear' for nil):

In my setup:

config.active_storage.variant_processor = :mini_magick

Because I know that with ruby-vips ins't the best option, and sometimes has problems.

Someone knows something about this, or have any idea.

Upvotes: 0

Views: 355

Answers (3)

Hackeron
Hackeron

Reputation: 636

You need to do this:

# This conf needs to make activejob inline
#
# https://github.com/rails/rails/issues/37270
#
RSpec.configure do |config|
  config.around(:each, type: /(request|mailer)/) do |example|
    original_queue_adapter = ActiveJob::Base.queue_adapter
    descendants = ActiveJob::Base.descendants + [ActiveJob::Base]

    ActiveJob::Base.queue_adapter = :inline
    descendants.each(&:disable_test_adapter)
    example.run
    descendants.each { |a| a.enable_test_adapter(ActiveJob::QueueAdapters::TestAdapter.new) }
    ActiveJob::Base.queue_adapter = original_queue_adapter
  end
end

Upvotes: 0

sbrocos
sbrocos

Reputation: 1

In my case... I found the next answer in other [post][1]

Add both of these settings to config/environments/test.rb:

# Use inline job processing to make things happen immediately
config.active_job.queue_adapter = :inline

# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test

I understand that now, with this config, the project use correctly the queue to access and read the file to upload and now it's not freezing when I try to execute the test. [1]: https://stackoverflow.com/a/62310984/20661211

Upvotes: 0

Anton  Bogdanov
Anton Bogdanov

Reputation: 834

You can attach file to model like this

trait :with_cover do
  after(:create) do |album|
    album.cover.attach(Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/cover.jpg"))
  end
end

Upvotes: 1

Related Questions