rspec-sidekiq 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +12 -0
- data/README.md +42 -38
- data/lib/rspec/sidekiq/configuration.rb +10 -0
- data/lib/rspec/sidekiq/matchers/base.rb +87 -7
- data/lib/rspec/sidekiq/matchers/enqueue_sidekiq_job.rb +3 -16
- data/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb +9 -1
- data/lib/rspec/sidekiq/matchers.rb +1 -0
- data/lib/rspec/sidekiq/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2bbe8c4c2097c67abf526af45ba5a3652fa83e898ccb82732f3639b83cc7d33
|
4
|
+
data.tar.gz: ec606df39e62123fd43d595c412f9dd70edc5c93389395b6d6e58f53deccf32a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
* [
|
42
|
-
* [
|
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
|
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
|
-
|
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
|
-
|
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
|
-
"
|
259
|
+
"#{common_message} with arguments #{expected_arguments}"
|
201
260
|
end
|
202
261
|
|
203
262
|
def failure_message
|
204
|
-
message = ["expected to
|
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
|
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
|
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
|
34
|
-
|
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?(
|
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
|
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
|
+
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:
|
13
|
+
date: 2024-05-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-core
|