diff --git a/lib/rspec/sidekiq/matchers/have_enqueued_job.rb b/lib/rspec/sidekiq/matchers/have_enqueued_job.rb index 4ab86df..124a30f 100644 --- a/lib/rspec/sidekiq/matchers/have_enqueued_job.rb +++ b/lib/rspec/sidekiq/matchers/have_enqueued_job.rb @@ -18,7 +18,7 @@ def initialize(job) end def matches?(option, value) - raise ArgumentError, "Option `#{option}` is not defined." unless %w(in at).include?(option.to_s) + raise ArgumentError, "Option `#{option}` is not defined." unless %w[at].include?(option.to_s) send("#{option}_evaluator", value) end @@ -26,12 +26,7 @@ def matches?(option, value) def at_evaluator(value) return false if job['at'].to_s.empty? - value.to_time.to_i == Time.at(job['at']).to_i - end - - def in_evaluator(value) - return false if job['at'].to_s.empty? - (Time.now + value).to_i == Time.at(job['at']).to_i + value == Time.at(job['at']).to_i end end @@ -80,7 +75,7 @@ def active_job_original_args end class EnqueuedJobs - attr_reader :jobs, :actual_arguments, :actual_options + attr_reader :jobs def initialize(klass) @jobs = unwrap_jobs(klass.jobs) @@ -98,7 +93,7 @@ def actual_options @actual_options ||= if jobs.is_a?(Hash) jobs.values else - jobs.flatten.map { |j| { 'at' => j['at'] } } + jobs.flatten.map { |j| {"at" => j["at"]} } end end @@ -149,12 +144,12 @@ def matches?(klass) end def at(timestamp) - @expected_options['at'] = timestamp + @expected_options['at'] = timestamp.to_time.to_i self end def in(interval) - @expected_options['in'] = interval + @expected_options['at'] = (Time.now.to_f + interval.to_f).to_i self end diff --git a/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb b/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb index e5d3eea..34dd546 100644 --- a/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb +++ b/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb @@ -13,43 +13,45 @@ before(:each) do GlobalID.app = 'rspec-sidekiq' allow(GlobalID::Locator).to receive(:locate).and_return(resource) - worker.perform_async *worker_args - active_job.perform_later "someResource", *worker_args - active_job.perform_later(resource) - TestActionMailer.testmail(*worker_args).deliver_later - TestActionMailer.testmail(resource).deliver_later end describe 'expected usage' do context 'Sidekiq' do it 'matches' do + worker.perform_async *worker_args expect(worker).to have_enqueued_sidekiq_job *worker_args end it 'matches on the global Worker queue' do + worker.perform_async *worker_args expect(Sidekiq::Worker).to have_enqueued_sidekiq_job *worker_args end context 'perform_in' do let(:worker_args_in) { worker_args + ['in'] } - before(:each) do - worker.perform_in 3.minutes, *worker_args_in - end - it 'matches on an scheduled job with #perform_in' do + worker.perform_in interval, *worker_args_in expect(worker).to have_enqueued_sidekiq_job(*worker_args_in).in(interval) end + + context "when crossing daylight saving time lines" do + let(:interval) { 1.day } + + it "matches on a scheduled job with #perform_in" do + travel_to Time.new(2023, 3, 12, 0, 0, 0, "-05:00") do # 2 hours before DST starts + worker.perform_in interval, *worker_args_in + expect(worker).to have_enqueued_sidekiq_job(*worker_args_in).in(interval) + end + end + end end context 'perform_at' do let(:worker_args_at) { worker_args + ['at'] } - before(:each) do - worker.perform_at tomorrow, *worker_args_at - end - it 'matches on an scheduled job with #perform_at' do + worker.perform_at tomorrow, *worker_args_at expect(worker).to have_enqueued_sidekiq_job(*worker_args_at).at(tomorrow) end end @@ -57,16 +59,19 @@ context 'ActiveJob' do it 'matches on an enqueued ActiveJob' do + active_job.perform_later "someResource", *worker_args expect(Sidekiq::Worker).to have_enqueued_sidekiq_job 'someResource', *worker_args end it 'matches on an enqueued ActiveJob by global_id-capable object' do + active_job.perform_later(resource) expect(Sidekiq::Worker).to have_enqueued_sidekiq_job(resource) end end context 'ActionMailer' do it 'matches on ActionMailer Job' do + TestActionMailer.testmail(*worker_args).deliver_later expect(Sidekiq::Worker).to have_enqueued_sidekiq_job( 'TestActionMailer', 'testmail', @@ -76,6 +81,7 @@ end it 'matches on ActionMailer with a resource Job' do + TestActionMailer.testmail(resource).deliver_later expect(Sidekiq::Worker).to have_enqueued_sidekiq_job( 'TestActionMailer', 'testmail', @@ -88,16 +94,19 @@ describe '#have_enqueued_sidekiq_job' do it 'returns instance' do + worker.perform_async *worker_args expect(have_enqueued_sidekiq_job).to be_a RSpec::Sidekiq::Matchers::HaveEnqueuedJob end it 'matches the same way have_enqueued_sidekiq_job does' do + worker.perform_async *worker_args expect(worker).to have_enqueued_sidekiq_job *worker_args end end describe '#description' do it 'returns description' do + worker.perform_async *worker_args argument_subject.matches? worker expect(argument_subject.description).to eq %{have an enqueued #{worker} job with arguments [\"string\", 1, true, {\"key\"=>\"value\", \"bar\"=>\"foo\", \"nested\"=>[{\"hash\"=>true}]}]} end @@ -105,6 +114,7 @@ describe '#failure_message' do it 'returns message' do + worker.perform_async *worker_args argument_subject.matches? worker expect(argument_subject.failure_message).to eq <<-eos.gsub(/^ {6}/, '').strip expected to have an enqueued #{worker} job @@ -119,6 +129,7 @@ describe '#failure_message_when_negated' do it 'returns message' do + worker.perform_async *worker_args argument_subject.matches? worker expect(argument_subject.failure_message_when_negated).to eq <<-eos.gsub(/^ {6}/, '').strip expected not to have an enqueued #{worker} job @@ -145,36 +156,32 @@ context 'when job is scheduled' do context 'with #perform_at' do - before(:each) do - worker.perform_at(tomorrow, *worker_args) - end - context 'and timestamp matches' do it 'returns true' do + worker.perform_at(tomorrow, *worker_args) expect(matcher_subject.at(tomorrow).matches? worker).to be true end end context 'and timestamp does not match' do it 'returns false' do + worker.perform_at(tomorrow, *worker_args) expect(matcher_subject.at(tomorrow + 1).matches? worker).to be false end end end context 'with #perform_in' do - before(:each) do - worker.perform_in(interval, *worker_args) - end - context 'and interval matches' do it 'returns true' do + worker.perform_in(interval, *worker_args) expect(matcher_subject.in(interval).matches? worker).to be true end end context 'and interval does not match' do it 'returns false' do + worker.perform_in(interval, *worker_args) expect(matcher_subject.in(interval + 1.minute).matches? worker).to be false end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8bba386..87d1afe 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,6 +5,7 @@ require 'active_job' require 'action_mailer' +require 'active_support/testing/time_helpers' require_relative 'support/init' @@ -12,6 +13,7 @@ config.disable_monkey_patching! config.include RSpec::Sidekiq::Spec::Support::Factories + config.include ActiveSupport::Testing::TimeHelpers # Add a setting to store our Sidekiq Version and share that around the specs config.add_setting :sidekiq_gte_7