dawarich/spec/jobs/tracks/daily_generation_job_spec.rb
2025-09-29 22:27:07 +02:00

127 lines
4.3 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Tracks::DailyGenerationJob, type: :job do
describe '#perform' do
let!(:active_user) { create(:user, settings: { 'minutes_between_routes' => 60, 'meters_between_routes' => 500 }) }
let!(:trial_user) { create(:user, :trial) }
let!(:inactive_user) { create(:user, :inactive) }
let!(:active_user_old_track) do
create(:track, user: active_user, start_at: 2.days.ago, end_at: 2.days.ago + 1.hour)
end
let!(:active_user_new_points) do
create_list(:point, 3, user: active_user, timestamp: 1.hour.ago.to_i)
end
let!(:trial_user_old_track) do
create(:track, user: trial_user, start_at: 3.days.ago, end_at: 3.days.ago + 1.hour)
end
let!(:trial_user_new_points) do
create_list(:point, 2, user: trial_user, timestamp: 30.minutes.ago.to_i)
end
before do
active_user.update!(points_count: active_user.points.count)
trial_user.update!(points_count: trial_user.points.count)
allow(User).to receive(:active_or_trial)
.and_return(User.where(id: [active_user.id, trial_user.id]))
ActiveJob::Base.queue_adapter.enqueued_jobs.clear
end
it 'processes all active and trial users' do
expect { described_class.perform_now }.to \
have_enqueued_job(Tracks::ParallelGeneratorJob).twice
end
it 'does not process inactive users' do
# Clear points and tracks to make destruction possible
Point.destroy_all
Track.destroy_all
# Remove active and trial users to isolate test
active_user.destroy
trial_user.destroy
expect do
described_class.perform_now
end.not_to have_enqueued_job(Tracks::ParallelGeneratorJob)
end
it 'enqueues correct number of parallel generation jobs for users with new points' do
expect { described_class.perform_now }.to \
have_enqueued_job(Tracks::ParallelGeneratorJob).exactly(2).times
end
it 'enqueues parallel generation job for active user with correct parameters' do
expect { described_class.perform_now }.to \
have_enqueued_job(Tracks::ParallelGeneratorJob).with(
active_user.id,
hash_including(mode: 'daily')
)
end
it 'enqueues parallel generation job for trial user' do
expect { described_class.perform_now }.to \
have_enqueued_job(Tracks::ParallelGeneratorJob).with(
trial_user.id,
hash_including(mode: 'daily')
)
end
it 'does not enqueue jobs for users without new points' do
Point.destroy_all
expect { described_class.perform_now }.not_to \
have_enqueued_job(Tracks::ParallelGeneratorJob)
end
context 'when processing fails' do
before do
allow_any_instance_of(User).to receive(:tracks).and_raise(StandardError, 'Database error')
allow(ExceptionReporter).to receive(:call)
active_user.update!(points_count: 5)
trial_user.update!(points_count: 3)
end
it 'does not raise errors when processing fails' do
expect { described_class.perform_now }.not_to raise_error
end
it 'reports exceptions when processing fails' do
described_class.perform_now
expect(ExceptionReporter).to have_received(:call).at_least(:once)
end
end
context 'when user has no points' do
let!(:empty_user) { create(:user) }
it 'skips users with no points' do
expect { described_class.perform_now }.not_to \
have_enqueued_job(Tracks::ParallelGeneratorJob).with(empty_user.id, any_args)
end
end
context 'when user has tracks but no new points' do
let!(:user_with_current_tracks) { create(:user) }
let!(:recent_points) { create_list(:point, 2, user: user_with_current_tracks, timestamp: 1.hour.ago.to_i) }
let!(:recent_track) do
create(:track, user: user_with_current_tracks, start_at: 1.hour.ago, end_at: 30.minutes.ago)
end
before do
user_with_current_tracks.update!(points_count: user_with_current_tracks.points.count)
end
it 'skips users without new points since last track' do
expect { described_class.perform_now }.not_to \
have_enqueued_job(Tracks::ParallelGeneratorJob).with(user_with_current_tracks.id, any_args)
end
end
end
end