module RSpec module Sidekiq module Matchers # @api private class EnqueueSidekiqJob < Base attr_reader :original_jobs # Plus that from Base def initialize(job_class) super() default = if RSpec::Sidekiq.configuration.sidekiq_gte_7? ::Sidekiq::Job else ::Sidekiq::Worker end @klass = job_class || default end def matches?(proc) raise ArgumentError, "Only block syntax supported for enqueue_sidekiq_job" unless Proc === proc @original_jobs = EnqueuedJobs.new(@klass) proc.call @actual_jobs = EnqueuedJobs.new(@klass).minus!(original_jobs) if @actual_jobs.none? return false end @actual_jobs.includes?(expected_arguments, expected_options) end def failure_message if @actual_jobs.none? "expected to enqueue a job but enqueued 0" else super end end def failure_message_when_negated messages = ["expected not to enqueue a #{@klass} job but enqueued #{actual_jobs.count}"] messages << " with arguments #{formatted(expected_arguments)}" if expected_arguments messages << " with context #{formatted(expected_options)}" if expected_options messages.join("\n") end def supports_block_expectations? true end end # @api public # # Passes if a Job is enqueued as the result of a block. Chainable `with` # for arguments, `on` for queue, `at` for queued for a specific time, and # `in` for a specific interval delay to being queued, `immediately` for # queued without delay. # # @example # # expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job # # # A specific job class # expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job(AwesomeJob) # # # with specific arguments # expect { AwesomeJob.perform_async "Awesome!" }.to enqueue_sidekiq_job.with("Awesome!") # # # On a specific queue # expect { AwesomeJob.set(queue: "high").perform_async }.to enqueue_sidekiq_job.on("high") # # # At a specific datetime # specific_time = 1.hour.from_now # expect { AwesomeJob.perform_at(specific_time) }.to enqueue_sidekiq_job.at(specific_time) # # # In a specific interval (be mindful of freezing or managing time here) # freeze_time do # expect { AwesomeJob.perform_in(1.hour) }.to enqueue_sidekiq_job.in(1.hour) # end # # # Without any delay # expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.immediately # expect { AwesomeJob.perform_at(1.hour.ago) }.to enqueue_sidekiq_job.immediately # # ## Composable # # expect do # AwesomeJob.perform_async # OtherJob.perform_async # end.to enqueue_sidekiq_job(AwesomeJob).and enqueue_sidekiq_job(OtherJob) def enqueue_sidekiq_job(job_class = nil) EnqueueSidekiqJob.new(job_class) end end end end