# frozen_string_literal: true require "spec_helpers" describe Wayfarer::Base, redis: true do let(:task) { build(:task, :redis_pool) } before do stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base)) end describe "::crawl" do it "enqueues a task" do expect(DummyJob).to receive(:perform_later).with(task) DummyJob.crawl(task.url, batch: task.batch) end it "returns a task" do expect(DummyJob.crawl(task.url)).to be_a(Wayfarer::Task) end end describe "#perform" do subject(:counter) { Wayfarer::Redis::Counter.new(task) } let!(:initial) { counter.increment } before do DummyJob.class_eval do route.to :index end end describe "succeeding job" do before do DummyJob.class_eval do def index; end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) perform_enqueued_jobs assert_performed_jobs 1 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "failing job" do before do DummyJob.class_eval do def index raise end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) expect { perform_enqueued_jobs }.to raise_error(RuntimeError) assert_performed_jobs 1 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "failing job with retries" do before do DummyJob.class_eval do retry_on StandardError, attempts: 3 def index raise end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) 2.times { perform_enqueued_jobs } expect { perform_enqueued_jobs }.to raise_error(RuntimeError) assert_performed_jobs 3 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "discarded after retries" do before do DummyJob.class_eval do ErrorA = Class.new(StandardError) ErrorB = Class.new(StandardError) retry_on ErrorA, attempts: 5 discard_on ErrorB def index raise ErrorB if executions == 5 raise ErrorA end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) 4.times { perform_enqueued_jobs } perform_enqueued_jobs assert_performed_jobs 5 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "discarded job" do before do DummyJob.class_eval do discard_on RuntimeError def index raise "boom" end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) perform_enqueued_jobs assert_performed_jobs 1 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "after_batch callback" do let(:initial) { counter.value } describe "when after_perform callback fails" do before do DummyJob.class_eval do after_perform { raise } def index; end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) expect { perform_enqueued_jobs }.to raise_error(RuntimeError) assert_performed_jobs 1 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end describe "when after_batch callback fails" do before do DummyJob.class_eval do after_batch { raise } def index; end end end specify do expect_any_instance_of(Wayfarer::Redis::Counter) .to receive(:increment).at_least(:once).and_call_original expect { DummyJob.perform_later(task) expect { perform_enqueued_jobs }.to raise_error(RuntimeError) assert_performed_jobs 1 expect(enqueued_jobs).to be_empty }.not_to change { counter.value }.from(initial) end end end end end