Skip to content

Commit

Permalink
Merge pull request #2350 from rspec/improve-enqueued-job-at
Browse files Browse the repository at this point in the history
Improve enqueued_job at specs and warn about precision.
  • Loading branch information
JonRowe committed May 28, 2020
2 parents aa0cd35 + f9c3bc1 commit 631a226
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
24 changes: 23 additions & 1 deletion lib/rspec/rails/matchers/active_job.rb
Expand Up @@ -163,7 +163,29 @@ def at_match?(job)
return job[:at].nil? if @at == :no_wait
return false unless job[:at]

values_match?(@at, Time.at(job[:at]))
scheduled_at = Time.at(job[:at])
values_match?(@at, scheduled_at) || check_for_inprecise_value(scheduled_at)
end

def check_for_inprecise_value(scheduled_at)
return unless Time === @at && values_match?(@at.change(usec: 0), scheduled_at)

RSpec.warn_with((<<-WARNING).gsub(/^\s+\|/, '').chomp)
|[WARNING] Your expected `at(...)` value does not match the job scheduled_at value
|unless microseconds are removed. This precision error often occurs when checking
|values against `Time.current` / `Time.now` which have usec precision, but Rails
|uses `n.seconds.from_now` internally which has a usec count of `0`.
|
|Use `change(usec: 0)` to correct these values. For example:
|
|`Time.current.change(usec: 0)`
|
|Note: RSpec cannot do this for you because jobs can be scheduled with usec
|precision and we do not know wether it is on purpose or not.
|
|
WARNING
false
end

def set_expected_number(relativity, count)
Expand Down
19 changes: 15 additions & 4 deletions spec/rspec/rails/matchers/active_job_spec.rb
Expand Up @@ -225,14 +225,25 @@ def self.name; "LoggingJob"; end
}.to have_enqueued_job.at(time)
end

skip_freeze_time = method_defined?(:freeze_time) ? false : "#freeze_time is undefined"
it "works with time offsets", skip: skip_freeze_time do
freeze_time do
time = Time.current
it "works with time offsets" do
# note that Time.current does not replicate Rails behavior for 5 seconds from now.
time = Time.current.change(usec: 0)
travel_to time do
expect { hello_job.set(wait: 5).perform_later }.to have_enqueued_job.at(time + 5)
end
end

it "warns when time offsets are inprecise" do
expect(RSpec).to receive(:warn_with).with(/precision error/)

time = Time.current.change(usec: 550)
travel_to time do
expect {
expect { hello_job.set(wait: 5).perform_later }.to have_enqueued_job.at(time + 5)
}.to raise_error(/expected to enqueue exactly 1 jobs/)
end
end

it "accepts composable matchers as an at date" do
future = 1.minute.from_now
slightly_earlier = 58.seconds.from_now
Expand Down

0 comments on commit 631a226

Please sign in to comment.