Skip to content

Commit

Permalink
Merge pull request #194 from wspurgin/use-sidekiq-time-calculation
Browse files Browse the repository at this point in the history
Correct evaluation for "in" option
  • Loading branch information
wspurgin authored Jul 26, 2023
2 parents 0863fb8 + ab62910 commit 80a086e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 32 deletions.
17 changes: 6 additions & 11 deletions lib/rspec/sidekiq/matchers/have_enqueued_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,15 @@ 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

private

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

Expand Down Expand Up @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
49 changes: 28 additions & 21 deletions spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,65 @@
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
end

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',
Expand All @@ -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',
Expand All @@ -88,23 +94,27 @@

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
end

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
Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

require 'active_job'
require 'action_mailer'
require 'active_support/testing/time_helpers'

require_relative 'support/init'

RSpec.configure do |config|
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
Expand Down

0 comments on commit 80a086e

Please sign in to comment.