Skip to content

Commit

Permalink
Merge branch 'release/v2.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil Ostler committed Aug 5, 2015
2 parents 19bb686 + 3fbe495 commit 1574ebc
Show file tree
Hide file tree
Showing 25 changed files with 463 additions and 23 deletions.
1 change: 0 additions & 1 deletion .simplecov
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# encoding: utf-8
SimpleCov.start do
add_filter '/spec/'

Expand Down
12 changes: 4 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
language: ruby
rvm:
- 2.0.0
- 2.1.0
- ruby-head
- 2.0
- 2.1
- 2.2
- jruby
- jruby-head
- rbx-2
- rbx-head
script: "bundle exec rspec spec"
matrix:
allow_failures:
- rvm: ruby-head
- rvm: jruby-head
- rvm: rbx-head
- rvm: rbx-2
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2.1.0
---
* ActiveJob support [tarzan#71]
* adding be expired in matcher [bernabas#72]
* Fixed testing failures with be_delayed matcher due to rename of `enqueued_at` to `created_at` in latest Sidekiq [philostler]
* Add support for NullBatch#on and NullStatus#failures to the null batch objects. [PacerPRO#64]
* Adding a save_backtrace matcher [webdestroya#61]
* Add flag to skip Batch stubs [paulfri#69]
* allow passing an instance method to be_delayed matcher [lastobelus#63]

2.0.0
---
* Get specs to green [petergoldstein#58]
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Phil Ostler
Copyright (c) 2014, 2015 Phil Ostler

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Object.delay_until(1.hour.from_now).is_nil? # delay until
expect(Object.method :is_nil?).to be_delayed.until 1.hour.from_now
Object.delay_until(1.hour.from_now).is_a? Object # delay until with argument
expect(Object.method :is_a?).to be_delayed(Object).until 1.hour.from_now

#Rails Mailer
MyMailer.delay.some_mail
expect(MyMailer.instance_method :some_mail).to be_delayed
```

### be_processed_in
Expand All @@ -95,6 +99,23 @@ expect(AwesomeJob).to be_retryable false # or
it { is_expected.to be_retryable false }
```

### save_backtrace
*Describes if a job should save the error backtrace when there is a failure in it's execution*
```ruby
sidekiq_options backtrace: 5
# test with...
expect(AwesomeJob).to save_backtrace # or
it { is_expected.to save_backtrace }
# ...or alternatively specifiy the number of lines that should be saved
expect(AwesomeJob).to save_backtrace 5 # or
it { is_expected.to save_backtrace 5 }
# ...or when it should not save the backtrace
expect(AwesomeJob).to_not save_backtrace # or
expect(AwesomeJob).to save_backtrace false # or
it { is_expected.to_not save_backtrace } # or
it { is_expected.to save_backtrace false }
```

### be_unique
*Describes when a job should be unique within it's queue*
```ruby
Expand All @@ -103,6 +124,14 @@ sidekiq_options unique: true
expect(AwesomeJob).to be_unique
it { is_expected.to be_unique }
```
### be_expired_in
*Describes when a job should expire*
```ruby
sidekiq_options expires_in: 1.hour
# test with...
it { is_expected.to be_expired_in 1.hour }
it { is_expected.to_not be_expired_in 2.hours }
```

### have_enqueued_job
*Describes that there should be an enqueued job with the specified arguments*
Expand All @@ -120,6 +149,7 @@ describe AwesomeJob do
it { is_expected.to be_processed_in :my_queue }
it { is_expected.to be_retryable 5 }
it { is_expected.to be_unique }
it { is_expected.to be_expired_in 1.hour }

it 'enqueues another awesome job' do
subject.perform
Expand Down
24 changes: 21 additions & 3 deletions lib/rspec/sidekiq/batch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ class NullBatch < NullObject

def initialize(bid = nil)
@bid = bid || SecureRandom.hex(8)
@callbacks = []
end

def status
NullStatus.new(@bid)
NullStatus.new(@bid, @callbacks)
end

def on(*args)
@callbacks << args
end

def jobs(*)
Expand All @@ -28,12 +33,23 @@ def jobs(*)
class NullStatus < NullObject
attr_reader :bid

def initialize(bid)
def initialize(bid, callbacks)
@bid = bid
@callbacks = callbacks
end

def failures
0
end

def join
::Sidekiq::Worker.drain_all

@callbacks.each do |event, callback_class, options|
if event != :success || failures == 0
callback_class.new.send("on_#{event}", self, options)
end
end
end

def total
Expand All @@ -44,7 +60,9 @@ def total
end

RSpec.configure do |config|
config.before(:each) do
config.before(:each) do |example|
next if example.metadata[:stub_batches] == false

if mocked_with_mocha?
Sidekiq::Batch.stubs(:new) { RSpec::Sidekiq::NullBatch.new }
else
Expand Down
2 changes: 2 additions & 0 deletions lib/rspec/sidekiq/matchers.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require 'rspec/core'
require 'rspec/sidekiq/matchers/be_delayed'
require 'rspec/sidekiq/matchers/be_expired_in'
require 'rspec/sidekiq/matchers/be_processed_in'
require 'rspec/sidekiq/matchers/be_retryable'
require 'rspec/sidekiq/matchers/be_unique'
require 'rspec/sidekiq/matchers/have_enqueued_job'
require 'rspec/sidekiq/matchers/save_backtrace'

RSpec.configure do |config|
config.include RSpec::Sidekiq::Matchers
Expand Down
10 changes: 6 additions & 4 deletions lib/rspec/sidekiq/matchers/be_delayed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def description
end

def failure_message
"expected #{@expected_method.receiver}.#{@expected_method.name} to " + description
"expected #{@expected_method_receiver}.#{@expected_method.name} to " + description
end

def for(interval)
Expand All @@ -29,10 +29,12 @@ def for(interval)

def matches?(expected_method)
@expected_method = expected_method
@expected_method_receiver = @expected_method.is_a?(UnboundMethod) ? @expected_method.owner : @expected_method.receiver

find_job @expected_method, @expected_arguments do |job|
if @expected_interval
return job['at'].to_i == job['enqueued_at'].to_i + @expected_interval
created_enqueued_at = job['enqueued_at'] || job['created_at']
return job['at'].to_i == created_enqueued_at.to_i + @expected_interval
elsif @expected_time
return job['at'].to_i == @expected_time.to_i
else
Expand All @@ -44,7 +46,7 @@ def matches?(expected_method)
end

def failure_message_when_negated
"expected #{@expected_method.receiver}.#{@expected_method.name} to not " + description
"expected #{@expected_method_receiver}.#{@expected_method.name} to not " + description
end

def until(time)
Expand All @@ -57,7 +59,7 @@ def until(time)
def find_job(method, arguments, &block)
job = (::Sidekiq::Extensions::DelayedClass.jobs + ::Sidekiq::Extensions::DelayedModel.jobs + ::Sidekiq::Extensions::DelayedMailer.jobs).find do |job|
yaml = YAML.load(job['args'].first)
@expected_method.receiver == yaml[0] && @expected_method.name == yaml[1] && (@expected_arguments <=> yaml[2]) == 0
@expected_method_receiver == yaml[0] && @expected_method.name == yaml[1] && (@expected_arguments <=> yaml[2]) == 0
end

yield job if block && job
Expand Down
33 changes: 33 additions & 0 deletions lib/rspec/sidekiq/matchers/be_expired_in.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module RSpec
module Sidekiq
module Matchers
def be_expired_in(expected_argument)
BeExpiredIn.new(expected_argument)
end

class BeExpiredIn
def initialize(expected_argument)
@expected_argument = expected_argument
end

def description
"to expire in #{@expected_argument}"
end

def failure_message
"expected to expire in #{@expected_argument} but expired in #{@actual}"
end

def failure_message_when_negated
"expected to not expire in #{@expected_argument}"
end

def matches?(job)
@klass = job.is_a?(Class) ? job : job.class
@actual = @klass.get_sidekiq_options['expires_in']
@actual.to_s == @expected_argument.to_s
end
end
end
end
end
6 changes: 5 additions & 1 deletion lib/rspec/sidekiq/matchers/be_processed_in.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ def failure_message

def matches?(job)
@klass = job.is_a?(Class) ? job : job.class
@actual = @klass.get_sidekiq_options['queue']
if @klass.methods.include?(:get_sidekiq_options)
@actual = @klass.get_sidekiq_options['queue']
else
@actual = job.try(:queue_name)
end
@actual.to_s == @expected_queue.to_s
end

Expand Down
25 changes: 24 additions & 1 deletion lib/rspec/sidekiq/matchers/have_enqueued_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def failure_message

def matches?(klass)
@klass = klass
@actual = klass.jobs.map { |job| job['args'] }
@actual = unwrapped_job_arguments(klass.jobs)
@actual.any? { |arguments| contain_exactly?(arguments) }
end

Expand All @@ -33,6 +33,29 @@ def failure_message_when_negated

private

def unwrapped_job_arguments(jobs)
if jobs.is_a? Hash
jobs.values.flatten.map do |job|
map_arguments(job).flatten
end
else
map_arguments(jobs)
end
end

def map_arguments(job)
args = job_arguments(job) || job
if args.respond_to?(:any?) && args.any? { |e| e.is_a? Hash }
args.map { |a| map_arguments(a) }
else
args
end
end

def job_arguments(hash)
hash['arguments'] || hash['args'] unless hash.is_a? Array
end

def contain_exactly?(arguments)
exactly = RSpec::Matchers::BuiltIn::ContainExactly.new(expected_arguments)
exactly.matches?(arguments)
Expand Down
39 changes: 39 additions & 0 deletions lib/rspec/sidekiq/matchers/save_backtrace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module RSpec
module Sidekiq
module Matchers
def save_backtrace(expected_backtrace=true)
SaveBacktrace.new expected_backtrace
end

class SaveBacktrace
def initialize(expected_backtrace=true)
@expected_backtrace = expected_backtrace
end

def description
if @expected_backtrace.is_a?(Fixnum)
"save #{@expected_backtrace} lines of error backtrace" # backtrace: 5
elsif @expected_backtrace
'save error backtrace' # backtrace: true
else
'not save error backtrace' # backtrace: false
end
end

def failure_message
"expected #{@klass} to #{description} but got #{@actual}"
end

def matches?(job)
@klass = job.is_a?(Class) ? job : job.class
@actual = @klass.get_sidekiq_options['backtrace']
@actual == @expected_backtrace
end

def failure_message_when_negated
"expected #{@klass} to not #{description}".gsub 'not not ', ''
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/rspec/sidekiq/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module RSpec
module Sidekiq
VERSION = '2.0.0'
VERSION = '2.1.0'
end
end
6 changes: 4 additions & 2 deletions rspec-sidekiq.gemspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# encoding: utf-8
require File.expand_path('../lib/rspec/sidekiq/version', __FILE__)

Gem::Specification.new do |s|
Expand All @@ -15,8 +14,11 @@ Gem::Specification.new do |s|
s.add_dependency 'rspec', '~> 3.0', '>= 3.0.0'
s.add_dependency 'sidekiq', '>= 2.4.0'

s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7.0'
s.add_development_dependency 'coveralls', '~> 0.8', '>= 0.8.0'
s.add_development_dependency 'fuubar', '~> 2.0', '>= 2.0.0'
s.add_development_dependency 'activejob', '~> 4.2', '>= 4.0.0'
s.add_development_dependency 'actionmailer', '~> 4.2', '>= 4.0.0'


s.files = Dir['.gitattributes'] +
Dir['.gitignore'] +
Expand Down
Loading

0 comments on commit 1574ebc

Please sign in to comment.