class RSpec::Rails::Matchers::ActiveJob::Base

@private
rubocop: disable Style/ClassLength

def arguments_match?(job)

def arguments_match?(job)
  if @args.any?
    deserialized_args = ::ActiveJob::Arguments.deserialize(job[:args])
    RSpec::Mocks::ArgumentListMatcher.new(*@args).args_match?(*deserialized_args)
  else
    true
  end
end

def at(date)

def at(date)
  @at = date
  self
end

def at_least(count)

def at_least(count)
  set_expected_number(:at_least, count)
  self
end

def at_most(count)

def at_most(count)
  set_expected_number(:at_most, count)
  self
end

def base_job_message(job)

def base_job_message(job)
  msg_parts = []
  msg_parts << "with #{::ActiveJob::Arguments.deserialize(job[:args])}" if job[:args].any?
  msg_parts << "on queue #{job[:queue]}" if job[:queue]
  msg_parts << "at #{Time.at(job[:at])}" if job[:at]
  "#{job[:job].name} job".tap do |msg|
    msg << " #{msg_parts.join(', ')}" if msg_parts.any?
  end
end

def base_message

def base_message
  "#{message_expectation_modifier} #{@expected_number} jobs,".tap do |msg|
    msg << " with #{@args}," if @args.any?
    msg << " on queue #{@queue}," if @queue
    msg << " at #{@at}," if @at
    msg << " but enqueued #{@matching_jobs_count}"
  end
end

def check(jobs)

def check(jobs)
  @matching_jobs, @unmatching_jobs = jobs.partition do |job|
    if arguments_match?(job) && other_attributes_match?(job)
      args = ::ActiveJob::Arguments.deserialize(job[:args])
      @block.call(*args)
      true
    else
      false
    end
  end
  @matching_jobs_count = @matching_jobs.size
  case @expectation_type
  when :exactly then @expected_number == @matching_jobs_count
  when :at_most then @expected_number >= @matching_jobs_count
  when :at_least then @expected_number <= @matching_jobs_count
  end
end

def exactly(count)

def exactly(count)
  set_expected_number(:exactly, count)
  self
end

def failure_message

def failure_message
  "expected to enqueue #{base_message}".tap do |msg|
    if @unmatching_jobs.any?
      msg << "\nQueued jobs:"
      @unmatching_jobs.each do |job|
        msg << "\n  #{base_job_message(job)}"
      end
    end
  end
end

def failure_message_when_negated

def failure_message_when_negated
  "expected not to enqueue #{base_message}"
end

def initialize

def initialize
  @args = []
  @queue = nil
  @at = nil
  @block = Proc.new {}
  set_expected_number(:exactly, 1)
end

def message_expectation_modifier

def message_expectation_modifier
  case @expectation_type
  when :exactly then "exactly"
  when :at_most then "at most"
  when :at_least then "at least"
  end
end

def on_queue(queue)

def on_queue(queue)
  @queue = queue
  self
end

def once

def once
  exactly(:once)
end

def other_attributes_match?(job)

def other_attributes_match?(job)
  serialized_attributes.all? { |key, value| value == job[key] }
end

def queue_adapter

def queue_adapter
  ::ActiveJob::Base.queue_adapter
end

def serialized_attributes

def serialized_attributes
  {}.tap do |attributes|
    attributes[:at]    = @at.to_f if @at
    attributes[:queue] = @queue if @queue
    attributes[:job]   = @job if @job
  end
end

def set_expected_number(relativity, count)

def set_expected_number(relativity, count)
  @expectation_type = relativity
  @expected_number = case count
                     when :once then 1
                     when :twice then 2
                     when :thrice then 3
                     else Integer(count)
                     end
end

def supports_block_expectations?

def supports_block_expectations?
  true
end

def thrice

def thrice
  exactly(:thrice)
end

def times

def times
  self
end

def twice

def twice
  exactly(:twice)
end

def with(*args, &block)

def with(*args, &block)
  @args = args
  @block = block if block.present?
  self
end