Skip to content

Commit dc0abdb

Browse files
mbajurpirj
andauthored
Add at_priority matcher for ActiveJob matchers
Co-authored-by: Phil Pirozhkov <[email protected]>
1 parent 9f4a5de commit dc0abdb

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Enhancements:
77
(Steve Polito, #2746)
88
* Verify ActiveJob arguments by comparing to the method signature. (Oli Peate, #2745)
99
* Add suggestion to rails_helper.rb to skip when not in test most. (Glauco Custódio, #2751)
10+
* Add `at_priority` qualifier to `have_enqueued_job` set of matchers. (mbajur, #2759)
1011

1112
Bug Fixes:
1213

features/job_specs/job_spec.feature

+19
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,25 @@ Feature: Job specs
7878
When I run `rspec spec/jobs/upload_backups_job_spec.rb`
7979
Then the example should pass
8080

81+
Scenario: Specify that job was enqueued with a priority
82+
Given a file named "spec/jobs/upload_backups_job_spec.rb" with:
83+
"""ruby
84+
require "rails_helper"
85+
86+
RSpec.describe UploadBackupsJob, type: :job do
87+
describe "#perform_later" do
88+
it "uploads a backup" do
89+
ActiveJob::Base.queue_adapter = :test
90+
expect {
91+
UploadBackupsJob.set(priority: 5).perform_later
92+
}.to have_enqueued_job.at_priority(5)
93+
end
94+
end
95+
end
96+
"""
97+
When I run `rspec spec/jobs/upload_backups_job_spec.rb`
98+
Then the example should pass
99+
81100
Scenario: Specify that job was enqueued with alias block syntax
82101
Given a file named "spec/jobs/upload_backups_job_spec.rb" with:
83102
"""ruby

lib/rspec/rails/matchers/active_job.rb

+29-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Base < RSpec::Rails::Matchers::BaseMatcher
1414
def initialize
1515
@args = []
1616
@queue = nil
17+
@priority = nil
1718
@at = nil
1819
@block = proc { }
1920
set_expected_number(:exactly, 1)
@@ -30,6 +31,11 @@ def on_queue(queue)
3031
self
3132
end
3233

34+
def at_priority(priority)
35+
@priority = priority.to_i
36+
self
37+
end
38+
3339
def at(time_or_date)
3440
case time_or_date
3541
when Time then @at = Time.at(time_or_date.to_f)
@@ -103,7 +109,7 @@ def supports_block_expectations?
103109

104110
def check(jobs)
105111
@matching_jobs, @unmatching_jobs = jobs.partition do |job|
106-
if job_match?(job) && arguments_match?(job) && queue_match?(job) && at_match?(job)
112+
if job_match?(job) && arguments_match?(job) && queue_match?(job) && at_match?(job) && priority_match?(job)
107113
args = deserialize_arguments(job)
108114
@block.call(*args)
109115
true
@@ -117,6 +123,10 @@ def check(jobs)
117123
return false
118124
end
119125

126+
check_countable
127+
end
128+
129+
def check_countable
120130
@matching_jobs_count = @matching_jobs.size
121131

122132
case @expectation_type
@@ -131,6 +141,7 @@ def base_message
131141
msg << " with #{@args}," if @args.any?
132142
msg << " on queue #{@queue}," if @queue
133143
msg << " at #{@at.inspect}," if @at
144+
msg << " with priority #{@priority}," if @priority
134145
msg << " but #{self.class::MESSAGE_EXPECTATION_ACTION} #{@matching_jobs_count}"
135146
end
136147
end
@@ -140,6 +151,12 @@ def base_job_message(job)
140151
msg_parts << "with #{deserialize_arguments(job)}" if job[:args].any?
141152
msg_parts << "on queue #{job[:queue]}" if job[:queue]
142153
msg_parts << "at #{Time.at(job[:at])}" if job[:at]
154+
msg_parts <<
155+
if fetch_priority(job)
156+
"with priority #{fetch_priority(job)}"
157+
else
158+
"with no priority specified"
159+
end
143160

144161
"#{job[:job].name} job".tap do |msg|
145162
msg << " #{msg_parts.join(', ')}" if msg_parts.any?
@@ -150,6 +167,11 @@ def job_match?(job)
150167
@job ? @job == job[:job] : true
151168
end
152169

170+
# Rails 6.1 serializes the priority with a string key
171+
def fetch_priority(job)
172+
job[:priority] || job['priority']
173+
end
174+
153175
def arguments_match?(job)
154176
if @args.any?
155177
args = serialize_and_deserialize_arguments(@args)
@@ -187,6 +209,12 @@ def queue_match?(job)
187209
@queue == job[:queue]
188210
end
189211

212+
def priority_match?(job)
213+
return true unless @priority
214+
215+
@priority == fetch_priority(job)
216+
end
217+
190218
def at_match?(job)
191219
return true unless @at
192220
return job[:at].nil? if @at == :no_wait

spec/rspec/rails/matchers/active_job_spec.rb

+40-6
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,40 @@ def perform; raise StandardError; end
262262
}.to have_enqueued_job.on_queue(:low)
263263
end
264264

265+
it "passes with provided priority number as integer" do
266+
expect {
267+
hello_job.set(priority: 2).perform_later
268+
}.to have_enqueued_job.at_priority(2)
269+
end
270+
271+
it "passes with provided priority number as string" do
272+
expect {
273+
hello_job.set(priority: 2).perform_later
274+
}.to have_enqueued_job.at_priority("2")
275+
end
276+
277+
it "fails when the priority wan't set" do
278+
expect {
279+
expect {
280+
hello_job.perform_later
281+
}.to have_enqueued_job.at_priority(2)
282+
}.to fail_with(/expected to enqueue exactly 1 jobs, with priority 2, but enqueued 0.+ with no priority specified/m)
283+
end
284+
285+
it "fails when the priority was set to a different value" do
286+
expect {
287+
expect {
288+
hello_job.set(priority: 1).perform_later
289+
}.to have_enqueued_job.at_priority(2)
290+
}.to fail_with(/expected to enqueue exactly 1 jobs, with priority 2, but enqueued 0.+ with priority 1/m)
291+
end
292+
293+
pending "accepts matchers as arguments to at_priority" do
294+
expect {
295+
hello_job.set(priority: 1).perform_later
296+
}.to have_enqueued_job.at_priority(eq(1))
297+
end
298+
265299
it "passes with provided at date" do
266300
date = Date.tomorrow.noon
267301
expect {
@@ -370,14 +404,14 @@ def perform; raise StandardError; end
370404

371405
it "generates failure message with all provided options" do
372406
date = Date.tomorrow.noon
373-
message = "expected to enqueue exactly 2 jobs, with [42], on queue low, at #{date}, but enqueued 0" \
407+
message = "expected to enqueue exactly 2 jobs, with [42], on queue low, at #{date}, with priority 5, but enqueued 0" \
374408
"\nQueued jobs:" \
375-
"\n HelloJob job with [1], on queue default"
409+
"\n HelloJob job with [1], on queue default, with no priority specified"
376410

377411
expect {
378412
expect {
379413
hello_job.perform_later(1)
380-
}.to have_enqueued_job(hello_job).with(42).on_queue("low").at(date).exactly(2).times
414+
}.to have_enqueued_job(hello_job).with(42).on_queue("low").at(date).at_priority(5).exactly(2).times
381415
}.to fail_with(message)
382416
end
383417

@@ -687,14 +721,14 @@ def perform; raise StandardError; end
687721

688722
it "generates failure message with all provided options" do
689723
date = Date.tomorrow.noon
690-
message = "expected to perform exactly 2 jobs, with [42], on queue low, at #{date}, but performed 0" \
724+
message = "expected to perform exactly 2 jobs, with [42], on queue low, at #{date}, with priority 5, but performed 0" \
691725
"\nQueued jobs:" \
692-
"\n HelloJob job with [1], on queue default"
726+
"\n HelloJob job with [1], on queue default, with no priority specified"
693727

694728
expect {
695729
expect {
696730
hello_job.perform_later(1)
697-
}.to have_performed_job(hello_job).with(42).on_queue("low").at(date).exactly(2).times
731+
}.to have_performed_job(hello_job).with(42).on_queue("low").at(date).at_priority(5).exactly(2).times
698732
}.to fail_with(message)
699733
end
700734

0 commit comments

Comments
 (0)