journaled 4.0.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,3 +16,89 @@ RSpec::Matchers.define :journal_changes_to do |*attribute_names, as:|
16
16
  "expected #{model_class} not to journal changes to #{attribute_names.map(&:inspect).join(', ')} as #{as.inspect}"
17
17
  end
18
18
  end
19
+
20
+ RSpec::Matchers.define_negated_matcher :not_journal_changes_to, :journal_changes_to
21
+
22
+ RSpec::Matchers.define :journal_events_including do |*expected_events|
23
+ raise "Please specify at least one expected event. RSpec argument matchers are supported." if expected_events.empty?
24
+
25
+ attr_accessor :expected, :actual, :matches, :nonmatches
26
+
27
+ chain :with_schema_name, :expected_schema_name
28
+ chain :with_partition_key, :expected_partition_key
29
+ chain :with_stream_name, :expected_stream_name
30
+ chain :with_enqueue_opts, :expected_enqueue_opts
31
+ chain :with_priority, :expected_priority
32
+
33
+ def supports_block_expectations?
34
+ true
35
+ end
36
+
37
+ def hash_including_recursive(hash)
38
+ hash_including(
39
+ hash.transform_values { |v| v.is_a?(Hash) ? hash_including_recursive(v) : v },
40
+ )
41
+ end
42
+
43
+ match do |block|
44
+ expected_events = [expected_events.first].flatten(1) unless expected_events.length > 1
45
+
46
+ self.expected = expected_events.map { |e| { journaled_attributes: e } }
47
+ expected.each { |e| e.merge!(journaled_schema_name: expected_schema_name) } if expected_schema_name
48
+ expected.each { |e| e.merge!(journaled_partition_key: expected_partition_key) } if expected_partition_key
49
+ expected.each { |e| e.merge!(journaled_stream_name: expected_stream_name) } if expected_stream_name
50
+ expected.each { |e| e.merge!(journaled_enqueue_opts: expected_enqueue_opts) } if expected_enqueue_opts
51
+ expected.each { |e| e.merge!(priority: expected_priority) } if expected_priority
52
+ self.actual = []
53
+
54
+ callback = ->(_name, _started, _finished, _unique_id, payload) do
55
+ event = payload[:event]
56
+ a = { journaled_attributes: event.journaled_attributes }
57
+ a[:journaled_schema_name] = event.journaled_schema_name if expected_schema_name
58
+ a[:journaled_partition_key] = event.journaled_partition_key if expected_partition_key
59
+ a[:journaled_stream_name] = event.journaled_stream_name if expected_stream_name
60
+ a[:journaled_enqueue_opts] = event.journaled_enqueue_opts if expected_enqueue_opts
61
+ a[:priority] = payload[:priority] if expected_priority
62
+ actual << a
63
+ end
64
+
65
+ ActiveSupport::Notifications.subscribed(callback, 'journaled.event.enqueue', &block)
66
+
67
+ self.matches = actual.select do |a|
68
+ expected.any? { |e| values_match?(hash_including_recursive(e), a) }
69
+ end
70
+
71
+ self.nonmatches = actual - matches
72
+
73
+ exact_matches = matches.dup
74
+ matches.count == expected.count && expected.all? do |e|
75
+ match, index = exact_matches.each_with_index.find { |a, _| values_match?(hash_including_recursive(e), a) }
76
+ exact_matches.delete_at(index) if match
77
+ end && exact_matches.empty?
78
+ end
79
+
80
+ failure_message do
81
+ <<~MSG
82
+ Expected the code block to journal exactly one matching event per expected event.
83
+
84
+ Expected Events (#{expected.count}):
85
+ ===============================================================================
86
+ #{expected.map(&:to_json).join("\n ")}
87
+ ===============================================================================
88
+
89
+ Matching Events (#{matches.count}):
90
+ ===============================================================================
91
+ #{matches.map(&:to_json).join("\n ")}
92
+ ===============================================================================
93
+
94
+ Non-Matching Events (#{nonmatches.count}):
95
+ ===============================================================================
96
+ #{nonmatches.map(&:to_json).join("\n ")}
97
+ ===============================================================================
98
+ MSG
99
+ end
100
+ end
101
+
102
+ RSpec::Matchers.alias_matcher :journal_event_including, :journal_events_including
103
+ RSpec::Matchers.define_negated_matcher :not_journal_events_including, :journal_events_including
104
+ RSpec::Matchers.define_negated_matcher :not_journal_event_including, :journal_event_including
@@ -1,3 +1,3 @@
1
1
  module Journaled
2
- VERSION = "4.0.0".freeze
2
+ VERSION = "4.3.0".freeze
3
3
  end
data/lib/journaled.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require "aws-sdk-kinesis"
2
2
  require "active_job"
3
3
  require "json-schema"
4
- require "request_store"
5
4
 
6
5
  require "journaled/engine"
6
+ require "journaled/current"
7
7
 
8
8
  module Journaled
9
9
  SUPPORTED_QUEUE_ADAPTERS = %w(delayed delayed_job good_job que).freeze
@@ -20,7 +20,7 @@ module Journaled
20
20
  end
21
21
 
22
22
  def enabled?
23
- !['0', 'false', false, 'f', ''].include?(ENV.fetch('JOURNALED_ENABLED', !development_or_test?))
23
+ ['0', 'false', false, 'f', ''].exclude?(ENV.fetch('JOURNALED_ENABLED', !development_or_test?))
24
24
  end
25
25
 
26
26
  def schema_providers
@@ -51,5 +51,17 @@ module Journaled
51
51
  end
52
52
  end
53
53
 
54
+ def self.tagged(**tags)
55
+ existing_tags = Current.tags
56
+ tag!(**tags)
57
+ yield
58
+ ensure
59
+ Current.tags = existing_tags
60
+ end
61
+
62
+ def self.tag!(**tags)
63
+ Current.tags = Current.tags.merge(tags)
64
+ end
65
+
54
66
  module_function :development_or_test?, :enabled?, :schema_providers, :commit_hash, :actor_uri, :detect_queue_adapter!
55
67
  end
data/spec/dummy/config.ru CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is used by Rack-based servers to start the application.
2
2
 
3
- require ::File.expand_path('../config/environment', __FILE__)
3
+ require ::File.expand_path('config/environment', __dir__)
4
4
  run Rails.application
@@ -21,7 +21,7 @@ RSpec.describe Journaled::DeliveryJob do
21
21
  end
22
22
 
23
23
  it 'makes requests to AWS to put the event on the Kinesis with the correct body' do
24
- event = described_class.perform_now(args)
24
+ event = described_class.perform_now(**args)
25
25
 
26
26
  expect(event.shard_id).to eq '101'
27
27
  expect(event.sequence_number).to eq '101123'
@@ -60,7 +60,7 @@ RSpec.describe Journaled::DeliveryJob do
60
60
  end
61
61
 
62
62
  it 'initializes a Kinesis client with assume role credentials' do
63
- described_class.perform_now(args)
63
+ described_class.perform_now(**args)
64
64
 
65
65
  expect(Aws::AssumeRoleCredentials).to have_received(:new).with(
66
66
  client: aws_sts_client,
@@ -74,7 +74,7 @@ RSpec.describe Journaled::DeliveryJob do
74
74
  let(:stream_name) { nil }
75
75
 
76
76
  it 'raises an KeyError error' do
77
- expect { described_class.perform_now(args) }.to raise_error ArgumentError, 'missing keyword: stream_name'
77
+ expect { described_class.perform_now(**args) }.to raise_error ArgumentError, 'missing keyword: stream_name'
78
78
  end
79
79
  end
80
80
 
@@ -99,7 +99,7 @@ RSpec.describe Journaled::DeliveryJob do
99
99
  end
100
100
 
101
101
  it 'makes requests to AWS to put the event on the Kinesis with the correct body' do
102
- event = described_class.perform_now(args)
102
+ event = described_class.perform_now(**args)
103
103
 
104
104
  expect(event.shard_id).to eq '101'
105
105
  expect(event.sequence_number).to eq '101123'
@@ -119,7 +119,7 @@ RSpec.describe Journaled::DeliveryJob do
119
119
  end
120
120
 
121
121
  it 'makes requests to AWS to put the event on the Kinesis with the correct body' do
122
- event = described_class.perform_now(args)
122
+ event = described_class.perform_now(**args)
123
123
 
124
124
  expect(event.shard_id).to eq '101'
125
125
  expect(event.sequence_number).to eq '101123'
@@ -138,7 +138,7 @@ RSpec.describe Journaled::DeliveryJob do
138
138
 
139
139
  it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
140
140
  allow(Rails.logger).to receive(:error)
141
- expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
141
+ expect { described_class.perform_now(**args) }.to raise_error described_class::KinesisTemporaryFailure
142
142
  expect(Rails.logger).to have_received(:error).with(
143
143
  "Kinesis Error - Server Error occurred - Aws::Kinesis::Errors::InternalFailure",
144
144
  ).once
@@ -152,7 +152,7 @@ RSpec.describe Journaled::DeliveryJob do
152
152
 
153
153
  it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
154
154
  allow(Rails.logger).to receive(:error)
155
- expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
155
+ expect { described_class.perform_now(**args) }.to raise_error described_class::KinesisTemporaryFailure
156
156
  expect(Rails.logger).to have_received(:error).with(/\AKinesis Error/).once
157
157
  end
158
158
  end
@@ -163,7 +163,7 @@ RSpec.describe Journaled::DeliveryJob do
163
163
  end
164
164
 
165
165
  it 'raises an error that subclasses Aws::Kinesis::Errors::ServiceError' do
166
- expect { described_class.perform_now(args) }.to raise_error Aws::Kinesis::Errors::ServiceError
166
+ expect { described_class.perform_now(**args) }.to raise_error Aws::Kinesis::Errors::ServiceError
167
167
  end
168
168
  end
169
169
 
@@ -173,7 +173,7 @@ RSpec.describe Journaled::DeliveryJob do
173
173
  end
174
174
 
175
175
  it 'raises an AccessDeniedException error' do
176
- expect { described_class.perform_now(args) }.to raise_error Aws::Kinesis::Errors::AccessDeniedException
176
+ expect { described_class.perform_now(**args) }.to raise_error Aws::Kinesis::Errors::AccessDeniedException
177
177
  end
178
178
  end
179
179
 
@@ -184,7 +184,7 @@ RSpec.describe Journaled::DeliveryJob do
184
184
 
185
185
  it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
186
186
  allow(Rails.logger).to receive(:error)
187
- expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
187
+ expect { described_class.perform_now(**args) }.to raise_error described_class::KinesisTemporaryFailure
188
188
  expect(Rails.logger).to have_received(:error).with(
189
189
  "Kinesis Error - Networking Error occurred - Seahorse::Client::NetworkingError",
190
190
  ).once
@@ -75,12 +75,10 @@ RSpec.describe Journaled do
75
75
  end
76
76
 
77
77
  around do |example|
78
- begin
79
- example.run
80
- ensure
81
- ActiveJob::Base.queue_adapter = :test
82
- ActiveJob::Base.enable_test_adapter(ActiveJob::QueueAdapters::TestAdapter.new)
83
- end
78
+ example.run
79
+ ensure
80
+ ActiveJob::Base.queue_adapter = :test
81
+ ActiveJob::Base.enable_test_adapter(ActiveJob::QueueAdapters::TestAdapter.new)
84
82
  end
85
83
 
86
84
  it 'does not raise an error' do
@@ -5,11 +5,10 @@ RSpec.describe Journaled::Actor do
5
5
  let(:user) { double("User") }
6
6
  let(:klass) do
7
7
  Class.new do
8
- cattr_accessor :before_actions
9
- self.before_actions = []
8
+ cattr_accessor(:before_actions) { [] }
10
9
 
11
- def self.before_action(&hook)
12
- before_actions << hook
10
+ def self.before_action(method_name, _opts)
11
+ before_actions << method_name
13
12
  end
14
13
 
15
14
  include Journaled::Actor
@@ -21,7 +20,7 @@ RSpec.describe Journaled::Actor do
21
20
  end
22
21
 
23
22
  def trigger_before_actions
24
- before_actions.each { |proc| instance_eval(&proc) }
23
+ before_actions.each { |method_name| send(method_name) }
25
24
  end
26
25
  end
27
26
  end
@@ -33,7 +32,8 @@ RSpec.describe Journaled::Actor do
33
32
 
34
33
  allow(subject).to receive(:current_user).and_return(nil)
35
34
 
36
- expect(RequestStore.store[:journaled_actor_proc].call).to eq nil
35
+ expect(Journaled::Current.journaled_actor_proc.call).to be_nil
36
+ expect(Journaled::Current.actor).to be_nil
37
37
  end
38
38
 
39
39
  it "Stores a thunk returning current_user if it is set when called" do
@@ -41,6 +41,7 @@ RSpec.describe Journaled::Actor do
41
41
 
42
42
  allow(subject).to receive(:current_user).and_return(user)
43
43
 
44
- expect(RequestStore.store[:journaled_actor_proc].call).to eq user
44
+ expect(Journaled::Current.journaled_actor_proc.call).to eq user
45
+ expect(Journaled::Current.actor).to eq user
45
46
  end
46
47
  end
@@ -44,7 +44,7 @@ RSpec.describe Journaled::Changes do
44
44
 
45
45
  subject { klass.new }
46
46
 
47
- let(:change_writer) { double(Journaled::ChangeWriter, create: true, update: true, delete: true) }
47
+ let(:change_writer) { instance_double(Journaled::ChangeWriter, create: true, update: true, delete: true) }
48
48
 
49
49
  before do
50
50
  allow(Journaled::ChangeWriter).to receive(:new) do |opts|
@@ -2,7 +2,7 @@ require 'rails_helper'
2
2
 
3
3
  RSpec.describe Journaled::ActorUriProvider do
4
4
  describe "#actor_uri" do
5
- let(:request_store) { double(:[] => nil) }
5
+ let(:current_attributes) { double(:[] => nil) }
6
6
  let(:actor) { double(to_global_id: actor_gid) }
7
7
  let(:actor_gid) { double(to_s: "my_fancy_gid") }
8
8
  let(:program_name) { "/usr/local/bin/puma_or_something" }
@@ -17,13 +17,14 @@ RSpec.describe Journaled::ActorUriProvider do
17
17
  end
18
18
 
19
19
  before do
20
- allow(RequestStore).to receive(:store).and_return(request_store)
20
+ allow(Journaled::Current.instance)
21
+ .to receive(:attributes).and_return(current_attributes)
21
22
  end
22
23
 
23
- it "returns the global ID of the entity returned by RequestStore.store[:journaled_actor_proc].call if set" do
24
- allow(request_store).to receive(:[]).and_return(-> { actor })
24
+ it "returns the global ID of the entity returned by Current.journaled_actor_proc.call if set" do
25
+ allow(current_attributes).to receive(:[]).and_return(-> { actor })
25
26
  expect(subject.actor_uri).to eq("my_fancy_gid")
26
- expect(request_store).to have_received(:[]).with(:journaled_actor_proc)
27
+ expect(current_attributes).to have_received(:[]).with(:journaled_actor_proc)
27
28
  end
28
29
 
29
30
  context "when running in rake" do
@@ -139,7 +139,7 @@ RSpec.describe Journaled::ChangeWriter do
139
139
  end
140
140
 
141
141
  it "doesn't set journaled_stream_name if model class doesn't respond to it" do
142
- expect(subject.journaled_change_for("update", {}).journaled_stream_name).to eq(nil)
142
+ expect(subject.journaled_change_for("update", {}).journaled_stream_name).to be_nil
143
143
  end
144
144
 
145
145
  context "with journaled default app name set" do
@@ -88,8 +88,10 @@ RSpec.describe Journaled::Event do
88
88
 
89
89
  context 'when no additional attributes have been defined' do
90
90
  it 'returns the base attributes, and memoizes them after the first call' do
91
- expect(sample_journaled_event.journaled_attributes).to eq id: fake_uuid, created_at: frozen_time, event_type: 'some_class_name'
92
- expect(sample_journaled_event.journaled_attributes).to eq id: fake_uuid, created_at: frozen_time, event_type: 'some_class_name'
91
+ expect(sample_journaled_event.journaled_attributes)
92
+ .to eq id: fake_uuid, created_at: frozen_time, event_type: 'some_class_name'
93
+ expect(sample_journaled_event.journaled_attributes)
94
+ .to eq id: fake_uuid, created_at: frozen_time, event_type: 'some_class_name'
93
95
  end
94
96
  end
95
97
 
@@ -134,6 +136,80 @@ RSpec.describe Journaled::Event do
134
136
  )
135
137
  end
136
138
  end
139
+
140
+ context 'tagged: true' do
141
+ before do
142
+ sample_journaled_event_class.journal_attributes tagged: true
143
+ end
144
+
145
+ it 'adds a "tags" attribute' do
146
+ expect(sample_journaled_event.journaled_attributes).to include(tags: {})
147
+ end
148
+
149
+ context 'when tags are specified' do
150
+ around do |example|
151
+ Journaled.tag!(foo: 'bar')
152
+ Journaled.tagged(baz: 'bat') { example.run }
153
+ end
154
+
155
+ it 'adds them to the journaled attributes' do
156
+ expect(sample_journaled_event.journaled_attributes).to include(
157
+ tags: { foo: 'bar', baz: 'bat' },
158
+ )
159
+ end
160
+
161
+ context 'when even more tags are nested' do
162
+ it 'merges them in and then resets them' do
163
+ Journaled.tagged(oh_no: 'even more tags') do
164
+ expect(sample_journaled_event.journaled_attributes).to include(
165
+ tags: { foo: 'bar', baz: 'bat', oh_no: 'even more tags' },
166
+ )
167
+ end
168
+
169
+ allow(SecureRandom).to receive(:uuid).and_return(fake_uuid).once
170
+ expect(sample_journaled_event_class.new.journaled_attributes).to include(
171
+ tags: { foo: 'bar', baz: 'bat' },
172
+ )
173
+ end
174
+ end
175
+
176
+ context 'when custom event tags are also specified and merged' do
177
+ let(:sample_journaled_event_class) do
178
+ Class.new do
179
+ include Journaled::Event
180
+
181
+ def tags
182
+ super.merge(abc: '123')
183
+ end
184
+ end
185
+ end
186
+
187
+ it 'combines all tags' do
188
+ expect(sample_journaled_event.journaled_attributes).to include(
189
+ tags: { foo: 'bar', baz: 'bat', abc: '123' },
190
+ )
191
+ end
192
+ end
193
+
194
+ context 'when custom event tags are also specified but not merged' do
195
+ let(:sample_journaled_event_class) do
196
+ Class.new do
197
+ include Journaled::Event
198
+
199
+ def tags
200
+ { bananas: 'are great', but_not_actually: 'the best source of potassium' } # it's true
201
+ end
202
+ end
203
+ end
204
+
205
+ it 'adds them to the journaled attributes' do
206
+ expect(sample_journaled_event.journaled_attributes).to include(
207
+ tags: { bananas: 'are great', but_not_actually: 'the best source of potassium' },
208
+ )
209
+ end
210
+ end
211
+ end
212
+ end
137
213
  end
138
214
 
139
215
  describe '#journaled_enqueue_opts, .journaled_enqueue_opts' do
@@ -8,7 +8,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
8
8
  let(:attributes_to_validate) do
9
9
  {
10
10
  some_string: some_string_value,
11
- some_decimal: 0.1.to_d,
11
+ some_decimal: BigDecimal('0.1'),
12
12
  some_time: Time.zone.parse('2017-01-20 15:16:17 -05:00'),
13
13
  some_int: some_int_value,
14
14
  some_optional_string: some_optional_string_value,
@@ -66,7 +66,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
66
66
  context 'when all the required fields are provided' do
67
67
  context 'when all the fields are provided' do
68
68
  it 'is valid' do
69
- expect(subject.validate!(json_to_validate)).to eq true
69
+ expect(subject.validate!(json_to_validate)).to be true
70
70
  end
71
71
  end
72
72
 
@@ -74,7 +74,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
74
74
  let(:attributes_to_validate) do
75
75
  {
76
76
  some_string: some_string_value,
77
- some_decimal: 0.1.to_d,
77
+ some_decimal: BigDecimal('0.1'),
78
78
  some_time: Time.zone.parse('2017-01-20 15:16:17 -05:00'),
79
79
  some_int: some_int_value,
80
80
  some_nullable_field: some_nullable_field,
@@ -82,7 +82,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
82
82
  end
83
83
 
84
84
  it 'is valid' do
85
- expect(subject.validate!(json_to_validate)).to eq true
85
+ expect(subject.validate!(json_to_validate)).to be true
86
86
  end
87
87
  end
88
88
 
@@ -90,7 +90,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
90
90
  let(:some_nullable_optional_field) { nil }
91
91
 
92
92
  it 'is valid' do
93
- expect(subject.validate!(json_to_validate)).to eq true
93
+ expect(subject.validate!(json_to_validate)).to be true
94
94
  end
95
95
  end
96
96
 
@@ -107,7 +107,7 @@ RSpec.describe Journaled::JsonSchemaModel::Validator do
107
107
  let(:attributes_to_validate) do
108
108
  {
109
109
  some_string: some_string_value,
110
- some_decimal: 0.1.to_d,
110
+ some_decimal: BigDecimal('0.1'),
111
111
  some_time: Time.zone.parse('2017-01-20 15:16:17 -05:00'),
112
112
  }
113
113
  end
@@ -1,11 +1,12 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  RSpec.describe Journaled::Writer do
4
+ let(:event_class) { Class.new { include Journaled::Event } }
4
5
  subject { described_class.new journaled_event: journaled_event }
5
6
 
6
7
  describe '#initialize' do
7
8
  context 'when the Journaled Event does not implement all the necessary methods' do
8
- let(:journaled_event) { double }
9
+ let(:journaled_event) { instance_double(event_class) }
9
10
 
10
11
  it 'raises on initialization' do
11
12
  expect { subject }.to raise_error RuntimeError, /An enqueued event must respond to/
@@ -14,7 +15,8 @@ RSpec.describe Journaled::Writer do
14
15
 
15
16
  context 'when the Journaled Event returns non-present values for some of the required methods' do
16
17
  let(:journaled_event) do
17
- double(
18
+ instance_double(
19
+ event_class,
18
20
  journaled_schema_name: nil,
19
21
  journaled_attributes: {},
20
22
  journaled_partition_key: '',
@@ -30,7 +32,8 @@ RSpec.describe Journaled::Writer do
30
32
 
31
33
  context 'when the Journaled Event complies with the API' do
32
34
  let(:journaled_event) do
33
- double(
35
+ instance_double(
36
+ event_class,
34
37
  journaled_schema_name: :fake_schema_name,
35
38
  journaled_attributes: { foo: :bar },
36
39
  journaled_partition_key: 'fake_partition_key',
@@ -71,12 +74,14 @@ RSpec.describe Journaled::Writer do
71
74
 
72
75
  let(:journaled_enqueue_opts) { {} }
73
76
  let(:journaled_event) do
74
- double(
75
- journaled_schema_name: :fake_schema_name,
77
+ instance_double(
78
+ event_class,
79
+ journaled_schema_name: 'fake_schema_name',
76
80
  journaled_attributes: journaled_event_attributes,
77
81
  journaled_partition_key: 'fake_partition_key',
78
82
  journaled_stream_name: 'my_app_events',
79
83
  journaled_enqueue_opts: journaled_enqueue_opts,
84
+ tagged?: false,
80
85
  )
81
86
  end
82
87
 
@@ -84,7 +89,9 @@ RSpec.describe Journaled::Writer do
84
89
  let(:journaled_event_attributes) { { foo: 1 } }
85
90
 
86
91
  it 'raises an error and does not enqueue anything' do
87
- expect { subject.journal! }.to raise_error JSON::Schema::ValidationError
92
+ expect { subject.journal! }
93
+ .to raise_error(JSON::Schema::ValidationError)
94
+ .and not_journal_event_including(anything)
88
95
  expect(enqueued_jobs.count).to eq 0
89
96
  end
90
97
  end
@@ -94,7 +101,9 @@ RSpec.describe Journaled::Writer do
94
101
  let(:journaled_event_attributes) { { id: 'FAKE_UUID', event_type: 'fake_event', created_at: Time.zone.now, foo: 1 } }
95
102
 
96
103
  it 'raises an error and does not enqueue anything' do
97
- expect { subject.journal! }.to raise_error JSON::Schema::ValidationError
104
+ expect { subject.journal! }
105
+ .to raise_error(JSON::Schema::ValidationError)
106
+ .and not_journal_event_including(anything)
98
107
  expect(enqueued_jobs.count).to eq 0
99
108
  end
100
109
  end
@@ -103,7 +112,13 @@ RSpec.describe Journaled::Writer do
103
112
  let(:journaled_event_attributes) { { id: 'FAKE_UUID', event_type: 'fake_event', created_at: Time.zone.now, foo: :bar } }
104
113
 
105
114
  it 'creates a delivery with the app name passed through' do
106
- expect { subject.journal! }.to change { enqueued_jobs.count }.from(0).to(1)
115
+ expect { subject.journal! }
116
+ .to change { enqueued_jobs.count }.from(0).to(1)
117
+ .and journal_event_including(journaled_event_attributes)
118
+ .with_schema_name('fake_schema_name')
119
+ .with_partition_key('fake_partition_key')
120
+ .with_stream_name('my_app_events')
121
+ .with_enqueue_opts({})
107
122
  expect(enqueued_jobs.first[:args].first).to include('stream_name' => 'my_app_events')
108
123
  end
109
124
 
@@ -118,11 +133,18 @@ RSpec.describe Journaled::Writer do
118
133
  it 'defaults to the global default' do
119
134
  expect { subject.journal! }.to change {
120
135
  if Rails::VERSION::MAJOR < 6
121
- enqueued_jobs.select { |j| j[:job] == Journaled::DeliveryJob }.count
136
+ enqueued_jobs.count { |j| j[:job] == Journaled::DeliveryJob }
122
137
  else
123
- enqueued_jobs.select { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 999 }.count
138
+ enqueued_jobs.count { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 999 }
124
139
  end
125
140
  }.from(0).to(1)
141
+ .and journal_event_including(journaled_event_attributes)
142
+ .with_schema_name('fake_schema_name')
143
+ .with_partition_key('fake_partition_key')
144
+ .with_stream_name('my_app_events')
145
+ .with_priority(999)
146
+ .and not_journal_event_including(anything)
147
+ .with_enqueue_opts(priority: 999) # with_enqueue_opts looks at event itself
126
148
  end
127
149
  end
128
150
 
@@ -132,14 +154,59 @@ RSpec.describe Journaled::Writer do
132
154
  it 'enqueues a Journaled::DeliveryJob with the given priority' do
133
155
  expect { subject.journal! }.to change {
134
156
  if Rails::VERSION::MAJOR < 6
135
- enqueued_jobs.select { |j| j[:job] == Journaled::DeliveryJob }.count
157
+ enqueued_jobs.count { |j| j[:job] == Journaled::DeliveryJob }
136
158
  else
137
- enqueued_jobs.select { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 13 }.count
159
+ enqueued_jobs.count { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 13 }
138
160
  end
139
161
  }.from(0).to(1)
162
+ .and journal_event_including(journaled_event_attributes)
163
+ .with_schema_name('fake_schema_name')
164
+ .with_partition_key('fake_partition_key')
165
+ .with_stream_name('my_app_events')
166
+ .with_priority(13)
167
+ .with_enqueue_opts(priority: 13)
140
168
  end
141
169
  end
142
170
  end
143
171
  end
172
+
173
+ context 'when the event is tagged' do
174
+ before do
175
+ allow(journaled_event).to receive(:tagged?).and_return(true)
176
+ end
177
+
178
+ context 'and the "tags" attribute is not present' do
179
+ let(:journaled_event_attributes) do
180
+ { id: 'FAKE_UUID', event_type: 'fake_event', created_at: Time.zone.now, foo: 'bar' }
181
+ end
182
+
183
+ it 'raises an error and does not enqueue anything' do
184
+ expect { subject.journal! }
185
+ .to not_journal_events_including(anything)
186
+ .and raise_error JSON::Schema::ValidationError
187
+ expect(enqueued_jobs.count).to eq 0
188
+ end
189
+ end
190
+
191
+ context 'and the "tags" attribute is present' do
192
+ let(:journaled_event_attributes) do
193
+ { id: 'FAKE_UUID', event_type: 'fake_event', created_at: Time.zone.now, foo: 'bar', tags: { baz: 'bat' } }
194
+ end
195
+
196
+ it 'creates a delivery with the app name passed through' do
197
+ expect { subject.journal! }
198
+ .to change { enqueued_jobs.count }.from(0).to(1)
199
+ .and journal_event_including(journaled_event_attributes)
200
+ .with_schema_name('fake_schema_name')
201
+ .with_partition_key('fake_partition_key')
202
+ .with_stream_name('my_app_events')
203
+ .with_enqueue_opts({})
204
+ .with_priority(Journaled.job_priority)
205
+ .and not_journal_event_including(anything)
206
+ .with_enqueue_opts(priority: Journaled.job_priority)
207
+ expect(enqueued_jobs.first[:args].first).to include('stream_name' => 'my_app_events')
208
+ end
209
+ end
210
+ end
144
211
  end
145
212
  end
data/spec/rails_helper.rb CHANGED
@@ -7,7 +7,7 @@ require 'timecop'
7
7
  require 'webmock/rspec'
8
8
  require 'journaled/rspec'
9
9
 
10
- Dir[Rails.root.join('..', 'support', '**', '*.rb')].each { |f| require f }
10
+ Dir[Rails.root.join('../support/**/*.rb')].sort.each { |f| require f }
11
11
 
12
12
  RSpec.configure do |config|
13
13
  config.use_transactional_fixtures = true