rspec-activejob 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f57742790063ccf2ed6cd10e683e20389dbac437
4
- data.tar.gz: 231a686b90f41591f5ad437e8beaec9421ae8144
3
+ metadata.gz: 5ec1b26448aaa3732cc1239e94ed67be18fdd034
4
+ data.tar.gz: 53d956546e042ad727cc3d02094c5fb9851c24ff
5
5
  SHA512:
6
- metadata.gz: b95a86346e700b872030feb2d8046e9bfd6c33f9419709186caaee85a49807f72dc51a4e641e13e308fc740053731278b3fb4dc70f278824b44e01276137b8c6
7
- data.tar.gz: 38fedfe32066a157dd1b8b5e77edc9221889acbadf4a81fdaf14309cb58e08bfaa5efad2ec8044afeb2f051764ba7587e2376e67dd8c47a69cea51a3b4d6ef0d
6
+ metadata.gz: 7dbbdb3029c97cb2c71fe0b57d112fece98190849934e26e861e01cb4f2f9a427921fa541cba527589f341f06a1a5629a7a5afd9fddceb7f59d06ec56fabfddf
7
+ data.tar.gz: ded3be79382e60bf7fa9c590da4f34a0732ff660c51236cba33153aae22da379b3144bcd7a8cf8b4f4193dc24b47e35fca75a920bde1eebdaae8396719a61ee2
@@ -0,0 +1,33 @@
1
+ # Limit lines to 90 characters.
2
+ LineLength:
3
+ Max: 90
4
+
5
+ ClassLength:
6
+ Enabled: false
7
+
8
+ # Avoid single-line methods.
9
+ SingleLineMethods:
10
+ AllowIfMethodIsEmpty: true
11
+
12
+ StringLiterals:
13
+ Enabled: false
14
+
15
+ # Wants you to use the same argument names for every reduce. This seems kinda
16
+ # naff compared to naming them semantically
17
+ SingleLineBlockParams:
18
+ Enabled: false
19
+
20
+ Style/SignalException:
21
+ EnforcedStyle: 'only_raise'
22
+
23
+ # Use trailing rather than leading dots on multi-line call chains
24
+ Style/DotPosition:
25
+ EnforcedStyle: trailing
26
+
27
+ # Whatever
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ # RSpec argument matchers use ===. Sorry cop.
32
+ Style/CaseEquality:
33
+ Enabled: false
@@ -0,0 +1,3 @@
1
+ ## 0.1.0 - January 18, 2015
2
+
3
+ - Added support for argument matchers (e.g. `instance_of`, `hash_including`), like the `receive` matcher.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-activejob (0.1.0)
4
+ rspec-activejob (0.2.0)
5
5
  activejob (>= 4.2)
6
6
  rspec-mocks
7
7
 
data/README.md CHANGED
@@ -1,15 +1,48 @@
1
1
  # RSpec ActiveJob matchers
2
2
 
3
3
  ```ruby
4
+ # config/environments/test.rb
5
+ config.active_job.queue_adapter = :test
6
+
7
+ # spec/spec_helper.rb
4
8
  RSpec.configure do |config|
5
9
  config.include(RSpec::ActiveJob)
10
+
11
+ # clean out the queue after each spec
12
+ config.after(:each) do
13
+ ActiveJob::Base.queue_adapter.enqueued_jobs = []
14
+ ActiveJob::Base.queue_adapter.performed_jobs = []
15
+ end
6
16
  end
7
17
 
18
+ # spec/controllers/my_controller_spec.rb
8
19
  RSpec.describe MyController do
9
20
  let(:user) { create(:user) }
10
21
  let(:params) { { user_id: user.id } }
11
22
  subject(:make_request) { described_class.make_request(params) }
12
23
 
13
- specify { expect { make_request }.to enqueue_a(RequestMaker).with(user) }
24
+ specify { expect { make_request }.to enqueue_a(RequestMaker).with(global_id(user)) }
14
25
  end
15
- ```
26
+ ```
27
+
28
+ rspec-activejob expects the current queue adapter to expose an array of `enqueued_jobs`, like the included
29
+ test adapter. The test adapter included in ActiveJob 4.2.0 does not fully serialize its arguments, so you
30
+ will not need to use the GlobalID matcher until ActiveJob 4.2.1. See rails/rails#18266 for the improved
31
+ test adapter.
32
+
33
+ This gem defines two matchers:
34
+
35
+ * `enqueue_a`: for a block or proc, expects that to enqueue an job to the ActiveJob test adapter. Optionally
36
+ takes the job class as its argument, and can be modified with a `.with(*args)` call to expect specific arguments.
37
+ This will use the same argument list matcher as rspec-mocks' `receive(:message).with(*args)` matcher.
38
+
39
+ * `global_id(model_or_class)`: an argument matcher, matching ActiveJob-serialized versions of model classes or
40
+ specific models (or any other class which implements `to_global_id`). If you pass a model class, it will match
41
+ the serialized version of any instance of that model; if you pass an instance, it will expect the serialized
42
+ version of that specific instance.
43
+
44
+
45
+ With the `global_id` matcher it's important to note that it's specific to ActiveJob-serialized GlobalIDs.
46
+ ActiveJob serializes them as a hash like `{ '_aj_global_id' => 'gid://my-app/MyModel/ID123' }`, to avoid
47
+ clashes with plain strings which accidentally match the GlobalID syntax. This matcher will not work with
48
+ other usages of GlobalID.
@@ -1,8 +1,14 @@
1
- require 'rspec/active_job/matchers'
1
+ require 'rspec/active_job/enqueue_a'
2
+ require 'rspec/active_job/global_id'
3
+
2
4
  module RSpec
3
5
  module ActiveJob
4
6
  def enqueue_a(job_class)
5
7
  Matchers::EnqueueA.new(job_class)
6
8
  end
9
+
10
+ def global_id(expected)
11
+ Matchers::GlobalID.new(expected)
12
+ end
7
13
  end
8
14
  end
@@ -27,10 +27,12 @@ module RSpec
27
27
  end
28
28
 
29
29
  unless enqueued_correct_class?
30
- return "expected to enqueue a #{job_class}, enqueued a #{enqueued_jobs.last[:job]}"
30
+ return "expected to enqueue a #{job_class}, " \
31
+ "enqueued a #{enqueued_jobs.last[:job]}"
31
32
  end
32
33
 
33
- "expected to enqueue a #{job_class} with #{argument_list_matcher.expected_args}, but enqueued with " \
34
+ "expected to enqueue a #{job_class} with " \
35
+ "#{argument_list_matcher.expected_args}, but enqueued with " \
34
36
  "#{new_jobs_with_correct_class.first[:args]}"
35
37
  end
36
38
 
@@ -38,6 +40,12 @@ module RSpec
38
40
  true
39
41
  end
40
42
 
43
+ def description
44
+ return "enqueue a job" unless job_class
45
+ return "enqueue a #{job_class.name}" unless argument_list_matcher
46
+ "enqueue a #{job_class.name} with #{argument_list_matcher.expected_args}"
47
+ end
48
+
41
49
  private
42
50
 
43
51
  attr_reader :before_count, :after_count, :job_class, :argument_list_matcher
@@ -65,7 +73,8 @@ module RSpec
65
73
  end
66
74
 
67
75
  def new_jobs_with_correct_class_and_args
68
- new_jobs_with_correct_class.select { |job| argument_list_matcher.args_match?(*job[:args]) }
76
+ new_jobs_with_correct_class.
77
+ select { |job| argument_list_matcher.args_match?(*job[:args]) }
69
78
  end
70
79
 
71
80
  def enqueued_jobs
@@ -0,0 +1,47 @@
1
+ require 'global_id'
2
+
3
+ module RSpec
4
+ module ActiveJob
5
+ module Matchers
6
+ class GlobalID
7
+ def initialize(expected)
8
+ unless valid_expected?(expected)
9
+ raise "expected argument must implement to_global_id"
10
+ end
11
+
12
+ @expected = expected
13
+ end
14
+
15
+ def ===(other)
16
+ other.is_a?(Hash) &&
17
+ other.keys == ['_aj_globalid'] &&
18
+ global_id_matches?(other['_aj_globalid'])
19
+ end
20
+
21
+ def description
22
+ "serialized global ID of #{@expected}" unless @expected.is_a?(Class)
23
+ "serialized global ID of #{@expected.name}"
24
+ end
25
+
26
+ private
27
+
28
+ def valid_expected?(expected)
29
+ return expected.instance_method(:to_global_id) if expected.is_a?(Class)
30
+ expected.respond_to?(:to_global_id)
31
+ end
32
+
33
+ def global_id_matches?(other)
34
+ parsed = ::GlobalID.parse(other)
35
+ return false unless parsed
36
+ return correct_class?(parsed) if @expected.is_a?(Class)
37
+ other == @expected.to_global_id.to_s
38
+ end
39
+
40
+ def correct_class?(other)
41
+ other.app == ::GlobalID.app &&
42
+ other.model_class == @expected
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module ActiveJob
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
@@ -41,7 +41,7 @@ RSpec.describe RSpec::ActiveJob::Matchers::EnqueueA do
41
41
 
42
42
  context "when it enqueues two jobs" do
43
43
  let(:proc) do
44
- -> { enqueued_jobs << { job: AJob, args: []} << { job: BJob, args: [] } }
44
+ -> { enqueued_jobs << { job: AJob, args: [] } << { job: BJob, args: [] } }
45
45
  end
46
46
 
47
47
  it { is_expected.to be(true) }
@@ -70,4 +70,4 @@ RSpec.describe RSpec::ActiveJob::Matchers::EnqueueA do
70
70
  end
71
71
  end
72
72
  end
73
- end
73
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSpec::ActiveJob::Matchers::GlobalID do
4
+ class MyModel
5
+ def to_global_id
6
+ "gid://my-app/MyModel/ID123"
7
+ end
8
+ end
9
+
10
+ let(:instance) { described_class.new(expected) }
11
+ subject(:matches?) { instance === actual }
12
+
13
+ before { GlobalID.app = 'my-app' }
14
+
15
+ context "expecting a class" do
16
+ let(:expected) { MyModel }
17
+
18
+ context "serialized model" do
19
+ let(:actual) { { '_aj_globalid' => 'gid://my-app/MyModel/ID123' } }
20
+ it { is_expected.to be(true) }
21
+ end
22
+
23
+ context "actual model" do
24
+ let(:actual) { MyModel.new }
25
+ it { is_expected.to be(false) }
26
+ end
27
+
28
+ context "model class" do
29
+ let(:actual) { MyModel }
30
+ it { is_expected.to be(false) }
31
+ end
32
+
33
+ context "hash with extra stuff" do
34
+ let(:actual) do
35
+ { '_aj_globalid' => 'gid://my-app/MyModel/ID123', 'other' => 'stuff' }
36
+ end
37
+ it { is_expected.to be(false) }
38
+ end
39
+
40
+ context "invalid GlobalID" do
41
+ let(:actual) { { '_aj_globalid' => 'not://a/global/id' } }
42
+ it { is_expected.to be(false) }
43
+ end
44
+
45
+ context "nil" do
46
+ let(:actual) { nil }
47
+ it { is_expected.to be(false) }
48
+ end
49
+ end
50
+
51
+ context "expecting a specific instance" do
52
+ let(:expected) { MyModel.new }
53
+
54
+ context "serialized instance" do
55
+ let(:actual) { { '_aj_globalid' => 'gid://my-app/MyModel/ID123' } }
56
+ it { is_expected.to be(true) }
57
+ end
58
+
59
+ context "model class" do
60
+ let(:actual) { MyModel }
61
+ it { is_expected.to be(false) }
62
+ end
63
+
64
+ context "instance itself" do
65
+ let(:actual) { expected }
66
+ it { is_expected.to be(false) }
67
+ end
68
+
69
+ context "hash with extra stuff" do
70
+ let(:actual) do
71
+ { '_aj_globalid' => 'gid://my-app/MyModel/ID123', 'other' => 'stuff' }
72
+ end
73
+ it { is_expected.to be(false) }
74
+ end
75
+
76
+ context "mismatching app" do
77
+ let(:actual) { { '_aj_globalid' => 'gid://other-app/MyModel/ID123' } }
78
+ it { is_expected.to be(false) }
79
+ end
80
+
81
+ context "mismatching model" do
82
+ let(:actual) { { '_aj_globalid' => 'gid://my-app/OtherModel/ID123' } }
83
+ it { is_expected.to be(false) }
84
+ end
85
+
86
+ context "mismatching ID" do
87
+ let(:actual) { { '_aj_globalid' => 'gid://my-app/MyModel/ID456' } }
88
+ it { is_expected.to be(false) }
89
+ end
90
+ end
91
+
92
+ context "expecting a non-gid instance" do
93
+ let(:expected) { Object.new }
94
+ specify { expect { matches? }.to raise_error }
95
+ end
96
+
97
+ context "expecting a non-gid class" do
98
+ let(:expected) { Object }
99
+ specify { expect { matches? }.to raise_error }
100
+ end
101
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-activejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Isaac Seymour
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-18 00:00:00.000000000 Z
11
+ date: 2015-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -76,14 +76,18 @@ extensions: []
76
76
  extra_rdoc_files: []
77
77
  files:
78
78
  - .gitignore
79
+ - .rubocop.yml
80
+ - CHANGELOG.md
79
81
  - Gemfile
80
82
  - Gemfile.lock
81
83
  - README.md
82
84
  - lib/rspec/active_job.rb
83
- - lib/rspec/active_job/matchers.rb
85
+ - lib/rspec/active_job/enqueue_a.rb
86
+ - lib/rspec/active_job/global_id.rb
84
87
  - lib/rspec/active_job/version.rb
85
88
  - rspec-activejob.gemspec
86
- - spec/rspec/active_job/matchers_spec.rb
89
+ - spec/rspec/active_job/enqueue_a_spec.rb
90
+ - spec/rspec/active_job/global_id_spec.rb
87
91
  - spec/spec_helper.rb
88
92
  homepage: http://github.com/gocardless/rspec-activejob
89
93
  licenses: