110 lines
3.4 KiB
Ruby
110 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module SidekiqHelpers
|
|
# Assert job is enqueued:
|
|
#
|
|
# expect_enqueued_with(job: :post_process, args: { post_id: post.id }) do
|
|
# post.update!(raw: 'new raw')
|
|
# end
|
|
#
|
|
# Asserting jobs enqueued with delay:
|
|
#
|
|
# expect_enqueued_with(
|
|
# job: :post_process,
|
|
# args: { post_id: post.id },
|
|
# at: Time.zone.now + 1.hour
|
|
# ) do
|
|
# post.update!(raw: 'new raw')
|
|
# end
|
|
def expect_enqueued_with(job:, args: {}, at: nil, expectation: true)
|
|
klass = job.instance_of?(Class) ? job : "::Jobs::#{job.to_s.camelcase}".constantize
|
|
at = at.to_f if at.is_a?(Time)
|
|
expected = { job: job, args: args, at: at }.compact
|
|
original_jobs = klass.jobs.dup
|
|
|
|
yield if block_given?
|
|
|
|
matched_job = false
|
|
jobs = klass.jobs - original_jobs
|
|
matched_job = match_jobs(jobs: jobs, args: args, at: at) if jobs.present?
|
|
|
|
expect(matched_job).to(
|
|
eq(expectation),
|
|
(
|
|
if expectation
|
|
"No enqueued job with #{expected}\nFound:\n #{jobs.inspect}"
|
|
else
|
|
"Enqueued job with #{expected} found"
|
|
end
|
|
),
|
|
)
|
|
end
|
|
|
|
# Assert job is not enqueued:
|
|
#
|
|
# expect_not_enqueued_with(job: :post_process) do
|
|
# post.update!(raw: 'new raw')
|
|
# end
|
|
#
|
|
# Assert job is not enqueued with specific params
|
|
#
|
|
# expect_not_enqueued_with(job: :post_process, args: { post_id: post.id }) do
|
|
# post.update!(raw: 'new raw')
|
|
# end
|
|
def expect_not_enqueued_with(job:, args: {}, at: nil)
|
|
expect_enqueued_with(job: job, args: args, at: at, expectation: false) { yield if block_given? }
|
|
end
|
|
|
|
# Checks whether a job has been enqueued with the given arguments
|
|
#
|
|
# job_enqueued?(job: :post_process, args: { post_id: post.id }) => true/false
|
|
# job_enqueued?(job: :post_process, args: { post_id: post.id }, at: Time.zone.now + 1.hour) => true/false
|
|
def job_enqueued?(job:, args: {}, at: nil)
|
|
klass = job.instance_of?(Class) ? job : "::Jobs::#{job.to_s.camelcase}".constantize
|
|
at = at.to_f if at.is_a?(Time)
|
|
match_jobs(jobs: klass.jobs, args: args, at: at)
|
|
end
|
|
|
|
# Same as job_enqueued? except it checks the expectation is true.
|
|
# Use this if you need to check if more than one job is enqueued from
|
|
# a single command, unlike expect_enqueued_with which needs a block
|
|
# to run code for the expectation to work. E.g.
|
|
#
|
|
# expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id })
|
|
# expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id })
|
|
# subject.execute
|
|
# expect_job_enqueued(job: :close_topic, args: { topic_timer_id: timer1.id })
|
|
# expect_job_enqueued(job: :open_topic, args: { topic_timer_id: timer2.id })
|
|
def expect_job_enqueued(job:, args: {}, at: nil)
|
|
expect(job_enqueued?(job: job, args: args, at: at)).to eq(true)
|
|
end
|
|
|
|
private
|
|
|
|
def match_jobs(jobs:, args:, at:)
|
|
matched_job = false
|
|
|
|
args = JSON.parse(args.to_json)
|
|
args.merge!(at: at) if at
|
|
|
|
jobs.each do |job|
|
|
job_args = job["args"].first.with_indifferent_access
|
|
job_args.merge!(at: job["at"]) if job["at"]
|
|
job_args.merge!(enqueued_at: job["enqueued_at"]) if job["enqueued_at"]
|
|
|
|
matched_job ||=
|
|
args.all? do |key, value|
|
|
value = value.to_s if value.is_a?(Symbol)
|
|
|
|
if key == :at
|
|
value.to_f == (job_args[:at] || job_args[:enqueued_at]).to_f
|
|
else
|
|
value == job_args[key]
|
|
end
|
|
end
|
|
end
|
|
|
|
matched_job
|
|
end
|
|
end
|