Module: RSpec::SidekiqPro::Matchers::JobMatcher

Includes:
Matchers::Composable
Included in:
EnqueueSidekiqJobs, HaveEnqueuedSidekiqJobs
Defined in:
lib/rspec/sidekiq_pro/matchers/job_matcher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#actual_jobsObject (readonly)

Returns the value of attribute actual_jobs.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def actual_jobs
  @actual_jobs
end

#expected_argumentsObject (readonly)

Returns the value of attribute expected_arguments.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_arguments
  @expected_arguments
end

#expected_batchObject (readonly)

Returns the value of attribute expected_batch.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_batch
  @expected_batch
end

#expected_countObject (readonly)

Returns the value of attribute expected_count.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_count
  @expected_count
end

#expected_intervalObject (readonly)

Returns the value of attribute expected_interval.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_interval
  @expected_interval
end

#expected_scheduleObject (readonly)

Returns the value of attribute expected_schedule.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_schedule
  @expected_schedule
end

#expected_timestampObject (readonly)

Returns the value of attribute expected_timestamp.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_timestamp
  @expected_timestamp
end

#expected_without_batchObject (readonly)

Returns the value of attribute expected_without_batch.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def expected_without_batch
  @expected_without_batch
end

#worker_classObject (readonly)

Returns the value of attribute worker_class.



9
10
11
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 9

def worker_class
  @worker_class
end

Instance Method Details

#actual_jobs_details_in_failure_messageObject



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 181

def actual_jobs_details_in_failure_message
  actual_jobs.flat_map do |job|
    job_details_in_failure_message(job).map.with_index do |line, index|
      if actual_jobs.size > 1
        indent = "    "
        indent = "  - " if index.zero?
        line = "#{indent}#{line[2..]}"
      end

      line
    end
  end
end

#actual_jobs_size_in_failure_messageObject



150
151
152
153
154
155
156
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 150

def actual_jobs_size_in_failure_message
  if actual_jobs.empty?
    "no #{worker_class} found"
  else
    "found #{actual_jobs.size} #{worker_class}"
  end
end

#at(timestamp) ⇒ Object



39
40
41
42
43
44
45
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 39

def at(timestamp)
  raise "setting expecations with both `at` and `in` is not supported" if @expected_interval

  @expected_timestamp = timestamp
  @expected_schedule = timestamp.to_i
  self
end

#batch_match?(expected_batch, bid) ⇒ Boolean

Returns:

  • (Boolean)


233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 233

def batch_match?(expected_batch, bid)
  case expected_batch
  when :__undef__
    !bid.nil?
  when String
    expected_batch == bid
  when ::Sidekiq::Batch
    expected_batch.bid == bid
  else
    return unless bid

    batch = ::Sidekiq::Batch.new(bid)
    values_match?(expected_batch, batch)
  end
end

#does_not_match?(jobs) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 97

def does_not_match?(jobs)
  @actual_jobs = jobs
  filtered_jobs = filter_jobs(actual_jobs)

  if expected_count
    filtered_jobs.count != expected_count
  else
    filtered_jobs.empty?
  end
end

#exactly(times) ⇒ Object



55
56
57
58
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 55

def exactly(times)
  @expected_count = times
  self
end

#expectations_in_failure_messageObject

rubocop:disable Layout/ExtraSpacing It becomes unreadable when not allowing alignement



160
161
162
163
164
165
166
167
168
169
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 160

def expectations_in_failure_message
  message = []
  message << "  exactly:   #{expected_count} time(s)"       if expected_count
  message << "  arguments: #{expected_arguments}"           if expected_arguments
  message << "  in:        #{expected_interval_output}"     if expected_interval
  message << "  at:        #{expected_timestamp}"           if expected_timestamp
  message << "  batch:     #{output_batch(expected_batch)}" if expected_batch
  message << "  batch:     no batch"                        if expected_without_batch
  message
end

#expected_interval_outputObject

rubocop:enable Layout/ExtraSpacing



197
198
199
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 197

def expected_interval_output
  "#{expected_interval.inspect} (#{output_schedule(expected_schedule)})"
end

#expected_job_descriptionObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 116

def expected_job_description
  description = "#{worker_class} job"

  if expected_count == 1
    description += " once"
  elsif expected_count == 2
    description += " twice"
  elsif expected_count
    description += " #{expected_count} times"
  end

  if expected_arguments.is_a?(Proc)
    description += " with some arguments"
  elsif expected_arguments
    description += " with arguments #{expected_arguments}"
  end

  description
end

#failure_message_diffObject



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 136

def failure_message_diff
  message = []
  message += expectations_in_failure_message
  message << "" if message.any?
  message << actual_jobs_size_in_failure_message

  if expected_arguments || expected_schedule || expected_without_batch || expected_batch
    message[-1] = "#{message[-1]}:"
    message += actual_jobs_details_in_failure_message
  end

  message.join("\n")
end

#filter_jobs(jobs) ⇒ Object



222
223
224
225
226
227
228
229
230
231
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 222

def filter_jobs(jobs)
  jobs.select do |job|
    next if expected_arguments && !values_match?(expected_arguments, job["args"])
    next if expected_schedule && !values_match?(expected_schedule.to_i, job["at"].to_i)
    next if expected_without_batch && job["bid"]
    next if expected_batch && !batch_match?(expected_batch, job["bid"])

    true
  end
end

#in(interval) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 31

def in(interval)
  raise "setting expecations with both `at` and `in` is not supported" if @expected_timestamp

  @expected_interval = interval
  @expected_schedule = interval.from_now.to_i
  self
end

#job_details_in_failure_message(job) ⇒ Object



171
172
173
174
175
176
177
178
179
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 171

def job_details_in_failure_message(job)
  message = []
  message << "  arguments: #{job["args"]}"                if expected_arguments
  message << "  at:        #{output_schedule(job["at"])}" if expected_schedule && job["at"]
  message << "  at:        no schedule"                   if expected_schedule && !job["at"]
  message << "  batch:     #{output_batch(job["bid"])}"   if (expected_without_batch || expected_batch) && job["bid"]
  message << "  batch:     no batch"                      if (expected_without_batch || expected_batch) && !job["bid"]
  message
end

#matches?(jobs) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 86

def matches?(jobs)
  @actual_jobs = jobs
  filtered_jobs = filter_jobs(actual_jobs)

  if expected_count
    filtered_jobs.count == expected_count
  else
    filtered_jobs.any?
  end
end

#normalize_arguments(arguments) ⇒ Object



108
109
110
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 108

def normalize_arguments(arguments)
  JSON.parse(JSON.dump(arguments))
end

#onceObject



47
48
49
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 47

def once
  exactly(1)
end

#output_arguments(arguments) ⇒ Object



112
113
114
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 112

def output_arguments(arguments)
  arguments.map(&:inspect).join(", ")
end

#output_batch(value) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 205

def output_batch(value)
  case value
  when :__undef__
    "to be present"
  when String
    "<Sidekiq::Batch bid: #{value.inspect}>"
  when Sidekiq::Batch
    "<Sidekiq::Batch bid: #{value.bid.inspect}>"
  else
    if value.respond_to?(:description)
      value.description
    else
      value
    end
  end
end

#output_schedule(timestamp) ⇒ Object



201
202
203
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 201

def output_schedule(timestamp)
  Time.at(timestamp) if timestamp
end

#timesObject Also known as: time



60
61
62
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 60

def times
  self
end

#twiceObject



51
52
53
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 51

def twice
  exactly(2)
end

#with(*expected_arguments, &block) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 19

def with(*expected_arguments, &block)
  if block
    raise ArgumentError, "setting block to `with` is not supported for this matcher" if supports_value_expectations?
    raise ArgumentError, "setting arguments and block together in `with` is not supported" if expected_arguments.any?
    @expected_arguments = block
  else
    @expected_arguments = normalize_arguments(expected_arguments)
  end

  self
end

#within_batch(batch_expectation = :__undef__, &block) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 72

def within_batch(batch_expectation = :__undef__, &block)
  raise "setting expecations with both `without_batch` and `within_batch` is not supported" if @expected_without_batch

  if block
    raise ArgumentError, "setting arguments and block together in `with_batch` is not supported" if batch_expectation != :__undef__

    @expected_batch = block
  else
    @expected_batch = batch_expectation
  end

  self
end

#without_batchObject



65
66
67
68
69
70
# File 'lib/rspec/sidekiq_pro/matchers/job_matcher.rb', line 65

def without_batch
  raise "setting expecations with both `without_batch` and `within_batch` is not supported" if @expected_batch

  @expected_without_batch = true
  self
end