Allow all ActiveJob assertion helper to accept Proc in their `only` kw:

- That feature is useful to enqueue or assert that jobs got enqueued
  or performed based on dynamic conditions.
  We will be able to leverage that feature to fix all ActionMailer
  assertion helper issue when a Mailer define a custom delivery job
  (see next commit).
This commit is contained in:
Edouard CHIN 2018-11-21 22:43:14 +01:00
parent ca0339215f
commit cdb16ac576
4 changed files with 101 additions and 4 deletions

View File

@ -1,3 +1,8 @@
* Allow all assertion helpers that have a `only` and `except` keyword to accept
Procs.
*Edouard Chin*
* Restore HashWithIndifferentAccess support to ActiveJob::Arguments.deserialize.
*Gannon McGibbon*

View File

@ -65,11 +65,17 @@ module ActiveJob
def filtered_job_class?(job)
if filter
!Array(filter).include?(job.class)
!filter_as_proc(filter).call(job)
elsif reject
Array(reject).include?(job.class)
filter_as_proc(reject).call(job)
end
end
def filter_as_proc(filter)
return filter if filter.is_a?(Proc)
->(job) { Array(filter).include?(job.class) }
end
end
end
end

View File

@ -107,6 +107,9 @@ module ActiveJob
# end
# end
#
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
# a hash containing the job's class and it's argument are passed as argument.
#
# Asserts the number of times a job is enqueued to a specific queue by passing +:queue+ option.
#
# def test_logging_job
@ -163,6 +166,9 @@ module ActiveJob
# end
# end
#
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
# a hash containing the job's class and it's argument are passed as argument.
#
# Asserts that no jobs are enqueued to a specific queue by passing +:queue+ option
#
# def test_no_logging
@ -243,6 +249,18 @@ module ActiveJob
# end
# end
#
# A proc may also be specified. When passed a Proc, the job's instance will be passed as argument.
#
# def test_hello_and_logging_jobs
# assert_nothing_raised do
# assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
# HelloJob.perform_later('jeremy')
# LoggingJob.perform_later('stewie')
# RescueJob.perform_later('david')
# end
# end
# end
#
# If the +:queue+ option is specified,
# then only the job(s) enqueued to a specific queue will be performed.
#
@ -305,6 +323,9 @@ module ActiveJob
# end
# end
#
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
# an instance of the job will be passed as argument.
#
# If the +:queue+ option is specified,
# then only the job(s) enqueued to a specific queue will not be performed.
#
@ -505,6 +526,9 @@ module ActiveJob
# assert_performed_jobs 1
# end
#
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
# an instance of the job will be passed as argument.
#
# If the +:queue+ option is specified,
# then only the job(s) enqueued to a specific queue will be performed.
#
@ -569,9 +593,9 @@ module ActiveJob
job_class = job.fetch(:job)
if only
next false unless Array(only).include?(job_class)
next false unless filter_as_proc(only).call(job)
elsif except
next false if Array(except).include?(job_class)
next false if filter_as_proc(except).call(job)
end
if queue
@ -584,6 +608,12 @@ module ActiveJob
end
end
def filter_as_proc(filter)
return filter if filter.is_a?(Proc)
->(job) { Array(filter).include?(job.fetch(:job)) }
end
def enqueued_jobs_with(only: nil, except: nil, queue: nil, &block)
jobs_with(enqueued_jobs, only: only, except: except, queue: queue, &block)
end

View File

@ -114,6 +114,16 @@ class EnqueuedJobsTest < ActiveJob::TestCase
end
end
def test_assert_enqueued_jobs_with_only_option_as_proc
assert_nothing_raised do
assert_enqueued_jobs(1, only: ->(job) { job.fetch(:job).name == "HelloJob" }) do
HelloJob.perform_later("jeremy")
LoggingJob.perform_later
LoggingJob.perform_later
end
end
end
def test_assert_enqueued_jobs_with_except_option
assert_nothing_raised do
assert_enqueued_jobs 1, except: LoggingJob do
@ -124,6 +134,16 @@ class EnqueuedJobsTest < ActiveJob::TestCase
end
end
def test_assert_enqueued_jobs_with_except_option_as_proc
assert_nothing_raised do
assert_enqueued_jobs(1, except: ->(job) { job.fetch(:job).name == "LoggingJob" }) do
HelloJob.perform_later("jeremy")
LoggingJob.perform_later
LoggingJob.perform_later
end
end
end
def test_assert_enqueued_jobs_with_only_and_except_option
error = assert_raise ArgumentError do
assert_enqueued_jobs 1, only: HelloJob, except: HelloJob do
@ -911,6 +931,15 @@ class PerformedJobsTest < ActiveJob::TestCase
end
end
def test_assert_performed_jobs_with_only_option_as_proc
assert_nothing_raised do
assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
end
end
end
def test_assert_performed_jobs_without_block_with_only_option
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
@ -920,6 +949,15 @@ class PerformedJobsTest < ActiveJob::TestCase
assert_performed_jobs 1, only: HelloJob
end
def test_assert_performed_jobs_without_block_with_only_option_as_proc
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
perform_enqueued_jobs
assert_performed_jobs(1, only: ->(job) { job.fetch(:job).name == "HelloJob" })
end
def test_assert_performed_jobs_without_block_with_only_option_failure
LoggingJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
@ -942,6 +980,15 @@ class PerformedJobsTest < ActiveJob::TestCase
end
end
def test_assert_performed_jobs_with_except_option_as_proc
assert_nothing_raised do
assert_performed_jobs(1, except: ->(job) { job.is_a?(HelloJob) }) do
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
end
end
end
def test_assert_performed_jobs_without_block_with_except_option
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
@ -951,6 +998,15 @@ class PerformedJobsTest < ActiveJob::TestCase
assert_performed_jobs 1, except: HelloJob
end
def test_assert_performed_jobs_without_block_with_except_option_as_proc
HelloJob.perform_later("jeremy")
LoggingJob.perform_later("bogdan")
perform_enqueued_jobs
assert_performed_jobs(1, except: ->(job) { job.fetch(:job).name == "HelloJob" })
end
def test_assert_performed_jobs_without_block_with_except_option_failure
HelloJob.perform_later("jeremy")
HelloJob.perform_later("bogdan")