rspec-sidekiq 4.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4f0ece401056914cf478dc4657d19aad569156ebf40ee29ee85c36fc430cfc3
4
- data.tar.gz: 858c2c49ae54497a5201eab4cb3d9179fbe21a1684b11663719dfd17dd198cb2
3
+ metadata.gz: e2bbe8c4c2097c67abf526af45ba5a3652fa83e898ccb82732f3639b83cc7d33
4
+ data.tar.gz: ec606df39e62123fd43d595c412f9dd70edc5c93389395b6d6e58f53deccf32a
5
5
  SHA512:
6
- metadata.gz: 831dfa10d07623e001f2253072b6d8e5311a0d887661421ba3eb914fce8f5020b73e5c7bda02264ebf4be6b6f23c2b02f8082a149d7ff5836895525ae61d697c
7
- data.tar.gz: fda99d4e3bd9b43fb55ed60e96f77fd0ca54156bc6dcc42df3f1d2fb9323fff9fc63f5495a595766e937d0214fff10736ef18b9b468fccf4b97b91b2aae5e296
6
+ metadata.gz: 7a601baf7161f039f0fb8b78a8ea3bed432b418431eae0b2e149365922f88d7f7c543450433175c4c16ba974ab91b8050ba1dc927619bbc2162a229f34de94ad
7
+ data.tar.gz: 2964a340caee3c386a99eb8a69a79552782ff2e9cfcdacd9140d50232939138f95297b313620ec658f1e21fa044d946e3f030d8a8a212b3b1af2e1c89a175c6a
data/CHANGES.md CHANGED
@@ -1,3 +1,15 @@
1
+ Unreleased
2
+ ---
3
+
4
+ 5.0.0
5
+ ---
6
+ * [BREAKING] Make `have_enqueued_sidekiq_job()` match jobs with any arguments (same as `enqueue_sidekiq_job()` or `have_enqueued_sidekiq_job(any_args)`) (#215)
7
+ * Add support for expected number of jobs to both `enqueue_sidekiq_job` and `have_enqueued_sidekiq_job` (#219)
8
+
9
+ 4.2.0
10
+ ---
11
+ * Add warning about `have_enqueued_sidekiq_job` with no arguments (default will change in next major release) (#216, #217)
12
+
1
13
  4.1.0
2
14
  ---
3
15
  * Add Composable support to `enqueue_sidekiq_job` and
data/README.md CHANGED
@@ -34,14 +34,16 @@ end
34
34
  ```
35
35
 
36
36
  ## Matchers
37
- * [enqueue_sidekiq_job](#enqueue_sidekiq_job)
38
- * [have_enqueued_sidekiq_job](#have_enqueued_sidekiq_job)
39
- * [be_processed_in](#be_processed_in)
40
- * [be_retryable](#be_retryable)
41
- * [be_unique](#be_unique)
42
- * [be_delayed (_deprecated_)](#be_delayed)
37
+ * [```enqueue_sidekiq_job```](#enqueue_sidekiq_job)
38
+ * [```have_enqueued_sidekiq_job```](#have_enqueued_sidekiq_job)
39
+ * [```be_processed_in```](#be_processed_in)
40
+ * [```be_retryable```](#be_retryable)
41
+ * [```save_backtrace```](#save_backtrace)
42
+ * [```be_unique```](#be_unique)
43
+ * [```be_expired_in```](#be_expired_in)
44
+ * [```be_delayed``` (_deprecated_)](#be_delayed)
43
45
 
44
- ### enqueue_sidekiq_job
46
+ ### ```enqueue_sidekiq_job```
45
47
 
46
48
  *Describes that the block should enqueue a job*. Optionally specify the
47
49
  specific job class, arguments, timing, and other context
@@ -68,6 +70,17 @@ freeze_time do
68
70
  expect { AwesomeJob.perform_in(1.hour) }.to enqueue_sidekiq_job.in(1.hour)
69
71
  end
70
72
 
73
+ # A specific number of times
74
+
75
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.once
76
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(1).time
77
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(:once)
78
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(1).time
79
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(:once)
80
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(2).times
81
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:twice)
82
+ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:thrice)
83
+
71
84
  # Combine and chain them as desired
72
85
  expect { AwesomeJob.perform_at(specific_time, "Awesome!") }.to(
73
86
  enqueue_sidekiq_job(AwesomeJob)
@@ -83,13 +96,14 @@ expect do
83
96
  end.to enqueue_sidekiq_job(AwesomeJob).and enqueue_sidekiq_job(OtherJob)
84
97
  ```
85
98
 
86
- ### have_enqueued_sidekiq_job
99
+ ### ```have_enqueued_sidekiq_job```
87
100
 
88
- Describes that there should be an enqueued job with the **specified arguments**
101
+ Describes that there should be an enqueued job (with the specified arguments):
89
102
 
90
103
  ```ruby
91
104
  AwesomeJob.perform_async 'Awesome', true
92
105
  # test with...
106
+ expect(AwesomeJob).to have_enqueued_sidekiq_job
93
107
  expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true)
94
108
  ```
95
109
 
@@ -106,6 +120,19 @@ expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_excluding("bad_stuff" => an
106
120
  expect(AwesomeJob).to have_enqueued_sidekiq_job(any_args).and have_enqueued_sidekiq_job(hash_including("something" => "Awesome"))
107
121
  ```
108
122
 
123
+ You can specify the number of jobs enqueued:
124
+
125
+ ```ruby
126
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.once
127
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(1).time
128
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(:once)
129
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(1).time
130
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(:once)
131
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(2).times
132
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:twice)
133
+ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:thrice)
134
+ ```
135
+
109
136
  #### Testing scheduled jobs
110
137
 
111
138
  *Use chainable matchers `#at`, `#in` and `#immediately`*
@@ -166,30 +193,7 @@ expect(Sidekiq::Worker).to have_enqueued_sidekiq_job(
166
193
  )
167
194
  ```
168
195
 
169
- #### Testing a job is _not_ enqueued
170
-
171
- The negative case for `have_enqueued_sidekiq_job` is provided, but it's
172
- important to remember that `have_enqueued_sidekiq_job` is an expectation that a
173
- job is enqueued _with specific arguments_. In other words, passing no arguments
174
- to `have_enqueued_sidekiq_job` is implicitly telling the matcher to look for
175
- jobs _without_ arguments.
176
-
177
- In short, unless you tell the matcher that _no_ jobs with _any_ arguments should be enqueued, you'll get the wrong result:
178
-
179
- ```ruby
180
- # example this is a test that we'd expect to fail
181
- AwesomeJob.perform_async "Actually not awesome"
182
-
183
- ### BAD - saying there shouldn't be a job enqueued _without_ args
184
- expect(AwesomeJob).not_to have_enqueued_sidekiq_job
185
- # => passes! 😱 Our job was enqueued _with_ args so no job exists without args.
186
-
187
- ### Good
188
- expect(AwesomeJob).not_to have_enqueued_sidekiq_job(any_args)
189
- # => fails
190
- ```
191
-
192
- ### be_processed_in
196
+ ### ```be_processed_in```
193
197
  *Describes the queue that a job should be processed in*
194
198
  ```ruby
195
199
  sidekiq_options queue: :download
@@ -198,7 +202,7 @@ expect(AwesomeJob).to be_processed_in :download # or
198
202
  it { is_expected.to be_processed_in :download }
199
203
  ```
200
204
 
201
- ### be_retryable
205
+ ### ```be_retryable```
202
206
  *Describes if a job should retry when there is a failure in its execution*
203
207
  ```ruby
204
208
  sidekiq_options retry: 5
@@ -213,7 +217,7 @@ expect(AwesomeJob).to be_retryable false # or
213
217
  it { is_expected.to be_retryable false }
214
218
  ```
215
219
 
216
- ### save_backtrace
220
+ ### ```save_backtrace```
217
221
  *Describes if a job should save the error backtrace when there is a failure in its execution*
218
222
  ```ruby
219
223
  sidekiq_options backtrace: 5
@@ -230,7 +234,7 @@ it { is_expected.to_not save_backtrace } # or
230
234
  it { is_expected.to save_backtrace false }
231
235
  ```
232
236
 
233
- ### be_unique
237
+ ### ```be_unique```
234
238
  *Describes when a job should be unique within its queue*
235
239
  ```ruby
236
240
  sidekiq_options unique: true
@@ -239,7 +243,7 @@ expect(AwesomeJob).to be_unique
239
243
  it { is_expected.to be_unique }
240
244
  ```
241
245
 
242
- ### be_expired_in
246
+ ### ```be_expired_in```
243
247
  *Describes when a job should expire*
244
248
  ```ruby
245
249
  sidekiq_options expires_in: 1.hour
@@ -248,7 +252,7 @@ it { is_expected.to be_expired_in 1.hour }
248
252
  it { is_expected.to_not be_expired_in 2.hours }
249
253
  ```
250
254
 
251
- ### be_delayed
255
+ ### ```be_delayed```
252
256
 
253
257
  **This matcher is deprecated**. Use of it with Sidekiq 7+ will raise an error.
254
258
  Sidekiq 7 [dropped Delayed
@@ -1,4 +1,5 @@
1
1
  require "rubygems"
2
+ require "set"
2
3
 
3
4
  module RSpec
4
5
  module Sidekiq
@@ -14,11 +15,20 @@ module RSpec
14
15
  # Functional settings defaults
15
16
  @clear_all_enqueued_jobs = true
16
17
  @warn_when_jobs_not_processed_by_sidekiq = true
18
+ @silence_warnings = Set.new
17
19
  end
18
20
 
19
21
  def sidekiq_gte_7?
20
22
  Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
21
23
  end
24
+
25
+ def silence_warning(symbol)
26
+ @silence_warnings << symbol
27
+ end
28
+
29
+ def warn_for?(symbol)
30
+ !@silence_warnings.include?(symbol)
31
+ end
22
32
  end
23
33
  end
24
34
  end
@@ -118,8 +118,19 @@ module RSpec
118
118
  @jobs = unwrap_jobs(klass.jobs).map { |job| EnqueuedJob.new(job) }
119
119
  end
120
120
 
121
- def includes?(arguments, options)
122
- !!jobs.find { |job| matches?(job, arguments, options) }
121
+ def includes?(arguments, options, count)
122
+ matching = jobs.filter { |job| matches?(job, arguments, options) }
123
+
124
+ case count
125
+ in [:exactly, n]
126
+ matching.size == n
127
+ in [:at_least, n]
128
+ matching.size >= n
129
+ in [:at_most, n]
130
+ matching.size <= n
131
+ else
132
+ matching.size > 0
133
+ end
123
134
  end
124
135
 
125
136
  def each(&block)
@@ -164,11 +175,12 @@ module RSpec
164
175
  include RSpec::Mocks::ArgumentMatchers
165
176
  include RSpec::Matchers::Composable
166
177
 
167
- attr_reader :expected_arguments, :expected_options, :klass, :actual_jobs
178
+ attr_reader :expected_arguments, :expected_options, :klass, :actual_jobs, :expected_count
168
179
 
169
180
  def initialize
170
181
  @expected_arguments = [any_args]
171
182
  @expected_options = {}
183
+ set_expected_count :positive, 1
172
184
  end
173
185
 
174
186
  def with(*expected_arguments)
@@ -196,12 +208,59 @@ module RSpec
196
208
  self
197
209
  end
198
210
 
211
+ def once
212
+ set_expected_count :exactly, 1
213
+ self
214
+ end
215
+
216
+ def twice
217
+ set_expected_count :exactly, 2
218
+ self
219
+ end
220
+
221
+ def thrice
222
+ set_expected_count :exactly, 3
223
+ self
224
+ end
225
+
226
+ def exactly(n)
227
+ set_expected_count :exactly, n
228
+ self
229
+ end
230
+
231
+ def at_least(n)
232
+ set_expected_count :at_least, n
233
+ self
234
+ end
235
+
236
+ def at_most(n)
237
+ set_expected_count :at_most, n
238
+ self
239
+ end
240
+
241
+ def times
242
+ self
243
+ end
244
+ alias :time :times
245
+
246
+ def set_expected_count(relativity, n)
247
+ n =
248
+ case n
249
+ when Integer then n
250
+ when :once then 1
251
+ when :twice then 2
252
+ when :thrice then 3
253
+ else raise ArgumentError, "Unsupported #{n} in '#{relativity} #{n}'. Use either an Integer, :once, :twice, or :thrice."
254
+ end
255
+ @expected_count = [relativity, n]
256
+ end
257
+
199
258
  def description
200
- "have an enqueued #{klass} job with arguments #{expected_arguments}"
259
+ "#{common_message} with arguments #{expected_arguments}"
201
260
  end
202
261
 
203
262
  def failure_message
204
- message = ["expected to have an enqueued #{klass} job"]
263
+ message = ["expected to #{common_message}"]
205
264
  if expected_arguments
206
265
  message << " with arguments:"
207
266
  message << " -#{formatted(expected_arguments)}"
@@ -213,7 +272,7 @@ module RSpec
213
272
  end
214
273
 
215
274
  if actual_jobs.any?
216
- message << "but have enqueued only jobs"
275
+ message << "but enqueued only jobs"
217
276
  if expected_arguments
218
277
  job_messages = actual_jobs.map do |job|
219
278
  base = " -JID:#{job.jid} with arguments:"
@@ -227,13 +286,34 @@ module RSpec
227
286
 
228
287
  message << job_messages.join("\n")
229
288
  end
289
+ else
290
+ message << "but enqueued 0 jobs"
230
291
  end
231
292
 
232
293
  message.join("\n")
233
294
  end
234
295
 
296
+ def common_message
297
+ "#{prefix_message} #{count_message} #{klass} #{expected_count.last == 1 ? "job" : "jobs"}"
298
+ end
299
+
300
+ def prefix_message
301
+ raise NotImplementedError
302
+ end
303
+
304
+ def count_message
305
+ case expected_count
306
+ in [:positive, _]
307
+ "a"
308
+ in [:exactly, n]
309
+ n
310
+ in [relativity, n]
311
+ "#{relativity.to_s.gsub('_', ' ')} #{n}"
312
+ end
313
+ end
314
+
235
315
  def failure_message_when_negated
236
- message = ["expected not to have an enqueued #{klass} job"]
316
+ message = ["expected not to #{common_message} but enqueued #{actual_jobs.count}"]
237
317
  message << " arguments: #{expected_arguments}" if expected_arguments.any?
238
318
  message << " options: #{expected_options}" if expected_options.any?
239
319
  message.join("\n")
@@ -27,24 +27,11 @@ module RSpec
27
27
  return false
28
28
  end
29
29
 
30
- @actual_jobs.includes?(expected_arguments, expected_options)
30
+ @actual_jobs.includes?(expected_arguments, expected_options, expected_count)
31
31
  end
32
32
 
33
- def failure_message
34
- if @actual_jobs.none?
35
- "expected to enqueue a job but enqueued 0"
36
- else
37
- super
38
- end
39
- end
40
-
41
- def failure_message_when_negated
42
- messages = ["expected not to enqueue a #{@klass} job but enqueued #{actual_jobs.count}"]
43
-
44
- messages << " with arguments #{formatted(expected_arguments)}" if expected_arguments
45
- messages << " with context #{formatted(expected_options)}" if expected_options
46
-
47
- messages.join("\n")
33
+ def prefix_message
34
+ "enqueue"
48
35
  end
49
36
 
50
37
  def supports_block_expectations?
@@ -17,7 +17,15 @@ module RSpec
17
17
 
18
18
  @actual_jobs = EnqueuedJobs.new(klass)
19
19
 
20
- actual_jobs.includes?(expected_arguments, expected_options)
20
+ actual_jobs.includes?(
21
+ expected_arguments == [] ? any_args : expected_arguments,
22
+ expected_options,
23
+ expected_count
24
+ )
25
+ end
26
+
27
+ def prefix_message
28
+ "have enqueued"
21
29
  end
22
30
  end
23
31
  end
@@ -1,4 +1,5 @@
1
1
  require "rspec/core"
2
+ require "rspec/matchers"
2
3
  require "rspec/mocks/argument_list_matcher"
3
4
  require "rspec/mocks/argument_matchers"
4
5
 
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Sidekiq
3
- VERSION = "4.1.0"
3
+ VERSION = "5.0.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aidan Coyle
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-10-27 00:00:00.000000000 Z
13
+ date: 2024-05-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec-core