rspec-sidekiq 4.2.0 → 5.1.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 -2
- data/README.md +84 -41
- data/lib/rspec/sidekiq/batch.rb +4 -1
- data/lib/rspec/sidekiq/configuration.rb +6 -0
- data/lib/rspec/sidekiq/helpers/within_sidekiq_retries_exhausted_block.rb +5 -3
- data/lib/rspec/sidekiq/helpers.rb +2 -0
- data/lib/rspec/sidekiq/matchers/base.rb +119 -13
- data/lib/rspec/sidekiq/matchers/be_delayed.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_expired_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_processed_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_retryable.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_unique.rb +23 -1
- data/lib/rspec/sidekiq/matchers/enqueue_sidekiq_job.rb +8 -16
- data/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb +12 -11
- data/lib/rspec/sidekiq/matchers/save_backtrace.rb +2 -0
- data/lib/rspec/sidekiq/matchers.rb +2 -0
- data/lib/rspec/sidekiq/sidekiq.rb +2 -0
- data/lib/rspec/sidekiq/version.rb +3 -1
- data/lib/rspec-sidekiq.rb +2 -0
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56ce84afbf67491fa24da1f527bced61c54afa3d62dbb50e6a09a89e8c0bc16c
|
4
|
+
data.tar.gz: 5b4a368bbb098d580713009fb9381d66326c37eced31c91eaf85b43158a85db5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ec18b3d6ceff7390807d7358259b44f236ca6d81b1b9175c069b6c4912041b914082042a5396c7cf1eb0b602a5448d9aacd9e23b3cee211ad7222c3ec3719af
|
7
|
+
data.tar.gz: 4f0232e7b482f7c565a5cca98be9b7143e51adbe6015329f9d052e393fd857fe97e2449fb53f9e3d209ff6319c54e23e9e2919e7003a44bfc00834692039eed0
|
data/CHANGES.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
Unreleased
|
2
2
|
---
|
3
|
+
* Add `until` matcher for Sidekiq Enterprise unique jobs (#232, #147)
|
4
|
+
* Add `with_context` matcher for matching against job contexts (#222)
|
5
|
+
* Support for Sidekiq 8 (#233)
|
6
|
+
* Add `frozen_string_literal: true` (#220)
|
7
|
+
* Fix queue always nil in default_retries_exhausted_message (#229)
|
8
|
+
* Fix pattern matching warnings on Ruby 2.7 (#227)
|
9
|
+
|
10
|
+
5.0.0
|
11
|
+
---
|
12
|
+
* [BREAKING] Make `have_enqueued_sidekiq_job()` match jobs with any arguments (same as `enqueue_sidekiq_job()` or `have_enqueued_sidekiq_job(any_args)`) (#215)
|
13
|
+
* Add support for expected number of jobs to both `enqueue_sidekiq_job` and `have_enqueued_sidekiq_job` (#219)
|
3
14
|
|
4
15
|
4.2.0
|
5
16
|
---
|
6
|
-
* Add warning about `have_enqueued_sidekiq_job` with no arguments (default will
|
7
|
-
change in next major release) (#216, #217)
|
17
|
+
* Add warning about `have_enqueued_sidekiq_job` with no arguments (default will change in next major release) (#216, #217)
|
8
18
|
|
9
19
|
4.1.0
|
10
20
|
---
|
data/README.md
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
**Welcome @wspurgin as new maintainer for `rspec-sidekiq`!**
|
2
|
-
|
3
1
|
[](https://badge.fury.io/rb/rspec-sidekiq)
|
4
2
|
[![Github Actions CI][github_actions_badge]][github_actions]
|
5
3
|
|
@@ -34,14 +32,16 @@ end
|
|
34
32
|
```
|
35
33
|
|
36
34
|
## 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
|
-
* [
|
35
|
+
* [```enqueue_sidekiq_job```](#enqueue_sidekiq_job)
|
36
|
+
* [```have_enqueued_sidekiq_job```](#have_enqueued_sidekiq_job)
|
37
|
+
* [```be_processed_in```](#be_processed_in)
|
38
|
+
* [```be_retryable```](#be_retryable)
|
39
|
+
* [```save_backtrace```](#save_backtrace)
|
40
|
+
* [```be_unique```](#be_unique)
|
41
|
+
* [```be_expired_in```](#be_expired_in)
|
42
|
+
* [```be_delayed``` (_deprecated_)](#be_delayed)
|
43
43
|
|
44
|
-
### enqueue_sidekiq_job
|
44
|
+
### ```enqueue_sidekiq_job```
|
45
45
|
|
46
46
|
*Describes that the block should enqueue a job*. Optionally specify the
|
47
47
|
specific job class, arguments, timing, and other context
|
@@ -68,6 +68,28 @@ freeze_time do
|
|
68
68
|
expect { AwesomeJob.perform_in(1.hour) }.to enqueue_sidekiq_job.in(1.hour)
|
69
69
|
end
|
70
70
|
|
71
|
+
# A specific number of times
|
72
|
+
|
73
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.once
|
74
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(1).time
|
75
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(:once)
|
76
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(1).time
|
77
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(:once)
|
78
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(2).times
|
79
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:twice)
|
80
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:thrice)
|
81
|
+
|
82
|
+
# With specific context:
|
83
|
+
# Useful for testing anything `set` on the job, including
|
84
|
+
# overrides to things like `retry`
|
85
|
+
expect {
|
86
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
87
|
+
}.to enqueue_sidekiq_job.with_context(trace_id: anything)
|
88
|
+
|
89
|
+
expect {
|
90
|
+
AwesomeJob.set(retry: 5).perform_async
|
91
|
+
}.to enqueue_sidekiq_job.with_context(retry: 5)
|
92
|
+
|
71
93
|
# Combine and chain them as desired
|
72
94
|
expect { AwesomeJob.perform_at(specific_time, "Awesome!") }.to(
|
73
95
|
enqueue_sidekiq_job(AwesomeJob)
|
@@ -83,13 +105,14 @@ expect do
|
|
83
105
|
end.to enqueue_sidekiq_job(AwesomeJob).and enqueue_sidekiq_job(OtherJob)
|
84
106
|
```
|
85
107
|
|
86
|
-
### have_enqueued_sidekiq_job
|
108
|
+
### ```have_enqueued_sidekiq_job```
|
87
109
|
|
88
|
-
Describes that there should be an enqueued job with the
|
110
|
+
Describes that there should be an enqueued job (with the specified arguments):
|
89
111
|
|
90
112
|
```ruby
|
91
113
|
AwesomeJob.perform_async 'Awesome', true
|
92
114
|
# test with...
|
115
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job
|
93
116
|
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true)
|
94
117
|
```
|
95
118
|
|
@@ -106,6 +129,26 @@ expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_excluding("bad_stuff" => an
|
|
106
129
|
expect(AwesomeJob).to have_enqueued_sidekiq_job(any_args).and have_enqueued_sidekiq_job(hash_including("something" => "Awesome"))
|
107
130
|
```
|
108
131
|
|
132
|
+
You can specify the number of jobs enqueued:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.once
|
136
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(1).time
|
137
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(:once)
|
138
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(1).time
|
139
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(:once)
|
140
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(2).times
|
141
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:twice)
|
142
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:thrice)
|
143
|
+
```
|
144
|
+
|
145
|
+
Likewise, specify what should be in the context:
|
146
|
+
```ruby
|
147
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
148
|
+
|
149
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.with_context(trace_id: anything)
|
150
|
+
```
|
151
|
+
|
109
152
|
#### Testing scheduled jobs
|
110
153
|
|
111
154
|
*Use chainable matchers `#at`, `#in` and `#immediately`*
|
@@ -166,30 +209,7 @@ expect(Sidekiq::Worker).to have_enqueued_sidekiq_job(
|
|
166
209
|
)
|
167
210
|
```
|
168
211
|
|
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
|
212
|
+
### ```be_processed_in```
|
193
213
|
*Describes the queue that a job should be processed in*
|
194
214
|
```ruby
|
195
215
|
sidekiq_options queue: :download
|
@@ -198,8 +218,12 @@ expect(AwesomeJob).to be_processed_in :download # or
|
|
198
218
|
it { is_expected.to be_processed_in :download }
|
199
219
|
```
|
200
220
|
|
201
|
-
### be_retryable
|
221
|
+
### ```be_retryable```
|
202
222
|
*Describes if a job should retry when there is a failure in its execution*
|
223
|
+
|
224
|
+
Note: this only tests against the `retry` option in the job's Sidekiq options.
|
225
|
+
To test an enqueued job's retry, i.e. `AwesomeJob.set(retry: 5)`, use
|
226
|
+
`with_context`
|
203
227
|
```ruby
|
204
228
|
sidekiq_options retry: 5
|
205
229
|
# test with...
|
@@ -213,7 +237,7 @@ expect(AwesomeJob).to be_retryable false # or
|
|
213
237
|
it { is_expected.to be_retryable false }
|
214
238
|
```
|
215
239
|
|
216
|
-
### save_backtrace
|
240
|
+
### ```save_backtrace```
|
217
241
|
*Describes if a job should save the error backtrace when there is a failure in its execution*
|
218
242
|
```ruby
|
219
243
|
sidekiq_options backtrace: 5
|
@@ -230,16 +254,35 @@ it { is_expected.to_not save_backtrace } # or
|
|
230
254
|
it { is_expected.to save_backtrace false }
|
231
255
|
```
|
232
256
|
|
233
|
-
### be_unique
|
257
|
+
### ```be_unique```
|
258
|
+
|
259
|
+
:warning: This is intended to for Sidekiq Enterprise unique job implementation.
|
260
|
+
There is _limited_ support for Sidekiq Unique Jobs, but compatibility is not
|
261
|
+
guaranteed.
|
262
|
+
|
234
263
|
*Describes when a job should be unique within its queue*
|
235
264
|
```ruby
|
236
|
-
sidekiq_options
|
265
|
+
sidekiq_options unique_for: 1.hour
|
237
266
|
# test with...
|
238
267
|
expect(AwesomeJob).to be_unique
|
239
268
|
it { is_expected.to be_unique }
|
269
|
+
|
270
|
+
# specify a specific interval
|
271
|
+
sidekiq_options unique_for: 1.hour
|
272
|
+
it { is_expected.to be_unique.for(1.hour) }
|
240
273
|
```
|
241
274
|
|
242
|
-
|
275
|
+
#### `until` sub-matcher
|
276
|
+
|
277
|
+
:warning: This sub-matcher only works for Sidekiq Enterprise
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
sidekiq_options unique_for: 1.hour, unique_until: :start
|
281
|
+
it { is_expected.to be_unique.until(:start) }
|
282
|
+
```
|
283
|
+
|
284
|
+
|
285
|
+
### ```be_expired_in```
|
243
286
|
*Describes when a job should expire*
|
244
287
|
```ruby
|
245
288
|
sidekiq_options expires_in: 1.hour
|
@@ -248,7 +291,7 @@ it { is_expected.to be_expired_in 1.hour }
|
|
248
291
|
it { is_expected.to_not be_expired_in 2.hours }
|
249
292
|
```
|
250
293
|
|
251
|
-
### be_delayed
|
294
|
+
### ```be_delayed```
|
252
295
|
|
253
296
|
**This matcher is deprecated**. Use of it with Sidekiq 7+ will raise an error.
|
254
297
|
Sidekiq 7 [dropped Delayed
|
data/lib/rspec/sidekiq/batch.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rubygems"
|
2
4
|
require "set"
|
3
5
|
|
@@ -22,6 +24,10 @@ module RSpec
|
|
22
24
|
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
|
23
25
|
end
|
24
26
|
|
27
|
+
def sidekiq_gte_8?
|
28
|
+
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("8.0.0")
|
29
|
+
end
|
30
|
+
|
25
31
|
def silence_warning(symbol)
|
26
32
|
@silence_warnings << symbol
|
27
33
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Worker
|
3
5
|
module ClassMethods
|
@@ -8,15 +10,15 @@ module Sidekiq
|
|
8
10
|
|
9
11
|
def default_retries_exhausted_message
|
10
12
|
{
|
11
|
-
'queue' => get_sidekiq_options[
|
13
|
+
'queue' => get_sidekiq_options['queue'],
|
12
14
|
'class' => name,
|
13
15
|
'args' => [],
|
14
|
-
'error_message' => 'An error
|
16
|
+
'error_message' => 'An error occurred'
|
15
17
|
}
|
16
18
|
end
|
17
19
|
|
18
20
|
def default_retries_exhausted_exception
|
19
|
-
StandardError.new('An error
|
21
|
+
StandardError.new('An error occurred')
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -26,7 +28,7 @@ module RSpec
|
|
26
28
|
# send to custom evaluator
|
27
29
|
at_evaluator(value)
|
28
30
|
else
|
29
|
-
job.context.has_key?(key) && job.context[key]
|
31
|
+
job.context.has_key?(key) && RSpec::Support::FuzzyMatcher.values_match?(value, job.context[key])
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -58,7 +60,11 @@ module RSpec
|
|
58
60
|
private
|
59
61
|
|
60
62
|
def active_job?
|
61
|
-
|
63
|
+
if RSpec::Sidekiq.configuration.sidekiq_gte_8?
|
64
|
+
job["class"] == "Sidekiq::ActiveJob::Wrapper"
|
65
|
+
else
|
66
|
+
job["class"] == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
70
|
def deserialized_active_job_args
|
@@ -118,8 +124,19 @@ module RSpec
|
|
118
124
|
@jobs = unwrap_jobs(klass.jobs).map { |job| EnqueuedJob.new(job) }
|
119
125
|
end
|
120
126
|
|
121
|
-
def includes?(arguments, options)
|
122
|
-
|
127
|
+
def includes?(arguments, options, count)
|
128
|
+
matching = jobs.filter { |job| matches?(job, arguments, options) }
|
129
|
+
|
130
|
+
case count[0]
|
131
|
+
when :exactly
|
132
|
+
matching.size == count[1]
|
133
|
+
when :at_least
|
134
|
+
matching.size >= count[1]
|
135
|
+
when :at_most
|
136
|
+
matching.size <= count[1]
|
137
|
+
else
|
138
|
+
matching.size > 0
|
139
|
+
end
|
123
140
|
end
|
124
141
|
|
125
142
|
def each(&block)
|
@@ -164,11 +181,12 @@ module RSpec
|
|
164
181
|
include RSpec::Mocks::ArgumentMatchers
|
165
182
|
include RSpec::Matchers::Composable
|
166
183
|
|
167
|
-
attr_reader :expected_arguments, :expected_options, :klass, :actual_jobs
|
184
|
+
attr_reader :expected_arguments, :expected_options, :klass, :actual_jobs, :expected_count
|
168
185
|
|
169
186
|
def initialize
|
170
187
|
@expected_arguments = [any_args]
|
171
188
|
@expected_options = {}
|
189
|
+
set_expected_count :positive, 1
|
172
190
|
end
|
173
191
|
|
174
192
|
def with(*expected_arguments)
|
@@ -196,12 +214,79 @@ module RSpec
|
|
196
214
|
self
|
197
215
|
end
|
198
216
|
|
217
|
+
def once
|
218
|
+
set_expected_count :exactly, 1
|
219
|
+
self
|
220
|
+
end
|
221
|
+
|
222
|
+
def twice
|
223
|
+
set_expected_count :exactly, 2
|
224
|
+
self
|
225
|
+
end
|
226
|
+
|
227
|
+
def thrice
|
228
|
+
set_expected_count :exactly, 3
|
229
|
+
self
|
230
|
+
end
|
231
|
+
|
232
|
+
def exactly(n)
|
233
|
+
set_expected_count :exactly, n
|
234
|
+
self
|
235
|
+
end
|
236
|
+
|
237
|
+
def at_least(n)
|
238
|
+
set_expected_count :at_least, n
|
239
|
+
self
|
240
|
+
end
|
241
|
+
|
242
|
+
def at_most(n)
|
243
|
+
set_expected_count :at_most, n
|
244
|
+
self
|
245
|
+
end
|
246
|
+
|
247
|
+
def times
|
248
|
+
self
|
249
|
+
end
|
250
|
+
alias :time :times
|
251
|
+
|
252
|
+
def with_context(**kwargs)
|
253
|
+
raise ArgumentError, "Must specify keyword arguments to with_context" if kwargs.empty?
|
254
|
+
|
255
|
+
# gather keys and compare against currently set expected_options
|
256
|
+
# Someone could have accidentally used with_context and other
|
257
|
+
# chainables with different expectations. Better to explicitly
|
258
|
+
# inform loudly of clashes than let them overwrite silently
|
259
|
+
normalized = normalize_arguments(kwargs)
|
260
|
+
already_set = normalized.keys & @expected_options.keys
|
261
|
+
if already_set.any?
|
262
|
+
prettied = already_set.map { |key| "'#{key}'" }
|
263
|
+
raise ArgumentError, "There are already expectations against #{prettied.join(",")}. Did you already call other context chainables like `on` or `at`?"
|
264
|
+
end
|
265
|
+
|
266
|
+
# We're good, no accidental overwrites of expectations
|
267
|
+
@expected_options.merge!(normalized)
|
268
|
+
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
272
|
+
def set_expected_count(relativity, n)
|
273
|
+
n =
|
274
|
+
case n
|
275
|
+
when Integer then n
|
276
|
+
when :once then 1
|
277
|
+
when :twice then 2
|
278
|
+
when :thrice then 3
|
279
|
+
else raise ArgumentError, "Unsupported #{n} in '#{relativity} #{n}'. Use either an Integer, :once, :twice, or :thrice."
|
280
|
+
end
|
281
|
+
@expected_count = [relativity, n]
|
282
|
+
end
|
283
|
+
|
199
284
|
def description
|
200
|
-
"
|
285
|
+
"#{common_message} with arguments #{expected_arguments}"
|
201
286
|
end
|
202
287
|
|
203
288
|
def failure_message
|
204
|
-
message = ["expected to
|
289
|
+
message = ["expected to #{common_message}"]
|
205
290
|
if expected_arguments
|
206
291
|
message << " with arguments:"
|
207
292
|
message << " -#{formatted(expected_arguments)}"
|
@@ -213,27 +298,48 @@ module RSpec
|
|
213
298
|
end
|
214
299
|
|
215
300
|
if actual_jobs.any?
|
216
|
-
message << "but
|
301
|
+
message << "but enqueued only jobs"
|
217
302
|
if expected_arguments
|
218
303
|
job_messages = actual_jobs.map do |job|
|
219
|
-
base = " -JID:#{job.jid} with arguments:"
|
220
|
-
base << "
|
304
|
+
base = [" -JID:#{job.jid} with arguments:"]
|
305
|
+
base << " -#{formatted(job.args)}"
|
221
306
|
if expected_options.any?
|
222
|
-
base << "
|
307
|
+
base << " with context: #{formatted(job.context)}"
|
223
308
|
end
|
224
309
|
|
225
|
-
base
|
310
|
+
base.join("\n")
|
226
311
|
end
|
227
312
|
|
228
313
|
message << job_messages.join("\n")
|
229
314
|
end
|
315
|
+
else
|
316
|
+
message << "but enqueued 0 jobs"
|
230
317
|
end
|
231
318
|
|
232
319
|
message.join("\n")
|
233
320
|
end
|
234
321
|
|
322
|
+
def common_message
|
323
|
+
"#{prefix_message} #{count_message} #{klass} #{expected_count.last == 1 ? "job" : "jobs"}"
|
324
|
+
end
|
325
|
+
|
326
|
+
def prefix_message
|
327
|
+
raise NotImplementedError
|
328
|
+
end
|
329
|
+
|
330
|
+
def count_message
|
331
|
+
case expected_count[0]
|
332
|
+
when :positive
|
333
|
+
"a"
|
334
|
+
when :exactly
|
335
|
+
expected_count[1]
|
336
|
+
else
|
337
|
+
"#{expected_count[0].to_s.gsub('_', ' ')} #{expected_count[1]}"
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
235
341
|
def failure_message_when_negated
|
236
|
-
message = ["expected not to
|
342
|
+
message = ["expected not to #{common_message} but enqueued #{actual_jobs.count}"]
|
237
343
|
message << " arguments: #{expected_arguments}" if expected_arguments.any?
|
238
344
|
message << " options: #{expected_options}" if expected_options.any?
|
239
345
|
message.join("\n")
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -25,6 +27,9 @@ module RSpec
|
|
25
27
|
if !interval_matches? && @expected_interval
|
26
28
|
"expected #{@klass} to be unique for #{@expected_interval} seconds, "\
|
27
29
|
"but its interval was #{actual_interval} seconds"
|
30
|
+
elsif !expiration_matches?
|
31
|
+
"expected #{@klass} to be unique until #{@expected_expiration}, "\
|
32
|
+
"but its unique_until was #{actual_expiration || 'not specified'}"
|
28
33
|
else
|
29
34
|
"expected #{@klass} to be unique in the queue"
|
30
35
|
end
|
@@ -33,7 +38,7 @@ module RSpec
|
|
33
38
|
def matches?(job)
|
34
39
|
@klass = job.is_a?(Class) ? job : job.class
|
35
40
|
@actual = @klass.get_sidekiq_options[unique_key]
|
36
|
-
!!(value_matches? && interval_matches?)
|
41
|
+
!!(value_matches? && interval_matches? && expiration_matches?)
|
37
42
|
end
|
38
43
|
|
39
44
|
def for(interval)
|
@@ -41,6 +46,11 @@ module RSpec
|
|
41
46
|
self
|
42
47
|
end
|
43
48
|
|
49
|
+
def until(expiration)
|
50
|
+
@expected_expiration = expiration
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
44
54
|
def interval_specified?
|
45
55
|
@expected_interval
|
46
56
|
end
|
@@ -49,6 +59,10 @@ module RSpec
|
|
49
59
|
!interval_specified? || actual_interval == @expected_interval
|
50
60
|
end
|
51
61
|
|
62
|
+
def expiration_matches?
|
63
|
+
@expected_expiration.nil? || actual_expiration == @expected_expiration
|
64
|
+
end
|
65
|
+
|
52
66
|
def failure_message_when_negated
|
53
67
|
"expected #{@klass} to not be unique in the queue"
|
54
68
|
end
|
@@ -59,6 +73,10 @@ module RSpec
|
|
59
73
|
@klass.get_sidekiq_options['unique_job_expiration']
|
60
74
|
end
|
61
75
|
|
76
|
+
def actual_expiration
|
77
|
+
fail 'until is not supported for SidekiqUniqueJobs'
|
78
|
+
end
|
79
|
+
|
62
80
|
def value_matches?
|
63
81
|
[true, :all].include?(@actual)
|
64
82
|
end
|
@@ -73,6 +91,10 @@ module RSpec
|
|
73
91
|
@actual
|
74
92
|
end
|
75
93
|
|
94
|
+
def actual_expiration
|
95
|
+
@klass.get_sidekiq_options['unique_until']
|
96
|
+
end
|
97
|
+
|
76
98
|
def value_matches?
|
77
99
|
@actual && @actual > 0
|
78
100
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -27,24 +29,11 @@ module RSpec
|
|
27
29
|
return false
|
28
30
|
end
|
29
31
|
|
30
|
-
@actual_jobs.includes?(expected_arguments, expected_options)
|
32
|
+
@actual_jobs.includes?(expected_arguments, expected_options, expected_count)
|
31
33
|
end
|
32
34
|
|
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")
|
35
|
+
def prefix_message
|
36
|
+
"enqueue"
|
48
37
|
end
|
49
38
|
|
50
39
|
def supports_block_expectations?
|
@@ -85,6 +74,9 @@ module RSpec
|
|
85
74
|
# expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.immediately
|
86
75
|
# expect { AwesomeJob.perform_at(1.hour.ago) }.to enqueue_sidekiq_job.immediately
|
87
76
|
#
|
77
|
+
# # With specific context
|
78
|
+
# expect { AwesomeJob.set(trace_id: "something").perform_async }.to enqueue_sidekiq_job.with_context(trace_id: anything)
|
79
|
+
#
|
88
80
|
# ## Composable
|
89
81
|
#
|
90
82
|
# expect do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -7,18 +9,8 @@ module RSpec
|
|
7
9
|
|
8
10
|
# @api private
|
9
11
|
class HaveEnqueuedSidekiqJob < Base
|
10
|
-
DEPRECATION = [
|
11
|
-
"[WARNING] `have_enqueued_sidekiq_job()` without arguments default behavior will change in next major release.",
|
12
|
-
"Use `have_enqueued_sidekiq_job(no_args)` to maintain legacy behavior.",
|
13
|
-
"More available here: https://github.com/wspurgin/rspec-sidekiq/wiki/have_enqueued_sidekiq_job-without-argument-default-behavior"
|
14
|
-
].join(" ").freeze
|
15
|
-
|
16
12
|
def initialize(expected_arguments)
|
17
13
|
super()
|
18
|
-
|
19
|
-
if expected_arguments == [] && RSpec::Sidekiq.configuration.warn_for?(:have_enqueued_sidekiq_job_default)
|
20
|
-
Kernel.warn(DEPRECATION, uplevel: 3)
|
21
|
-
end
|
22
14
|
@expected_arguments = normalize_arguments(expected_arguments)
|
23
15
|
end
|
24
16
|
|
@@ -26,7 +18,16 @@ module RSpec
|
|
26
18
|
@klass = job_class
|
27
19
|
|
28
20
|
@actual_jobs = EnqueuedJobs.new(klass)
|
29
|
-
|
21
|
+
|
22
|
+
actual_jobs.includes?(
|
23
|
+
expected_arguments == [] ? any_args : expected_arguments,
|
24
|
+
expected_options,
|
25
|
+
expected_count
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def prefix_message
|
30
|
+
"have enqueued"
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
data/lib/rspec-sidekiq.rb
CHANGED
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.1.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: 2025-03-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-core
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: '5'
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
66
|
+
version: '9'
|
67
67
|
type: :runtime
|
68
68
|
prerelease: false
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
version: '5'
|
74
74
|
- - "<"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '9'
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
78
|
name: pry
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
@@ -228,6 +228,20 @@ dependencies:
|
|
228
228
|
- - ">="
|
229
229
|
- !ruby/object:Gem::Version
|
230
230
|
version: '0'
|
231
|
+
- !ruby/object:Gem::Dependency
|
232
|
+
name: railties
|
233
|
+
requirement: !ruby/object:Gem::Requirement
|
234
|
+
requirements:
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
type: :development
|
239
|
+
prerelease: false
|
240
|
+
version_requirements: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '0'
|
231
245
|
description: Simple testing of Sidekiq jobs via a collection of matchers and helpers
|
232
246
|
email:
|
233
247
|
executables: []
|
@@ -257,7 +271,8 @@ files:
|
|
257
271
|
homepage: http://github.com/wspurgin/rspec-sidekiq
|
258
272
|
licenses:
|
259
273
|
- MIT
|
260
|
-
metadata:
|
274
|
+
metadata:
|
275
|
+
changelog_uri: https://github.com/wspurgin/rspec-sidekiq/blob/main/CHANGES.md
|
261
276
|
post_install_message:
|
262
277
|
rdoc_options: []
|
263
278
|
require_paths:
|
@@ -273,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
273
288
|
- !ruby/object:Gem::Version
|
274
289
|
version: '0'
|
275
290
|
requirements: []
|
276
|
-
rubygems_version: 3.
|
291
|
+
rubygems_version: 3.5.22
|
277
292
|
signing_key:
|
278
293
|
specification_version: 4
|
279
294
|
summary: RSpec for Sidekiq
|