rspec-sidekiq 2.2.0 → 3.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
  SHA1:
3
- metadata.gz: 4e76f040dc9a72982978b86c4085e90a4efeab6f
4
- data.tar.gz: 4f3531dc67714ce9f1aae2858b2e12c4baf80f2e
3
+ metadata.gz: 71242ca35cdc2cccbfbae1008db364d84f58a1f1
4
+ data.tar.gz: 6114262aa4025c8d10b982d3a7261b36667318bb
5
5
  SHA512:
6
- metadata.gz: 02c75664a4f650debe93f2a6a61d51ce5c8341c16388824f500d0d5afe75b7ab044a6606a2c3fab25649ea424f9da683da05e8ab71dd69893f54a9dc7cea5345
7
- data.tar.gz: 7528d4c9f3cda76979b3118dee4069fdb86792e566e91bfd475703d2f107e5555ed1a850a0ff0e4b79b874f37b74261f2250bc28e148324555d22b31bdf4dbfd
6
+ metadata.gz: 861094f58471094e392603b3978e9c95d8f6ca0ca1da86ff064831d0bd42c28c4ea8fac5c779a01b030286bbab6bde0ca378b066bf8635706cd7f2e9a00583d1
7
+ data.tar.gz: 0f6a5cd8b3f6a5fbc436e4594d96cc25286a9631a7f93941878f87df7ccb8dc313e2ce3fa21535c1b442d5fa2849526a22c003afee4d59315b10992690d43b7e
data/CHANGES.md CHANGED
@@ -1,3 +1,14 @@
1
+ 3.0.0
2
+ ---
3
+ * Use default arguments for NullStatus initialization [briansharon#111]
4
+ * Fix at and in chainable methods [wpolicarpo#109]
5
+ * Rely on all of RSpec in development [packrat386#101]
6
+ * Pass exception to within_sidekiq_retries_exhausted_block [packrat386#100]
7
+ * Add support for testing scheduled jobs [wpolicarpo#81]
8
+ * only depend on rspec-core [urkle#96]
9
+ * Add support for Sidekiq Enterprise [Geesu#82]
10
+ * Fix clash with rspec-rails [pavel-jurasek-bcgdv-com#95]
11
+
1
12
  2.2.0
2
13
  ---
3
14
  * Fix typo in README file [bradhaydon#87]
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ **Welcome @wpolicarpo and @packrat386 as new maintainers for `rspec-sidekiq`!**
2
+
1
3
  # RSpec for Sidekiq
2
4
 
3
5
  [![RubyGems][gem_version_badge]][ruby_gems]
@@ -124,6 +126,7 @@ sidekiq_options unique: true
124
126
  expect(AwesomeJob).to be_unique
125
127
  it { is_expected.to be_unique }
126
128
  ```
129
+
127
130
  ### be_expired_in
128
131
  *Describes when a job should expire*
129
132
  ```ruby
@@ -141,6 +144,19 @@ AwesomeJob.perform_async 'Awesome', true
141
144
  expect(AwesomeJob).to have_enqueued_job('Awesome', true)
142
145
  ```
143
146
 
147
+ #### Testing scheduled jobs
148
+ *Use chainable matchers `#at` and `#in`*
149
+ ```ruby
150
+ Awesomejob.perform_at 5.minutes.from_now, 'Awesome', true
151
+ # test with...
152
+ expect(AwesomeJob).to have_enqueued_job('Awesome', true).at(5.minutes.from_now)
153
+ ```
154
+ ```ruby
155
+ Awesomejob.perform_in 5.minutes, 'Awesome', true
156
+ # test with...
157
+ expect(AwesomeJob).to have_enqueued_job('Awesome', true).in(5.minutes)
158
+ ```
159
+
144
160
  ## Example matcher usage
145
161
  ```ruby
146
162
  require 'spec_helper'
@@ -180,6 +196,11 @@ FooClass.within_sidekiq_retries_exhausted_block {
180
196
  ## Testing
181
197
  ```bundle exec rspec spec```
182
198
 
199
+ ## Maintainers
200
+ * @wpolicarpo
201
+ * @packrat386
202
+ * @philostler
203
+
183
204
  ## Contribute
184
205
  Please do! If there's a feature missing that you'd love to see then get in on the action!
185
206
 
@@ -33,7 +33,7 @@ if defined? Sidekiq::Batch
33
33
  class NullStatus < NullObject
34
34
  attr_reader :bid
35
35
 
36
- def initialize(bid, callbacks)
36
+ def initialize(bid = SecureRandom.hex(8), callbacks = [])
37
37
  @bid = bid
38
38
  @callbacks = callbacks
39
39
  end
@@ -59,6 +59,7 @@ if defined? Sidekiq::Batch
59
59
  end
60
60
  end
61
61
 
62
+ # :nocov:
62
63
  RSpec.configure do |config|
63
64
  config.before(:each) do |example|
64
65
  next if example.metadata[:stub_batches] == false
@@ -76,4 +77,5 @@ if defined? Sidekiq::Batch
76
77
  def mocked_with_mocha?
77
78
  Sidekiq::Batch.respond_to? :stubs
78
79
  end
80
+ # :nocov:
79
81
  end
@@ -1,12 +1,12 @@
1
1
  module Sidekiq
2
2
  module Worker
3
3
  module ClassMethods
4
- def within_sidekiq_retries_exhausted_block(user_msg = {}, &block)
4
+ def within_sidekiq_retries_exhausted_block(user_msg = {}, exception = default_retries_exhausted_exception, &block)
5
5
  block.call
6
- sidekiq_retries_exhausted_block.call default_retries_exhausted_args.merge(user_msg)
6
+ sidekiq_retries_exhausted_block.call(default_retries_exhausted_message.merge(user_msg), exception)
7
7
  end
8
8
 
9
- def default_retries_exhausted_args
9
+ def default_retries_exhausted_message
10
10
  {
11
11
  'queue' => get_sidekiq_options[:worker],
12
12
  'class' => name,
@@ -14,6 +14,10 @@ module Sidekiq
14
14
  'error_message' => 'An error occured'
15
15
  }
16
16
  end
17
+
18
+ def default_retries_exhausted_exception
19
+ StandardError.new('An error occured')
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -6,22 +6,80 @@ module RSpec
6
6
  end
7
7
 
8
8
  class BeUnique
9
- def description
10
- 'be unique in the queue'
9
+ def self.new
10
+ if defined?(::Sidekiq::Enterprise)
11
+ SidekiqEnterprise.new
12
+ elsif defined?(::SidekiqUniqueJobs)
13
+ SidekiqUniqueJobs.new
14
+ else
15
+ fail "No support found for Sidekiq unique jobs"
16
+ end
11
17
  end
12
18
 
13
- def failure_message
14
- "expected #{@klass} to be unique in the queue"
19
+ class Base
20
+ def description
21
+ 'be unique in the queue'
22
+ end
23
+
24
+ def failure_message
25
+ if !interval_matches? && @expected_interval
26
+ "expected #{@klass} to be unique for #{@expected_interval} seconds, "\
27
+ "but its interval was #{actual_interval} seconds"
28
+ else
29
+ "expected #{@klass} to be unique in the queue"
30
+ end
31
+ end
32
+
33
+ def matches?(job)
34
+ @klass = job.is_a?(Class) ? job : job.class
35
+ @actual = @klass.get_sidekiq_options[unique_key]
36
+ !!(value_matches? && interval_matches?)
37
+ end
38
+
39
+ def for(interval)
40
+ @expected_interval = interval
41
+ self
42
+ end
43
+
44
+ def interval_specified?
45
+ @expected_interval
46
+ end
47
+
48
+ def interval_matches?
49
+ !interval_specified? || actual_interval == @expected_interval
50
+ end
51
+
52
+ def failure_message_when_negated
53
+ "expected #{@klass} to not be unique in the queue"
54
+ end
15
55
  end
16
56
 
17
- def matches?(job)
18
- @klass = job.is_a?(Class) ? job : job.class
19
- @actual = @klass.get_sidekiq_options['unique']
20
- [true, :all].include?(@actual)
57
+ class SidekiqUniqueJobs < Base
58
+ def actual_interval
59
+ @klass.get_sidekiq_options['unique_job_expiration']
60
+ end
61
+
62
+ def value_matches?
63
+ [true, :all].include?(@actual)
64
+ end
65
+
66
+ def unique_key
67
+ 'unique'
68
+ end
21
69
  end
22
70
 
23
- def failure_message_when_negated
24
- "expected #{@klass} to not be unique in the queue"
71
+ class SidekiqEnterprise < Base
72
+ def actual_interval
73
+ @actual
74
+ end
75
+
76
+ def value_matches?
77
+ @actual && @actual > 0
78
+ end
79
+
80
+ def unique_key
81
+ 'unique_for'
82
+ end
25
83
  end
26
84
  end
27
85
  end
@@ -5,11 +5,110 @@ module RSpec
5
5
  HaveEnqueuedJob.new expected_arguments
6
6
  end
7
7
 
8
+ if Gem::Dependency.new('rspec-rails', '>= 3.4.0').matching_specs.max_by(&:version)
9
+ warn "[DEPRECATION] `have_enqueued_job` is deprecated. Please use `have_enqueued_sidekiq_job` instead."
10
+ alias have_enqueued_sidekiq_job have_enqueued_job
11
+ end
12
+
13
+ class JobOptionParser
14
+ attr_reader :job
15
+
16
+ def initialize(job)
17
+ @job = job
18
+ end
19
+
20
+ def matches?(option, value)
21
+ raise ArgumentError, "Option `#{option}` is not defined." unless %w(in at).include?(option.to_s)
22
+ send("#{option}_evaluator", value)
23
+ end
24
+
25
+ private
26
+
27
+ def at_evaluator(value)
28
+ return false if job['at'].blank?
29
+ value.to_time.to_s == Time.at(job['at']).to_s
30
+ end
31
+
32
+ def in_evaluator(value)
33
+ return false if job['at'].blank?
34
+ (Time.now + value).to_s == Time.at(job['at']).to_s
35
+ end
36
+ end
37
+
38
+ class JobMatcher
39
+ attr_reader :jobs
40
+
41
+ def initialize(klass)
42
+ @jobs = unwrap_jobs(klass.jobs)
43
+ end
44
+
45
+ def present?(arguments, options)
46
+ find_job(arguments, options).present?
47
+ end
48
+
49
+ private
50
+
51
+ def matches?(job, arguments, options)
52
+ arguments_matches?(job, arguments) &&
53
+ options_matches?(job, options)
54
+ end
55
+
56
+ def arguments_matches?(job, arguments)
57
+ arguments_got = job_arguments(job)
58
+ contain_exactly?(arguments, arguments_got)
59
+ end
60
+
61
+ def options_matches?(job, options)
62
+ options.all? do |option, value|
63
+ parser = JobOptionParser.new(job)
64
+ parser.matches?(option, value)
65
+ end
66
+ end
67
+
68
+ def find_job(arguments, options)
69
+ jobs.find { |job| matches?(job, arguments, options) }
70
+ end
71
+
72
+ def job_arguments(job)
73
+ args = job['args']
74
+ return args[0]['arguments'] if args.is_a?(Array) && args[0].is_a?(Hash) && args[0].has_key?('arguments')
75
+ args
76
+ end
77
+
78
+ def unwrap_jobs(jobs)
79
+ return jobs if jobs.is_a?(Array)
80
+ jobs.values.flatten
81
+ end
82
+
83
+ def contain_exactly?(expected, got)
84
+ exactly = RSpec::Matchers::BuiltIn::ContainExactly.new(expected)
85
+ exactly.matches?(got)
86
+ end
87
+ end
88
+
8
89
  class HaveEnqueuedJob
9
- attr_reader :klass, :expected_arguments, :actual
90
+ attr_reader :klass, :expected_arguments, :actual_arguments, :expected_options, :actual_options
10
91
 
11
92
  def initialize(expected_arguments)
12
93
  @expected_arguments = normalize_arguments(expected_arguments)
94
+ @expected_options = {}
95
+ end
96
+
97
+ def matches?(klass)
98
+ @klass = klass
99
+ @actual_arguments = unwrapped_job_arguments(klass.jobs)
100
+ @actual_options = unwrapped_job_options(klass.jobs)
101
+ JobMatcher.new(klass).present?(expected_arguments, expected_options)
102
+ end
103
+
104
+ def at(timestamp)
105
+ @expected_options['at'] = timestamp
106
+ self
107
+ end
108
+
109
+ def in(interval)
110
+ @expected_options['in'] = interval
111
+ self
13
112
  end
14
113
 
15
114
  def description
@@ -17,30 +116,39 @@ module RSpec
17
116
  end
18
117
 
19
118
  def failure_message
20
- "expected to have an enqueued #{klass} job with arguments #{expected_arguments}\n\n" \
21
- "found: #{actual}"
22
- end
23
-
24
- def matches?(klass)
25
- @klass = klass
26
- @actual = unwrapped_job_arguments(klass.jobs)
27
- @actual.any? { |arguments| contain_exactly?(arguments) }
119
+ message = ["expected to have an enqueued #{klass} job"]
120
+ message << " arguments: #{expected_arguments}" if expected_arguments
121
+ message << " options: #{expected_options}" if expected_options.any?
122
+ message << "found"
123
+ message << " arguments: #{actual_arguments}" if expected_arguments
124
+ message << " options: #{actual_options}" if expected_options.any?
125
+ message.join("\n")
28
126
  end
29
127
 
30
128
  def failure_message_when_negated
31
- "expected to not have an enqueued #{klass} job with arguments #{expected_arguments}"
129
+ message = ["expected not to have an enqueued #{klass} job"]
130
+ message << " arguments: #{expected_arguments}" if expected_arguments.any?
131
+ message << " options: #{expected_options}" if expected_options.any?
132
+ message.join("\n")
32
133
  end
33
134
 
34
135
  private
35
136
 
137
+ def unwrapped_job_options(jobs)
138
+ jobs = jobs.values if jobs.is_a?(Hash)
139
+ jobs.flatten.map do |job|
140
+ job.slice('at')
141
+ end
142
+ end
143
+
36
144
  def unwrapped_job_arguments(jobs)
37
145
  if jobs.is_a? Hash
38
146
  jobs.values.flatten.map do |job|
39
- map_arguments(job).flatten
147
+ map_arguments(job)
40
148
  end
41
149
  else
42
150
  map_arguments(jobs)
43
- end
151
+ end.map { |job| job.flatten }
44
152
  end
45
153
 
46
154
  def map_arguments(job)
@@ -56,11 +164,6 @@ module RSpec
56
164
  hash['arguments'] || hash['args'] if hash.is_a? Hash
57
165
  end
58
166
 
59
- def contain_exactly?(arguments)
60
- exactly = RSpec::Matchers::BuiltIn::ContainExactly.new(expected_arguments)
61
- exactly.matches?(arguments)
62
- end
63
-
64
167
  def normalize_arguments(args)
65
168
  if args.is_a?(Array)
66
169
  args.map{ |x| normalize_arguments(x) }
@@ -68,6 +171,8 @@ module RSpec
68
171
  args.each_with_object({}) do |(key, value), hash|
69
172
  hash[key.to_s] = normalize_arguments(value)
70
173
  end
174
+ elsif args.is_a?(Symbol)
175
+ args.to_s
71
176
  else
72
177
  args
73
178
  end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Sidekiq
3
- VERSION = '2.2.0'
3
+ VERSION = '3.0.0'
4
4
  end
5
5
  end
@@ -11,9 +11,10 @@ Gem::Specification.new do |s|
11
11
  s.description = 'Simple testing of Sidekiq jobs via a collection of matchers and helpers'
12
12
  s.license = 'MIT'
13
13
 
14
- s.add_dependency 'rspec', '~> 3.0', '>= 3.0.0'
14
+ s.add_dependency 'rspec-core', '~> 3.0', '>= 3.0.0'
15
15
  s.add_dependency 'sidekiq', '>= 2.4.0'
16
16
 
17
+ s.add_development_dependency 'rspec', '~> 3.0'
17
18
  s.add_development_dependency 'coveralls', '~> 0.8', '>= 0.8.0'
18
19
  s.add_development_dependency 'fuubar', '~> 2.0', '>= 2.0.0'
19
20
  s.add_development_dependency 'activejob', '~> 4.2', '>= 4.0.0'
@@ -10,31 +10,68 @@ RSpec.describe 'Batch' do
10
10
 
11
11
  load File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/rspec/sidekiq/batch.rb'))
12
12
 
13
+ describe 'NullObject' do
14
+ describe '#method_missing' do
15
+ it 'returns itself' do
16
+ batch = Sidekiq::Batch.new
17
+ expect(batch.non_existent_method).to eq(batch)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe 'NullBatch' do
23
+ end
24
+
13
25
  describe 'NullStatus' do
26
+ let(:batch) { Sidekiq::Batch.new }
27
+
28
+ subject { batch.status }
29
+
14
30
  describe '#total' do
15
31
  it 'returns 0 when no jobs' do
16
- null_status = Sidekiq::Batch.new.status
17
- expect(null_status.total).to eq(0)
32
+ expect(subject.total).to eq(0)
18
33
  end
19
34
 
20
35
  it 'returns 1 when 1 job' do
21
- batch = Sidekiq::Batch.new
22
-
23
36
  batch.jobs do
24
37
  TestWorker.perform_async('5')
25
38
  end
26
39
 
27
- null_status = batch.status
40
+ expect(subject.total).to eq(1)
41
+ end
42
+ end
28
43
 
29
- expect(null_status.total).to eq(1)
44
+ describe '#failures' do
45
+ it 'returns 0' do
46
+ expect(subject.failures).to eq(0)
30
47
  end
31
48
  end
32
49
 
33
50
  describe '#bid' do
34
51
  it 'returns a bid' do
35
- null_status = Sidekiq::Batch.new
36
- expect(null_status.bid).to_not be_nil
52
+ expect(subject.bid).to_not be_nil
53
+ end
54
+ end
55
+
56
+ describe '#join' do
57
+ class MyCallback
58
+ def on_event(status, options); end
59
+ end
60
+
61
+ before(:each) do
62
+ batch.on(:event, MyCallback, my_arg: 42)
63
+ end
64
+
65
+ it 'executes callbacks' do
66
+ expect_any_instance_of(MyCallback).to receive(:on_event).with(subject, { my_arg: 42 })
67
+ subject.join
68
+ end
69
+ end
70
+
71
+ describe '#initialize' do
72
+ it 'uses default argument values when none are provided' do
73
+ expect { Sidekiq::Batch::Status.new }.to_not raise_error
37
74
  end
38
75
  end
39
76
  end
40
- end
77
+ end
@@ -2,9 +2,10 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe 'Retries Exhausted block' do
4
4
  class FooClass < TestWorkerAlternative
5
- sidekiq_retries_exhausted do |msg|
5
+ sidekiq_retries_exhausted do |msg, exception|
6
6
  bar('hello')
7
7
  foo(msg)
8
+ baz(exception)
8
9
  end
9
10
 
10
11
  def self.bar(input)
@@ -12,17 +13,28 @@ RSpec.describe 'Retries Exhausted block' do
12
13
 
13
14
  def self.foo(msg)
14
15
  end
16
+
17
+ def self.baz(exception)
18
+ end
15
19
  end
16
20
 
17
21
  it 'executes whatever is within the block' do
18
22
  FooClass.within_sidekiq_retries_exhausted_block { expect(FooClass).to receive(:bar).with('hello') }
19
23
  end
20
24
 
21
- it 'passes arguments to the block' do
25
+ it 'passes message and exception to the block' do
22
26
  args = { 'args' => ['a', 'b']}
23
- FooClass.within_sidekiq_retries_exhausted_block(args) do
24
- expect(FooClass).to receive(:foo).with(FooClass.default_retries_exhausted_args.merge(args))
27
+ exception = StandardError.new('something went wrong')
28
+ FooClass.within_sidekiq_retries_exhausted_block(args, exception) do
29
+ expect(FooClass).to receive(:foo).with(FooClass.default_retries_exhausted_message.merge(args))
30
+ expect(FooClass).to receive(:baz).with(exception)
25
31
  end
26
32
  end
27
33
 
34
+ it 'sets a default value for the message and exception' do
35
+ FooClass.within_sidekiq_retries_exhausted_block do
36
+ expect(FooClass).to receive(:foo).with(FooClass.default_retries_exhausted_message)
37
+ expect(FooClass).to receive(:baz).with(FooClass.default_retries_exhausted_exception)
38
+ end
39
+ end
28
40
  end
@@ -2,6 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe RSpec::Sidekiq::Matchers::BeUnique do
4
4
  shared_context 'a unique worker' do
5
+ before do
6
+ stub_const(module_constant, true)
7
+ end
5
8
  before(:each) { subject.matches? @worker }
6
9
 
7
10
  describe 'expected usage' do
@@ -14,7 +17,6 @@ RSpec.describe RSpec::Sidekiq::Matchers::BeUnique do
14
17
  expect(subject.failure_message).to eq "expected #{@worker} to be unique in the queue"
15
18
  end
16
19
  end
17
-
18
20
  end
19
21
 
20
22
  describe '#matches?' do
@@ -36,27 +38,78 @@ RSpec.describe RSpec::Sidekiq::Matchers::BeUnique do
36
38
  end
37
39
  end
38
40
  end
41
+
42
+ describe '#description' do
43
+ it 'returns description' do
44
+ expect(subject.description).to eq 'be unique in the queue'
45
+ end
46
+ end
39
47
  end
40
48
 
41
- context 'a scheduled worker' do
42
- before { @worker = create_worker unique: :all }
49
+ context 'a sidekiq-enterprise scheduled worker' do
50
+ let(:interval) { 3.hours }
51
+ let(:module_constant) { "Sidekiq::Enterprise" }
52
+ before { @worker = create_worker unique_for: interval }
43
53
  include_context 'a unique worker'
44
54
  end
45
55
 
46
- context 'a regular worker' do
47
- before { @worker = create_worker unique: true }
56
+ context 'a sidekiq-unique-jobs scheduled worker' do
57
+ let(:module_constant) { "SidekiqUniqueJobs" }
58
+ before { @worker = create_worker unique: :all }
59
+ include_context 'a unique worker'
60
+ end
61
+
62
+ context 'a sidekiq-unique-jobs regular worker' do
63
+ let(:module_constant) { "SidekiqUniqueJobs" }
64
+ before { @worker = create_worker unique: true }
48
65
  include_context 'a unique worker'
49
66
  end
50
67
 
51
68
  describe '#be_unique' do
69
+ before do
70
+ stub_const("SidekiqUniqueJobs", true)
71
+ end
72
+
52
73
  it 'returns instance' do
53
- expect(be_unique).to be_a RSpec::Sidekiq::Matchers::BeUnique
74
+ expect(be_unique).to be_kind_of RSpec::Sidekiq::Matchers::BeUnique::Base
54
75
  end
55
76
  end
56
77
 
57
78
  describe '#failure_message_when_negated' do
79
+ before do
80
+ stub_const("SidekiqUniqueJobs", true)
81
+ end
82
+
58
83
  it 'returns message' do
59
84
  expect(subject.failure_message_when_negated).to eq "expected #{@worker} to not be unique in the queue"
60
85
  end
61
86
  end
87
+
88
+ describe '#unique_key' do
89
+ context "with Sidekiq Enterprise" do
90
+ before do
91
+ stub_const("Sidekiq::Enterprise", true)
92
+ end
93
+
94
+ it "returns the correct key" do
95
+ expect(subject.unique_key).to eq('unique_for')
96
+ end
97
+ end
98
+
99
+ context "with sidekiq-unique-jobs" do
100
+ before do
101
+ stub_const("SidekiqUniqueJobs", true)
102
+ end
103
+
104
+ it "returns the correct key" do
105
+ expect(subject.unique_key).to eq('unique')
106
+ end
107
+ end
108
+
109
+ context "without a uniquing solution" do
110
+ it "raises an exception" do
111
+ expect{subject.unique_key}.to raise_error
112
+ end
113
+ end
114
+ end
62
115
  end
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RSpec::Sidekiq::Matchers::HaveEnqueuedJob do
4
+ let(:tomorrow) { DateTime.now + 1 }
5
+ let(:interval) { 3.minutes }
4
6
  let(:argument_subject) { RSpec::Sidekiq::Matchers::HaveEnqueuedJob.new worker_args }
5
7
  let(:matcher_subject) { RSpec::Sidekiq::Matchers::HaveEnqueuedJob.new [be_a(String), be_a(Fixnum), true, be_a(Hash)] }
6
8
  let(:worker) { create_worker }
7
- let(:worker_args) { ['string', 1, true, {key: 'value', nested: [{hash: true}]}] }
9
+ let(:worker_args) { ['string', 1, true, { key: 'value', bar: :foo, nested: [{hash: true}] }] }
8
10
  let(:active_job) { create_active_job :mailers }
9
11
  let(:resource) { TestResource.new }
10
12
 
@@ -14,41 +16,70 @@ RSpec.describe RSpec::Sidekiq::Matchers::HaveEnqueuedJob do
14
16
  active_job.perform_later(resource)
15
17
  TestActionMailer.testmail.deliver_later
16
18
  TestActionMailer.testmail(resource).deliver_later
17
- argument_subject.matches? worker
18
19
  end
19
20
 
20
21
  describe 'expected usage' do
21
- it 'matches' do
22
- expect(worker).to have_enqueued_job *worker_args
23
- end
22
+ context 'Sidekiq' do
23
+ it 'matches' do
24
+ expect(worker).to have_enqueued_job *worker_args
25
+ end
24
26
 
25
- it 'matches on the global Worker queue' do
26
- expect(Sidekiq::Worker).to have_enqueued_job *worker_args
27
- end
27
+ it 'matches on the global Worker queue' do
28
+ expect(Sidekiq::Worker).to have_enqueued_job *worker_args
29
+ end
28
30
 
29
- it 'matches on an enqueued ActiveJob' do
30
- expect(Sidekiq::Worker).to have_enqueued_job 'someResource'
31
- end
31
+ context 'perform_in' do
32
+ let(:worker_args_in) { worker_args + ['in'] }
33
+
34
+ before(:each) do
35
+ worker.perform_in 3.minutes, *worker_args_in
36
+ end
37
+
38
+ it 'matches on an scheduled job with #perform_in' do
39
+ expect(worker).to have_enqueued_job(*worker_args_in).in(interval)
40
+ end
41
+ end
42
+
43
+ context 'perform_at' do
44
+ let(:worker_args_at) { worker_args + ['at'] }
32
45
 
33
- it 'matches on an enqueued ActiveJob by global_id' do
34
- expect(Sidekiq::Worker).to have_enqueued_job("_aj_globalid" => resource.to_global_id.uri.to_s)
46
+ before(:each) do
47
+ worker.perform_at tomorrow, *worker_args_at
48
+ end
49
+
50
+ it 'matches on an scheduled job with #perform_at' do
51
+ expect(worker).to have_enqueued_job(*worker_args_at).at(tomorrow)
52
+ end
53
+ end
35
54
  end
36
55
 
37
- it 'matches on ActionMailer Job' do
38
- expect(Sidekiq::Worker).to have_enqueued_job(
39
- "TestActionMailer",
40
- "testmail",
41
- "deliver_now"
42
- )
56
+ context 'ActiveJob' do
57
+ it 'matches on an enqueued ActiveJob' do
58
+ expect(Sidekiq::Worker).to have_enqueued_job 'someResource'
59
+ end
60
+
61
+ it 'matches on an enqueued ActiveJob by global_id' do
62
+ expect(Sidekiq::Worker).to have_enqueued_job('_aj_globalid' => resource.to_global_id.uri.to_s)
63
+ end
43
64
  end
44
65
 
45
- it 'matches on ActionMailer with a resource Job' do
46
- expect(Sidekiq::Worker).to have_enqueued_job(
47
- "TestActionMailer",
48
- "testmail",
49
- "deliver_now",
50
- { "_aj_globalid" => resource.to_global_id.uri.to_s }
51
- )
66
+ context 'ActionMailer' do
67
+ it 'matches on ActionMailer Job' do
68
+ expect(Sidekiq::Worker).to have_enqueued_job(
69
+ 'TestActionMailer',
70
+ 'testmail',
71
+ 'deliver_now'
72
+ )
73
+ end
74
+
75
+ it 'matches on ActionMailer with a resource Job' do
76
+ expect(Sidekiq::Worker).to have_enqueued_job(
77
+ 'TestActionMailer',
78
+ 'testmail',
79
+ 'deliver_now',
80
+ { '_aj_globalid' => resource.to_global_id.uri.to_s }
81
+ )
82
+ end
52
83
  end
53
84
  end
54
85
 
@@ -60,13 +91,30 @@ RSpec.describe RSpec::Sidekiq::Matchers::HaveEnqueuedJob do
60
91
 
61
92
  describe '#description' do
62
93
  it 'returns description' do
63
- expect(argument_subject.description).to eq "have an enqueued #{worker} job with arguments [\"string\", 1, true, {\"key\"=>\"value\", \"nested\"=>[{\"hash\"=>true}]}]"
94
+ argument_subject.matches? worker
95
+ expect(argument_subject.description).to eq %{have an enqueued #{worker} job with arguments [\"string\", 1, true, {\"key\"=>\"value\", \"bar\"=>\"foo\", \"nested\"=>[{\"hash\"=>true}]}]}
64
96
  end
65
97
  end
66
98
 
67
99
  describe '#failure_message' do
68
100
  it 'returns message' do
69
- expect(argument_subject.failure_message).to eq "expected to have an enqueued #{worker} job with arguments [\"string\", 1, true, {\"key\"=>\"value\", \"nested\"=>[{\"hash\"=>true}]}]\n\nfound: [[\"string\", 1, true, {\"key\"=>\"value\", \"nested\"=>[{\"hash\"=>true}]}]]"
101
+ argument_subject.matches? worker
102
+ expect(argument_subject.failure_message).to eq <<-eos.gsub(/^ {6}/, '').strip
103
+ expected to have an enqueued #{worker} job
104
+ arguments: [\"string\", 1, true, {\"key\"=>\"value\", \"bar\"=>\"foo\", \"nested\"=>[{\"hash\"=>true}]}]
105
+ found
106
+ arguments: [[\"string\", 1, true, {\"key\"=>\"value\", \"bar\"=>\"foo\", \"nested\"=>[{\"hash\"=>true}]}]]
107
+ eos
108
+ end
109
+ end
110
+
111
+ describe '#failure_message_when_negated' do
112
+ it 'returns message' do
113
+ argument_subject.matches? worker
114
+ expect(argument_subject.failure_message_when_negated).to eq <<-eos.gsub(/^ {6}/, '').strip
115
+ expected not to have an enqueued #{worker} job
116
+ arguments: [\"string\", 1, true, {\"key\"=>\"value\", \"bar\"=>\"foo\", \"nested\"=>[{\"hash\"=>true}]}]
117
+ eos
70
118
  end
71
119
  end
72
120
 
@@ -74,15 +122,55 @@ RSpec.describe RSpec::Sidekiq::Matchers::HaveEnqueuedJob do
74
122
  context 'when condition matches' do
75
123
  context 'when expected are arguments' do
76
124
  it 'returns true' do
125
+ worker.perform_async *worker_args
77
126
  expect(argument_subject.matches? worker).to be true
78
127
  end
79
128
  end
80
129
 
81
130
  context 'when expected are matchers' do
82
131
  it 'returns true' do
132
+ worker.perform_async *worker_args
83
133
  expect(matcher_subject.matches? worker).to be true
84
134
  end
85
135
  end
136
+
137
+ context 'when job is scheduled' do
138
+ context 'with #perform_at' do
139
+ before(:each) do
140
+ worker.perform_at(tomorrow, *worker_args)
141
+ end
142
+
143
+ context 'and timestamp matches' do
144
+ it 'returns true' do
145
+ expect(matcher_subject.at(tomorrow).matches? worker).to be true
146
+ end
147
+ end
148
+
149
+ context 'and timestamp does not match' do
150
+ it 'returns false' do
151
+ expect(matcher_subject.at(tomorrow + 1).matches? worker).to be false
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'with #perform_in' do
157
+ before(:each) do
158
+ worker.perform_in(interval, *worker_args)
159
+ end
160
+
161
+ context 'and interval matches' do
162
+ it 'returns true' do
163
+ expect(matcher_subject.in(interval).matches? worker).to be true
164
+ end
165
+ end
166
+
167
+ context 'and interval does not match' do
168
+ it 'returns false' do
169
+ expect(matcher_subject.in(interval + 1.minute).matches? worker).to be false
170
+ end
171
+ end
172
+ end
173
+ end
86
174
  end
87
175
 
88
176
  context 'when condition does not match' do
@@ -99,12 +187,28 @@ RSpec.describe RSpec::Sidekiq::Matchers::HaveEnqueuedJob do
99
187
  expect(matcher_subject.matches? worker).to be false
100
188
  end
101
189
  end
102
- end
103
- end
104
190
 
105
- describe '#failure_message_when_negated' do
106
- it 'returns message' do
107
- expect(argument_subject.failure_message_when_negated).to eq "expected to not have an enqueued #{worker} job with arguments [\"string\", 1, true, {\"key\"=>\"value\", \"nested\"=>[{\"hash\"=>true}]}]"
191
+ context 'when job is scheduled' do
192
+ context 'with #perform_at' do
193
+ before(:each) do
194
+ allow(matcher_subject).to receive(:options).and_return(at: tomorrow + 1)
195
+ end
196
+
197
+ it 'returns false' do
198
+ expect(matcher_subject.at(tomorrow).matches? worker).to be false
199
+ end
200
+ end
201
+
202
+ context 'with #perform_in' do
203
+ before(:each) do
204
+ allow(matcher_subject).to receive(:options).and_return(in: interval + 1)
205
+ end
206
+
207
+ it 'returns false' do
208
+ expect(matcher_subject.in(interval).matches? worker).to be false
209
+ end
210
+ end
211
+ end
108
212
  end
109
213
  end
110
214
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RSpec::Sidekiq::VERSION do
4
- it { is_expected.to eq('2.2.0') }
4
+ it { is_expected.to eq('3.0.0') }
5
5
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Ostler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-22 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: rspec-core
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: 2.4.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: coveralls
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -193,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
207
  version: '0'
194
208
  requirements: []
195
209
  rubyforge_project:
196
- rubygems_version: 2.4.8
210
+ rubygems_version: 2.5.2
197
211
  signing_key:
198
212
  specification_version: 4
199
213
  summary: RSpec for Sidekiq