activejob_spec 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f672c901cf70f80191d1393ef34d10398b5308f
4
+ data.tar.gz: f9c9b95e2093fd255e72989e971c1c7cc5c3a374
5
+ SHA512:
6
+ metadata.gz: 3722c62dc3832e81034d0ecd893a0824dc7ba4ab05af54891f2d59c0f5d48a81c7225643cbd52135607ba27d1ba2c28307962c685abe85f8262c3931d15feb42
7
+ data.tar.gz: 2b8e4d554a1cb5acf1b6db08e9d270b92212c495b3f2f639db8abb796646b64a2d73264c0a28ca1673fd244cead2b956f456e1003f9f5045d481e49a52c35e73
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in activejob_spec.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Peter Negrei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,151 @@
1
+ # ActiveJobSpec
2
+
3
+ A test double of ActiveJob for RSpec.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'activejob_spec'
11
+ ```
12
+
13
+ or
14
+
15
+ ```ruby
16
+ group :development, :test do
17
+ gem 'activejob_spec'
18
+ end
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Given this scenario
24
+
25
+ Given a payment
26
+ When I process
27
+ Then the payment has process queued
28
+
29
+ And I write this spec using the `activejob_spec` matcher
30
+
31
+ ```ruby
32
+ describe '#process' do
33
+ before do
34
+ ActiveJobSpec.reset!
35
+ end
36
+
37
+ it 'adds payment.process to the Payment queue' do
38
+ payment.process
39
+ expect(Payment).to have_queued(payment.id)
40
+
41
+ # also possible with :once and :times methods
42
+ # expect(Payment).to have_queued(payment.id).once
43
+ end
44
+ end
45
+ ```
46
+
47
+ And I see that the `have_queued` assertion is asserting that the `Payment` queue has a job with arguments `payment.id` and `:process`
48
+
49
+ And I take note of the `before` block that is calling `reset!` for every spec.
50
+
51
+ You can check the size of the queue in your specs too.
52
+
53
+ ```ruby
54
+ describe '#process' do
55
+ before do
56
+ ActiveJobSpec.reset!
57
+ end
58
+
59
+ it 'adds an entry to the Payment queue' do
60
+ payment.process
61
+ expect(Payment).to have_queue_size_of(1)
62
+ end
63
+ end
64
+ ```
65
+
66
+ ## Scheduled Jobs
67
+
68
+ Given this scenario
69
+
70
+ Given a payment
71
+ When I schedule a process
72
+ Then the payment has process scheduled
73
+
74
+ And I write this spec using the `activejob_spec` matcher
75
+
76
+ ```ruby
77
+ describe '#process' do
78
+ before do
79
+ ActiveJobSpec.reset!
80
+ end
81
+
82
+ it 'adds payment.process to the Payment queue' do
83
+ payment.process
84
+
85
+ expect(Payment).to have_scheduled(payment.id)
86
+ end
87
+ end
88
+ ```
89
+
90
+ And I might use the `at` statement to specify the time:
91
+
92
+ ```ruby
93
+ describe "#process" do
94
+ before do
95
+ ResqueSpec.reset!
96
+ end
97
+
98
+ it 'adds payment.process to the Payment queue' do
99
+ payment.process
100
+
101
+ # Is it scheduled to be executed at 2010-02-14 06:00:00 ?
102
+ expect(Payment).to have_scheduled(payment.id).at(Time.mktime(2010,2,14,6,0,0))
103
+ end
104
+ end
105
+ ```
106
+
107
+ And I might use the `in` statement to specify time interval (in seconds):
108
+
109
+ ```ruby
110
+ describe '#process' do
111
+ before do
112
+ ResqueSpec.reset!
113
+ end
114
+
115
+ it 'adds payment.process to the Payment queue' do
116
+ payment.process
117
+
118
+ # Is it scheduled to be executed in 5 minutes?
119
+ expect(Payment).to have_scheduled(payment.id).in(5 * 60)
120
+ end
121
+ end
122
+ ```
123
+
124
+ You can also check the size of the schedule:
125
+
126
+ ```ruby
127
+ describe "#process" do
128
+ before do
129
+ ResqueSpec.reset!
130
+ end
131
+
132
+ it "adds payment.calculate to the Payment queue" do
133
+ payment.process
134
+
135
+ expect(Payment).to have_schedule_size_of(1)
136
+ end
137
+ end
138
+ ```
139
+
140
+ (And I take note of the `before` block that is calling `reset!` for every spec)
141
+
142
+ ## Contributing
143
+
144
+ * Fork the project.
145
+ * Make your feature addition or bug fix.
146
+ * Add tests for it.
147
+ * Send a pull request.
148
+
149
+ ## License
150
+
151
+ Copyright (c) 2015 Peter Negrei. See LICENSE for details.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'activejob_spec/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "activejob_spec"
8
+ spec.version = ActiveJobSpec::VERSION
9
+ spec.authors = ["Peter Negrei"]
10
+ spec.email = ["negrei.petru@gmail.com"]
11
+
12
+ spec.summary = %q{RSpec matcher for ActiveJob}
13
+ spec.description = %q{}
14
+ spec.homepage = "https://github.com/noku/activejob_spec"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency 'rails'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.10"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec"
27
+
28
+ spec.add_development_dependency 'actionpack'
29
+ spec.add_development_dependency 'activesupport'
30
+ spec.add_development_dependency 'pry'
31
+ end
@@ -0,0 +1,9 @@
1
+ require "activejob_spec/version"
2
+ require "activejob_spec/matchers"
3
+
4
+ module ActiveJobSpec
5
+ def self.reset!
6
+ ActiveJob::Base.queue_adapter.enqueued_jobs = []
7
+ ActiveJob::Base.queue_adapter.performed_jobs = []
8
+ end
9
+ end
@@ -0,0 +1,183 @@
1
+ require 'rspec/core'
2
+ require 'rspec/expectations'
3
+ require 'rspec/mocks'
4
+
5
+ module ArgsHelper
6
+ def match_job(job, klass)
7
+ job.fetch(:job) == klass
8
+ end
9
+
10
+ def match_args(expected_args, args)
11
+ arg_list_matcher = RSpec::Mocks::ArgumentListMatcher.new(expected_args)
12
+ arg_list_matcher.args_match?(args)
13
+ end
14
+ end
15
+
16
+ module ActiveJobHelper
17
+ def enqueued_jobs
18
+ ::ActiveJob::Base.queue_adapter.enqueued_jobs
19
+ end
20
+ end
21
+
22
+ module QueueHelper
23
+ include ArgsHelper
24
+ include ActiveJobHelper
25
+
26
+ def find_matching_jobs(actual, expected_args)
27
+ enqueued_jobs.select do |entry|
28
+ match_job(entry, actual) && match_args(expected_args, entry.fetch(:args))
29
+ end
30
+ end
31
+
32
+ def queue_size_for(actual)
33
+ enqueued_jobs.select { |job| match_job(job, actual) }.size
34
+ end
35
+
36
+ def check_size_for(matched_jobs, times)
37
+ if times
38
+ matched_jobs.size == times
39
+ else
40
+ matched_jobs.size > 0
41
+ end
42
+ end
43
+ end
44
+
45
+ module ScheduleQueueHelper
46
+ include QueueHelper
47
+
48
+ def check_for_scheduled(actual, expected_args)
49
+ scheduled_jobs.any? do |entry|
50
+ class_matches = match_job(entry, actual)
51
+ args_match = match_args(expected_args, entry.fetch(:args))
52
+
53
+ class_matches && args_match && time_matches(entry)
54
+ end
55
+ end
56
+
57
+ def time_matches(entry)
58
+ return compare_time(entry) if @time
59
+ return compare_interval(entry) if @interval
60
+
61
+ true
62
+ end
63
+
64
+ def compare_time(entry)
65
+ entry[:at].to_i == @time.to_i
66
+ end
67
+
68
+ def compare_interval(entry)
69
+ entry[:at].to_i == (Time.now + @interval).to_i
70
+ end
71
+
72
+ def scheduled_jobs
73
+ enqueued_jobs.select { |job| job.key?(:at) }
74
+ end
75
+
76
+ def scheduled_size_for(actual)
77
+ scheduled_jobs.select { |job| match_job(job, actual) }.size
78
+ end
79
+ end
80
+
81
+ RSpec::Matchers.define :have_queued do |*expected_args|
82
+ include QueueHelper
83
+
84
+ chain :times do |num_times_queued|
85
+ @times = num_times_queued
86
+ @times_info = (@times == 1 ? ' once' : " #{@times} times")
87
+ end
88
+
89
+ chain :once do
90
+ @times = 1
91
+ @times_info = ' once'
92
+ end
93
+
94
+ match do |actual|
95
+ matched_jobs = find_matching_jobs(actual, expected_args)
96
+
97
+ check_size_for(matched_jobs, @times)
98
+ end
99
+
100
+ failure_message do |actual|
101
+ "expected that #{actual} would have [#{expected_args.join(', ')}] queued#{@times_info}"
102
+ end
103
+
104
+ failure_message_when_negated do |actual|
105
+ "expected that #{actual} would not have [#{expected_args.join(', ')}] queued#{@times_info}"
106
+ end
107
+
108
+ description do
109
+ "have queued arguments of [#{expected_args.join(', ')}]#{@times_info}"
110
+ end
111
+ end
112
+
113
+ RSpec::Matchers.define :have_queue_size_of do |size|
114
+ include QueueHelper
115
+
116
+ match do |actual|
117
+ queue_size_for(actual) == size
118
+ end
119
+
120
+ failure_message do |actual|
121
+ "expected that #{actual} would have #{size} entries queued, but got #{queue_size_for(actual)} instead"
122
+ end
123
+
124
+ failure_message_when_negated do |actual|
125
+ "expected that #{actual} would not have #{size} entries queued, but got #{queue_size_for(actual)} instead"
126
+ end
127
+
128
+ description do
129
+ "have a queue size of #{size}"
130
+ end
131
+ end
132
+
133
+ RSpec::Matchers.define :have_scheduled do |*expected_args|
134
+ include ScheduleQueueHelper
135
+
136
+ chain :at do |timestamp|
137
+ @interval = nil
138
+ @time = timestamp
139
+ @time_info = "at #{@time}"
140
+ end
141
+
142
+ chain :in do |interval|
143
+ @time = nil
144
+ @interval = interval
145
+ @time_info = "in #{@interval} seconds"
146
+ end
147
+
148
+ match do |actual|
149
+ check_for_scheduled(actual, expected_args)
150
+ end
151
+
152
+ failure_message do |actual|
153
+ ["expected that #{actual} would have [#{expected_args.join(', ')}] scheduled", @time_info].join(' ')
154
+ end
155
+
156
+ failure_message_when_negated do |actual|
157
+ ["expected that #{actual} would not have [#{expected_args.join(', ')}] scheduled", @time_info].join(' ')
158
+ end
159
+
160
+ description do
161
+ "have scheduled arguments"
162
+ end
163
+ end
164
+
165
+ RSpec::Matchers.define :have_schedule_size_of do |size|
166
+ include ScheduleQueueHelper
167
+
168
+ match do |actual|
169
+ scheduled_size_for(actual) == size
170
+ end
171
+
172
+ failure_message do |actual|
173
+ "expected that #{actual} would have #{size} entries scheduled, but got #{queue_size_for(actual)} instead"
174
+ end
175
+
176
+ failure_message_when_negated do |actual|
177
+ "expected that #{actual} would not have #{size} entries scheduled, but got #{queue_size_for(actual)} instead"
178
+ end
179
+
180
+ description do
181
+ "have a scheduled queue size of #{size}"
182
+ end
183
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveJobSpec
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activejob_spec
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Negrei
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: actionpack
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: ''
112
+ email:
113
+ - negrei.petru@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - CODE_OF_CONDUCT.md
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - activejob_spec.gemspec
127
+ - lib/activejob_spec.rb
128
+ - lib/activejob_spec/matchers.rb
129
+ - lib/activejob_spec/version.rb
130
+ homepage: https://github.com/noku/activejob_spec
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.4.8
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: RSpec matcher for ActiveJob
154
+ test_files: []