diff --git a/README.md b/README.md index dc85d77..aefcd2b 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,16 @@ AwesomeJob.perform_async 'Awesome', true expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true) ``` +You can use the built-in args matchers too: +```ruby +AwesomeJob.perform_async({"something" => "Awesome", "extra" => "stuff"}) + +# using built-in matchers from rspec-mocks: +expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_including("something" => "Awesome")) +expect(AwesomeJob).to have_enqueued_sidekiq_job(any_args) +expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_excluding("bad_stuff" => anything)) +``` + #### Testing scheduled jobs *Use chainable matchers `#at` and `#in`* diff --git a/lib/rspec/sidekiq/matchers.rb b/lib/rspec/sidekiq/matchers.rb index 0bdbce9..6e950df 100644 --- a/lib/rspec/sidekiq/matchers.rb +++ b/lib/rspec/sidekiq/matchers.rb @@ -1,4 +1,5 @@ require 'rspec/core' +require 'rspec/mocks/argument_list_matcher' require 'rspec/sidekiq/matchers/be_delayed' require 'rspec/sidekiq/matchers/be_expired_in' require 'rspec/sidekiq/matchers/be_processed_in' diff --git a/lib/rspec/sidekiq/matchers/be_delayed.rb b/lib/rspec/sidekiq/matchers/be_delayed.rb index c6bbce8..42f8f41 100644 --- a/lib/rspec/sidekiq/matchers/be_delayed.rb +++ b/lib/rspec/sidekiq/matchers/be_delayed.rb @@ -1,6 +1,8 @@ module RSpec module Sidekiq module Matchers + include RSpec::Mocks::ArgumentMatchers + def be_delayed(*expected_arguments) BeDelayed.new(*expected_arguments) end @@ -71,7 +73,7 @@ def find_job(method, arguments, &block) @expected_method_receiver == yaml[0] && method.name == yaml[1] && - (arguments.empty? || (arguments <=> yaml[2]) == 0) + (arguments.empty? || RSpec::Mocks::ArgumentListMatcher.new(*arguments).args_match?(*yaml[2])) end yield job if block && job diff --git a/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb b/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb index 009e025..9ffcdf4 100644 --- a/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb +++ b/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb @@ -36,13 +36,17 @@ def with_context(**expected_context) end class JobArguments + include RSpec::Mocks::ArgumentMatchers + def initialize(job) self.job = job end attr_accessor :job def matches?(expected_args) - RSpec::Matchers::BuiltIn::ContainExactly.new(expected_args).matches?(unwrapped_arguments) + matcher = RSpec::Mocks::ArgumentListMatcher.new(*expected_args) + + matcher.args_match?(*unwrapped_arguments) end def unwrapped_arguments diff --git a/rspec-sidekiq.gemspec b/rspec-sidekiq.gemspec index 8fb9519..5c495f4 100644 --- a/rspec-sidekiq.gemspec +++ b/rspec-sidekiq.gemspec @@ -11,6 +11,7 @@ Gem::Specification.new do |s| s.license = "MIT" s.add_dependency "rspec-core", "~> 3.0" + s.add_dependency "rspec-mocks", "~> 3.0" s.add_dependency "rspec-expectations", "~> 3.0" s.add_dependency "sidekiq", ">= 5", "< 8" diff --git a/spec/rspec/sidekiq/matchers/be_delayed_spec.rb b/spec/rspec/sidekiq/matchers/be_delayed_spec.rb index 3493604..bc6bd99 100644 --- a/spec/rspec/sidekiq/matchers/be_delayed_spec.rb +++ b/spec/rspec/sidekiq/matchers/be_delayed_spec.rb @@ -12,6 +12,13 @@ let(:delay_for_with_arguments_subject) { RSpec::Sidekiq::Matchers::BeDelayed.new(Object).for 3600 } let(:delay_until_subject) { RSpec::Sidekiq::Matchers::BeDelayed.new.until Time.now + 3600 } let(:delay_until_with_arguments_subject) { RSpec::Sidekiq::Matchers::BeDelayed.new(Object).until Time.now + 3600 } + + around(:each) do |example| + travel_to Time.new(2023, 8, 1, 0, 0, 0, "-05:00") do + example.run + end + end + before(:each) do delay_subject.matches? Object.method :nil? delay_with_arguments_subject.matches? Object.method :is_a? @@ -73,7 +80,7 @@ expect(delay_until_with_arguments_subject.description).to eq "be delayed until #{Time.now + 3600} with arguments [Object]" end end - end + end describe '#failure_message' do context 'when expected is a delay' do @@ -120,10 +127,16 @@ Object.delay.nil? expect(delay_subject.matches? Object.method :nil?).to be true + end - Object.delay.is_a? Object + context "and actual contains arguments" do + it "returns true" do + # Acutal has arugment + Object.delay.is_a? Object - expect(delay_subject.matches? Object.method :is_a?).to be true + # Expected didn't specify any arguemtns to match + expect(delay_subject.matches? Object.method :is_a?).to be true + end end end @@ -133,6 +146,14 @@ expect(delay_with_arguments_subject.matches? Object.method :is_a?).to be true end + + context "and expected uses builtin matchers" do + let(:delay_with_arguments_subject) { RSpec::Sidekiq::Matchers::BeDelayed.new anything } + it "returns true" do + Object.delay.is_a? Object + expect(delay_with_arguments_subject.matches? Object.method(:is_a?)).to be true + end + end end context 'when expected is a delay for' do @@ -166,7 +187,7 @@ expect(delay_until_with_arguments_subject.matches? Object.method :is_a?).to be true end end - end + end context 'when condition does not match' do context 'when expected is a delay' do diff --git a/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb b/spec/rspec/sidekiq/matchers/have_enqueued_sidekiq_job_spec.rb similarity index 93% rename from spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb rename to spec/rspec/sidekiq/matchers/have_enqueued_sidekiq_job_spec.rb index 86b7876..d661713 100644 --- a/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb +++ b/spec/rspec/sidekiq/matchers/have_enqueued_sidekiq_job_spec.rb @@ -27,6 +27,15 @@ expect(Sidekiq::Worker).to have_enqueued_sidekiq_job *worker_args end + context "when using builtin argument matchers" do + it "matches" do + worker.perform_async({"something" => "Awesome", "extra" => "stuff"}) + expect(worker).to have_enqueued_sidekiq_job(hash_including("something" => "Awesome")) + expect(worker).to have_enqueued_sidekiq_job(any_args) + expect(worker).to have_enqueued_sidekiq_job(hash_excluding("bad_stuff" => anything)) + end + end + context 'perform_in' do let(:worker_args_in) { worker_args + ['in'] } @@ -230,6 +239,13 @@ it 'returns false' do expect(argument_subject.matches? worker).to be false end + + context "and arguments are out of order" do + it "returns false" do + worker.perform_async(*worker_args.reverse) + expect(argument_subject.matches? worker).to be false + end + end end context 'when expected are matchers' do