rspec-sidekiq_pro 0.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 +7 -0
- data/LICENSE +22 -0
- data/README.md +38 -0
- data/lib/rspec/sidekiq_pro/batches.rb +204 -0
- data/lib/rspec/sidekiq_pro/matchers/enqueue_sidekiq_jobs.rb +59 -0
- data/lib/rspec/sidekiq_pro/matchers/have_enqueued_sidekiq_jobs.rb +43 -0
- data/lib/rspec/sidekiq_pro/matchers/job_matcher.rb +230 -0
- data/lib/rspec/sidekiq_pro/matchers.rb +48 -0
- data/lib/rspec/sidekiq_pro/version.rb +7 -0
- data/lib/rspec/sidekiq_pro.rb +14 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ab301b38f104fcdeda2a304b6f87f4d50e67ed15f01340b08c7d77643b35d98b
|
4
|
+
data.tar.gz: bdcf93f32eb2ec8040c286e864fa204ce01f066f88e76f6f0b5b9e61ec16cb11
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e86e8d44fcdad8b55dd826ae835fabc40b235dba13c90d471dbfef38e609d3d19a18a4ea4d6b9f65ec4c42db7a9f0690d97ad9ef582aed6303ebdad41ba5ecce
|
7
|
+
data.tar.gz: e682c9fe04fb2e49866a11af75d052d3003127e150444af0769332f983a3fe55f1f76e153db56beaca6bd4e6cb901117be42f5974016ddbcbfd17ea1780a02f6
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2022 Savater Sebastien
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Rspec for Sidekiq Pro
|
2
|
+
|
3
|
+
### Installation
|
4
|
+
|
5
|
+
```bash
|
6
|
+
bundle add rspec-sidekiq_pro
|
7
|
+
```
|
8
|
+
|
9
|
+
### Usage
|
10
|
+
|
11
|
+
TODO
|
12
|
+
|
13
|
+
## Contributing
|
14
|
+
|
15
|
+
1. Don't hesitate to submit your feature/idea/fix in [issues](https://github.com/inkstak/rspec-sidekiq_pro)
|
16
|
+
2. Fork the [repository](https://github.com/inkstak/rspec-sidekiq_pro)
|
17
|
+
3. Create your feature branch
|
18
|
+
4. Ensure RSpec & Rubocop are passing
|
19
|
+
4. Create a pull request
|
20
|
+
|
21
|
+
### Tests & lint
|
22
|
+
|
23
|
+
```bash
|
24
|
+
bundle exec rspec
|
25
|
+
bundle exec rubocop
|
26
|
+
```
|
27
|
+
|
28
|
+
Both can be run with:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
bundle exec rake
|
32
|
+
```
|
33
|
+
|
34
|
+
## License & credits
|
35
|
+
|
36
|
+
Please see [LICENSE](https://github.com/inkstak/rspec-sidekiq_pro/blob/main/LICENSE) for further details.
|
37
|
+
|
38
|
+
Contributors: [./graphs/contributors](https://github.com/inkstak/rspec-sidekiq_pro/graphs/contributors)
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module SidekiqPro
|
5
|
+
module Batches
|
6
|
+
module Props
|
7
|
+
class << self
|
8
|
+
delegate :size, :first, :last, :each, :empty?, :any?, :none?, to: :batches_array
|
9
|
+
delegate :fetch, to: :batches_hash
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
if key.is_a?(Numeric)
|
13
|
+
batches_array[key]
|
14
|
+
else
|
15
|
+
batches_hash[key]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(bid, batch)
|
20
|
+
batch["bid"] = bid
|
21
|
+
batches_array << batch
|
22
|
+
batches_hash[bid] = batch
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(bid)
|
26
|
+
batch = batches_hash.delete(bid)
|
27
|
+
batches_array.delete(batch)
|
28
|
+
end
|
29
|
+
|
30
|
+
def clear_all
|
31
|
+
batches_array.clear
|
32
|
+
batches_hash.clear
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_a
|
36
|
+
batches_array
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_h
|
40
|
+
batches_hash
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def batches_array
|
46
|
+
@batches_array ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
def batches_hash
|
50
|
+
@batches_hash ||= {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class << self
|
56
|
+
delegate :size, :delete, :clear_all, :empty?, :any?, :none?, to: Props
|
57
|
+
delegate_missing_to :each
|
58
|
+
|
59
|
+
def each
|
60
|
+
return to_enum(:each) unless block_given?
|
61
|
+
|
62
|
+
Props.each do |props|
|
63
|
+
yield Sidekiq::Batch.new(props["bid"])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def [](key)
|
68
|
+
Sidekiq::Batch.new(Props[key]["bid"])
|
69
|
+
end
|
70
|
+
|
71
|
+
def first
|
72
|
+
Sidekiq::Batch.new(Props.first["bid"])
|
73
|
+
end
|
74
|
+
|
75
|
+
def last
|
76
|
+
Sidekiq::Batch.new(Props.last["bid"])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module Sidekiq
|
84
|
+
class Batch
|
85
|
+
def initialize(bid = nil)
|
86
|
+
if Sidekiq::Testing.disabled?
|
87
|
+
super
|
88
|
+
else
|
89
|
+
@bid = bid || SecureRandom.urlsafe_base64(10)
|
90
|
+
props = RSpec::SidekiqPro::Batches::Props.fetch(bid, {})
|
91
|
+
|
92
|
+
@created_at = props.fetch("created_at", Time.now.utc).to_f
|
93
|
+
@description = props["description"]
|
94
|
+
@parent_bid = props["parent"]
|
95
|
+
@callbacks = props.fetch("callbacks", {})
|
96
|
+
@jids = props.fetch("jids", [])
|
97
|
+
@mutable = props.empty?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def redis(bid, &block)
|
102
|
+
return super if Sidekiq::Testing.disabled?
|
103
|
+
|
104
|
+
raise "Redis unavailbale when Sidekiq::Testing is enable"
|
105
|
+
end
|
106
|
+
|
107
|
+
def jids
|
108
|
+
return super if Sidekiq::Testing.disabled?
|
109
|
+
|
110
|
+
@jids
|
111
|
+
end
|
112
|
+
|
113
|
+
def include?(jid)
|
114
|
+
return super if Sidekiq::Testing.disabled?
|
115
|
+
|
116
|
+
@jids.include?(jid)
|
117
|
+
end
|
118
|
+
|
119
|
+
def invalidate_all
|
120
|
+
return super if Sidekiq::Testing.disabled?
|
121
|
+
|
122
|
+
RSpec::SidekiqPro::Batches::Props[bid]["invalidated"] = true
|
123
|
+
Sidekiq::Queues.jobs_by_queue.each_value { |jobs| jobs.delete_if { |job| include?(job["jid"]) } }
|
124
|
+
Sidekiq::Queues.jobs_by_class.each_value { |jobs| jobs.delete_if { |job| include?(job["jid"]) } }
|
125
|
+
end
|
126
|
+
|
127
|
+
def invalidate_jids(*jids)
|
128
|
+
return super if Sidekiq::Testing.disabled?
|
129
|
+
|
130
|
+
# TODO
|
131
|
+
end
|
132
|
+
|
133
|
+
def invalidated?
|
134
|
+
return super if Sidekiq::Testing.disabled?
|
135
|
+
|
136
|
+
!!RSpec::SidekiqPro::Batches::Props[bid]["invalidated"]
|
137
|
+
end
|
138
|
+
|
139
|
+
def jobs(&block)
|
140
|
+
return super if Sidekiq::Testing.disabled?
|
141
|
+
|
142
|
+
raise ArgumentError, "Must specify a block" unless block
|
143
|
+
|
144
|
+
if mutable?
|
145
|
+
@parent_bid = Thread.current[:sidekiq_batch]&.bid
|
146
|
+
|
147
|
+
RSpec::SidekiqPro::Batches::Props[bid] = {
|
148
|
+
"created_at" => created_at,
|
149
|
+
"description" => description,
|
150
|
+
"parent" => parent_bid,
|
151
|
+
"callbacks" => callbacks,
|
152
|
+
"jids" => jids
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
@mutable = false
|
157
|
+
|
158
|
+
begin
|
159
|
+
parent = Thread.current[:sidekiq_batch]
|
160
|
+
Thread.current[:sidekiq_batch] = self
|
161
|
+
yield
|
162
|
+
ensure
|
163
|
+
Thread.current[:sidekiq_batch] = parent
|
164
|
+
end
|
165
|
+
|
166
|
+
RSpec::SidekiqPro::Batches::Props[bid]["jids"] = @jids
|
167
|
+
end
|
168
|
+
|
169
|
+
def register(jid)
|
170
|
+
return super if Sidekiq::Testing.disabled?
|
171
|
+
|
172
|
+
@jids << jid
|
173
|
+
end
|
174
|
+
|
175
|
+
def perform_callback(event)
|
176
|
+
raise NotImplementedError if Sidekiq::Testing.disabled?
|
177
|
+
|
178
|
+
callbacks[event.to_s]&.each do |callback|
|
179
|
+
callback.each do |target, options|
|
180
|
+
klass_name, method = target.to_s.split("#")
|
181
|
+
klass = klass_name.constantize
|
182
|
+
meth = method || "on_#{event}"
|
183
|
+
inst = klass.new
|
184
|
+
inst.jid = SecureRandom.hex(12) if inst.respond_to?(:jid)
|
185
|
+
inst.send(meth, status, options)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class Status
|
191
|
+
def initialize(bid)
|
192
|
+
if Sidekiq::Testing.disabled?
|
193
|
+
super
|
194
|
+
else
|
195
|
+
@bid = bid
|
196
|
+
@props = RSpec::SidekiqPro::Batches::Props.fetch(bid, {})
|
197
|
+
@pending = 0
|
198
|
+
@failures = 0
|
199
|
+
@total = @props.fetch("jids", []).size
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/sidekiq_pro/matchers/job_matcher"
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module SidekiqPro
|
7
|
+
module Matchers
|
8
|
+
class EnqueueSidekiqJobs
|
9
|
+
include JobMatcher
|
10
|
+
|
11
|
+
def initialize(worker_class)
|
12
|
+
@worker_class = worker_class
|
13
|
+
end
|
14
|
+
|
15
|
+
def supports_block_expectations?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def supports_value_expectations?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def matches?(block)
|
24
|
+
super(capture_actual_jobs(block))
|
25
|
+
end
|
26
|
+
|
27
|
+
def does_not_match?(block)
|
28
|
+
super(capture_actual_jobs(block))
|
29
|
+
end
|
30
|
+
|
31
|
+
def description
|
32
|
+
"enqueue #{expected_job_description}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_message
|
36
|
+
"expected to enqueue #{worker_class} job\n#{failure_message_diff}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def failure_message_when_negated
|
40
|
+
"expected not to enqueue #{worker_class} job\n#{failure_message_diff}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def capture_actual_jobs(block)
|
44
|
+
before = worker_class.jobs.dup
|
45
|
+
result = block.call
|
46
|
+
|
47
|
+
if @expected_arguments.is_a?(Proc)
|
48
|
+
arguments = @expected_arguments.call(result)
|
49
|
+
raise "arguments returned from a proc are expected to be an Array" unless arguments.is_a?(Array)
|
50
|
+
|
51
|
+
@expected_arguments = normalize_arguments(arguments)
|
52
|
+
end
|
53
|
+
|
54
|
+
worker_class.jobs - before
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/sidekiq_pro/matchers/job_matcher"
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module SidekiqPro
|
7
|
+
module Matchers
|
8
|
+
class HaveEnqueuedSidekiqJobs
|
9
|
+
include JobMatcher
|
10
|
+
|
11
|
+
def supports_block_expectations?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def supports_value_expectations?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(worker_class)
|
20
|
+
@worker_class = worker_class
|
21
|
+
super(worker_class.jobs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def does_not_match?(worker_class)
|
25
|
+
@worker_class = worker_class
|
26
|
+
super(worker_class.jobs)
|
27
|
+
end
|
28
|
+
|
29
|
+
def description
|
30
|
+
"have enqueued #{expected_job_description}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message
|
34
|
+
"expected to have enqueued #{worker_class} job\n#{failure_message_diff}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def failure_message_when_negated
|
38
|
+
"expected not to have enqueued #{worker_class} job\n#{failure_message_diff}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module SidekiqPro
|
5
|
+
module Matchers
|
6
|
+
module JobMatcher
|
7
|
+
include ::RSpec::Matchers::Composable
|
8
|
+
|
9
|
+
attr_reader :worker_class,
|
10
|
+
:expected_arguments,
|
11
|
+
:expected_interval,
|
12
|
+
:expected_timestamp,
|
13
|
+
:expected_schedule,
|
14
|
+
:expected_count,
|
15
|
+
:expected_without_batch,
|
16
|
+
:expected_batch,
|
17
|
+
:actual_jobs
|
18
|
+
|
19
|
+
def with(*expected_arguments, &block)
|
20
|
+
if block
|
21
|
+
raise ArgumentError, "setting block to `with` is not supported for this matcher" if supports_value_expectations?
|
22
|
+
raise ArgumentError, "setting arguments and block together in `with` is not supported" if expected_arguments.any?
|
23
|
+
|
24
|
+
@expected_arguments = block
|
25
|
+
else
|
26
|
+
@expected_arguments = normalize_arguments(expected_arguments)
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def in(interval)
|
33
|
+
raise "setting expecations with both `at` and `in` is not supported" if @expected_timestamp
|
34
|
+
|
35
|
+
@expected_interval = interval
|
36
|
+
@expected_schedule = interval.from_now.to_i
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def at(timestamp)
|
41
|
+
raise "setting expecations with both `at` and `in` is not supported" if @expected_interval
|
42
|
+
|
43
|
+
@expected_timestamp = timestamp
|
44
|
+
@expected_schedule = timestamp.to_i
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def once
|
49
|
+
exactly(1)
|
50
|
+
end
|
51
|
+
|
52
|
+
def twice
|
53
|
+
exactly(2)
|
54
|
+
end
|
55
|
+
|
56
|
+
def exactly(times)
|
57
|
+
@expected_count = times
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def times
|
62
|
+
self
|
63
|
+
end
|
64
|
+
alias_method :time, :times
|
65
|
+
|
66
|
+
def without_batch
|
67
|
+
raise "setting expecations with both `without_batch` and `within_batch` is not supported" if @expected_batch
|
68
|
+
|
69
|
+
@expected_without_batch = true
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def within_batch(batch_expectation = :__undef__, &block)
|
74
|
+
raise "setting expecations with both `without_batch` and `within_batch` is not supported" if @expected_without_batch
|
75
|
+
|
76
|
+
if block
|
77
|
+
raise ArgumentError, "setting arguments and block together in `with_batch` is not supported" if batch_expectation != :__undef__
|
78
|
+
|
79
|
+
@expected_batch = block
|
80
|
+
else
|
81
|
+
@expected_batch = batch_expectation
|
82
|
+
end
|
83
|
+
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def matches?(jobs)
|
88
|
+
@actual_jobs = jobs
|
89
|
+
filtered_jobs = filter_jobs(actual_jobs)
|
90
|
+
|
91
|
+
if expected_count
|
92
|
+
filtered_jobs.count == expected_count
|
93
|
+
else
|
94
|
+
filtered_jobs.any?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def does_not_match?(jobs)
|
99
|
+
@actual_jobs = jobs
|
100
|
+
filtered_jobs = filter_jobs(actual_jobs)
|
101
|
+
|
102
|
+
if expected_count
|
103
|
+
filtered_jobs.count != expected_count
|
104
|
+
else
|
105
|
+
filtered_jobs.empty?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def normalize_arguments(arguments)
|
110
|
+
JSON.parse(JSON.dump(arguments))
|
111
|
+
end
|
112
|
+
|
113
|
+
def output_arguments(arguments)
|
114
|
+
arguments.map(&:inspect).join(", ")
|
115
|
+
end
|
116
|
+
|
117
|
+
def expected_job_description
|
118
|
+
description = "#{worker_class} job"
|
119
|
+
|
120
|
+
if expected_count == 1
|
121
|
+
description += " once"
|
122
|
+
elsif expected_count == 2
|
123
|
+
description += " twice"
|
124
|
+
elsif expected_count
|
125
|
+
description += " #{expected_count} times"
|
126
|
+
end
|
127
|
+
|
128
|
+
if expected_arguments.is_a?(Proc)
|
129
|
+
description += " with some arguments"
|
130
|
+
elsif expected_arguments
|
131
|
+
description += " with arguments #{expected_arguments}"
|
132
|
+
end
|
133
|
+
|
134
|
+
description
|
135
|
+
end
|
136
|
+
|
137
|
+
def failure_message_diff
|
138
|
+
diff = []
|
139
|
+
diff << " exactly: #{expected_count} time(s)" if expected_count
|
140
|
+
diff << " arguments: #{expected_arguments}" if expected_arguments
|
141
|
+
diff << " in: #{expected_interval_output}" if expected_interval
|
142
|
+
diff << " at: #{expected_timestamp}" if expected_timestamp
|
143
|
+
diff << " batch: #{output_batch(expected_batch)}" if expected_batch
|
144
|
+
diff << " batch: no batch" if expected_without_batch
|
145
|
+
diff << "" if diff.any?
|
146
|
+
|
147
|
+
if actual_jobs.empty?
|
148
|
+
diff << "no #{worker_class} found"
|
149
|
+
elsif !expected_arguments && !expected_schedule && !expected_without_batch && !expected_batch
|
150
|
+
diff << "found #{actual_jobs.size} #{worker_class}"
|
151
|
+
else
|
152
|
+
diff << "found #{actual_jobs.size} #{worker_class}:"
|
153
|
+
|
154
|
+
actual_jobs.each do |job|
|
155
|
+
job_message = []
|
156
|
+
job_message << "arguments: #{job["args"]}" if expected_arguments
|
157
|
+
job_message << "at: #{output_schedule(job["at"])}" if expected_schedule && job["at"]
|
158
|
+
job_message << "at: no schedule" if expected_schedule && !job["at"]
|
159
|
+
job_message << "batch: #{output_batch(job["bid"])}" if (expected_without_batch || expected_batch) && job["bid"]
|
160
|
+
job_message << "batch: no batch" if (expected_without_batch || expected_batch) && !job["bid"]
|
161
|
+
|
162
|
+
diff += job_message.map.with_index do |line, index|
|
163
|
+
if actual_jobs.size == 1
|
164
|
+
" #{line}"
|
165
|
+
elsif index.zero?
|
166
|
+
" - #{line}"
|
167
|
+
else
|
168
|
+
" #{line}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
diff.join("\n")
|
175
|
+
end
|
176
|
+
|
177
|
+
def expected_interval_output
|
178
|
+
"#{expected_interval.inspect} (#{output_schedule(expected_schedule)})"
|
179
|
+
end
|
180
|
+
|
181
|
+
def output_schedule(timestamp)
|
182
|
+
Time.at(timestamp) if timestamp
|
183
|
+
end
|
184
|
+
|
185
|
+
def output_batch(value)
|
186
|
+
case value
|
187
|
+
when :__undef__ then "to be present"
|
188
|
+
when String then "<Sidekiq::Batch bid: #{value.inspect}>"
|
189
|
+
when Sidekiq::Batch then "<Sidekiq::Batch bid: #{value.bid.inspect}>"
|
190
|
+
else
|
191
|
+
if value.respond_to?(:description)
|
192
|
+
value.description
|
193
|
+
else
|
194
|
+
value
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def filter_jobs(jobs)
|
200
|
+
jobs.select do |job|
|
201
|
+
next if expected_arguments && !values_match?(expected_arguments, job["args"])
|
202
|
+
next if expected_schedule && !values_match?(expected_schedule.to_i, job["at"].to_i)
|
203
|
+
next if expected_without_batch && job["bid"]
|
204
|
+
next if expected_batch && !batch_match?(expected_batch, job["bid"])
|
205
|
+
|
206
|
+
true
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def batch_match?(expected_batch, bid)
|
211
|
+
case expected_batch
|
212
|
+
when :__undef__
|
213
|
+
!bid.nil?
|
214
|
+
when String
|
215
|
+
expected_batch == bid
|
216
|
+
|
217
|
+
when ::Sidekiq::Batch
|
218
|
+
expected_batch.bid == bid
|
219
|
+
|
220
|
+
else
|
221
|
+
return unless bid
|
222
|
+
|
223
|
+
batch = ::Sidekiq::Batch.new(bid)
|
224
|
+
values_match?(expected_batch, batch)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/sidekiq_pro/matchers/enqueue_sidekiq_jobs"
|
4
|
+
require "rspec/sidekiq_pro/matchers/have_enqueued_sidekiq_jobs"
|
5
|
+
|
6
|
+
module RSpec
|
7
|
+
module SidekiqPro
|
8
|
+
module Matchers
|
9
|
+
# Checks if a certain job was enqueued.
|
10
|
+
#
|
11
|
+
# AwesomeWorker.perform_async
|
12
|
+
# expect(AwesomeWorker).to have_enqueued_sidekiq_job
|
13
|
+
#
|
14
|
+
# AwesomeWorker.perform_async(42, 'David')
|
15
|
+
# expect(AwesomeWorker).to have_enqueued_sidekiq_job.with(42, 'David')
|
16
|
+
#
|
17
|
+
# AwesomeWorker.perform_in(5.minutes)
|
18
|
+
# expect(AwesomeWorker).to have_enqueued_sidekiq_job.in(5.minutes)
|
19
|
+
#
|
20
|
+
def have_enqueued_sidekiq_job
|
21
|
+
HaveEnqueuedSidekiqJobs.new.once
|
22
|
+
end
|
23
|
+
|
24
|
+
def have_enqueued_sidekiq_jobs
|
25
|
+
HaveEnqueuedSidekiqJobs.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks if a certain job was enqueued in a block.
|
29
|
+
#
|
30
|
+
# expect { AwesomeWorker.perform_async }
|
31
|
+
# .to enqueue_sidekiq_job(AwesomeWorker)
|
32
|
+
#
|
33
|
+
# expect { AwesomeWorker.perform_async(42, 'David')
|
34
|
+
# .to enqueue_sidekiq_job(AwesomeWorker).with(42, 'David')
|
35
|
+
#
|
36
|
+
# expect { AwesomeWorker.perform_in(5.minutes) }
|
37
|
+
# .to enqueue_sidekiq_job(AwesomeWorker).in(5.minutes)
|
38
|
+
#
|
39
|
+
def enqueue_sidekiq_job(worker_class)
|
40
|
+
EnqueueSidekiqJobs.new(worker_class).once
|
41
|
+
end
|
42
|
+
|
43
|
+
def enqueue_sidekiq_jobs(worker_class)
|
44
|
+
EnqueueSidekiqJobs.new(worker_class)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
require "sidekiq"
|
5
|
+
require "sidekiq-pro"
|
6
|
+
require "sidekiq/testing"
|
7
|
+
require "active_support/duration"
|
8
|
+
require "active_support/core_ext/module/delegation"
|
9
|
+
require "rspec/sidekiq_pro/matchers"
|
10
|
+
require "rspec/sidekiq_pro/batches"
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include RSpec::SidekiqPro::Matchers
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-sidekiq_pro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Savater Sebastien
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '6.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.11'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.11'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sidekiq
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '6.5'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '6.5'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: sidekiq-pro
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '5.5'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '5.5'
|
75
|
+
description:
|
76
|
+
email: github.60k5k@simplelogin.co
|
77
|
+
executables: []
|
78
|
+
extensions: []
|
79
|
+
extra_rdoc_files: []
|
80
|
+
files:
|
81
|
+
- LICENSE
|
82
|
+
- README.md
|
83
|
+
- lib/rspec/sidekiq_pro.rb
|
84
|
+
- lib/rspec/sidekiq_pro/batches.rb
|
85
|
+
- lib/rspec/sidekiq_pro/matchers.rb
|
86
|
+
- lib/rspec/sidekiq_pro/matchers/enqueue_sidekiq_jobs.rb
|
87
|
+
- lib/rspec/sidekiq_pro/matchers/have_enqueued_sidekiq_jobs.rb
|
88
|
+
- lib/rspec/sidekiq_pro/matchers/job_matcher.rb
|
89
|
+
- lib/rspec/sidekiq_pro/version.rb
|
90
|
+
homepage: http://github.com/inkstak/rspec-sidekiq_pro
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.3.7
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: A collection of tools and matchers for Sidekiq Pro
|
113
|
+
test_files: []
|