msgr 1.2.0 → 1.4.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 +4 -4
- data/.editorconfig +8 -0
- data/.github/workflows/test.yml +79 -0
- data/.rubocop.yml +12 -47
- data/Appraisals +23 -0
- data/CHANGELOG.md +87 -5
- data/Gemfile +9 -15
- data/README.md +11 -28
- data/Rakefile +10 -6
- data/bin/msgr +1 -0
- data/gemfiles/rails_5.2.gemfile +15 -0
- data/gemfiles/rails_6.0.gemfile +15 -0
- data/gemfiles/rails_6.1.gemfile +15 -0
- data/gemfiles/rails_7.0.gemfile +15 -0
- data/gemfiles/rails_head.gemfile +15 -0
- data/lib/msgr/binding.rb +13 -8
- data/lib/msgr/channel.rb +7 -10
- data/lib/msgr/cli.rb +26 -20
- data/lib/msgr/client.rb +27 -25
- data/lib/msgr/connection.rb +14 -2
- data/lib/msgr/consumer.rb +2 -3
- data/lib/msgr/dispatcher.rb +7 -9
- data/lib/msgr/logging.rb +2 -0
- data/lib/msgr/message.rb +1 -2
- data/lib/msgr/railtie.rb +14 -75
- data/lib/msgr/route.rb +2 -5
- data/lib/msgr/routes.rb +2 -0
- data/lib/msgr/tasks/msgr/drain.rake +11 -0
- data/lib/msgr/test_pool.rb +1 -3
- data/lib/msgr/version.rb +1 -1
- data/lib/msgr.rb +2 -3
- data/msgr.gemspec +8 -6
- data/renovate.json +5 -0
- data/scripts/simple_test.rb +3 -4
- data/spec/fixtures/{msgr-routes-test-1.rb → msgr_routes_test_1.rb} +0 -0
- data/spec/fixtures/msgr_routes_test_drain.rb +5 -0
- data/spec/integration/dummy/Rakefile +1 -1
- data/spec/{msgr/support/.keep → integration/dummy/app/assets/config/manifest.js} +0 -0
- data/spec/integration/dummy/bin/bundle +1 -1
- data/spec/integration/dummy/bin/rails +1 -1
- data/spec/integration/dummy/config/application.rb +1 -1
- data/spec/integration/dummy/config/boot.rb +2 -2
- data/spec/integration/dummy/config/environment.rb +1 -1
- data/spec/integration/dummy/config/rabbitmq.yml +1 -1
- data/spec/integration/msgr/dispatcher_spec.rb +28 -12
- data/spec/integration/msgr/railtie_spec.rb +10 -120
- data/spec/integration/spec_helper.rb +2 -3
- data/spec/integration/{msgr_spec.rb → test_controller_spec.rb} +1 -1
- data/spec/unit/msgr/client_spec.rb +83 -0
- data/spec/{msgr → unit}/msgr/connection_spec.rb +1 -1
- data/spec/{msgr → unit}/msgr/consumer_spec.rb +0 -0
- data/spec/unit/msgr/dispatcher_spec.rb +45 -0
- data/spec/{msgr → unit}/msgr/route_spec.rb +29 -14
- data/spec/{msgr → unit}/msgr/routes_spec.rb +32 -35
- data/spec/{msgr → unit}/msgr_spec.rb +26 -18
- data/spec/{msgr → unit}/spec_helper.rb +1 -1
- data/spec/unit/support/.keep +0 -0
- metadata +43 -36
- data/.travis.yml +0 -43
- data/gemfiles/Gemfile.rails-4-2 +0 -7
- data/gemfiles/Gemfile.rails-5-0 +0 -7
- data/gemfiles/Gemfile.rails-5-1 +0 -7
- data/gemfiles/Gemfile.rails-5-2 +0 -7
- data/gemfiles/Gemfile.rails-master +0 -14
- data/spec/msgr/msgr/client_spec.rb +0 -60
- data/spec/msgr/msgr/dispatcher_spec.rb +0 -44
- data/spec/support/setup.rb +0 -29
@@ -3,6 +3,6 @@
|
|
3
3
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
4
4
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
5
5
|
|
6
|
-
require File.expand_path('
|
6
|
+
require File.expand_path('config/application', __dir__)
|
7
7
|
|
8
8
|
Dummy::Application.load_tasks
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Set up gems listed in the Gemfile.
|
4
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('
|
4
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
|
5
5
|
|
6
6
|
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
7
|
-
$LOAD_PATH.unshift File.expand_path('
|
7
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
|
@@ -4,7 +4,19 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
class DispatcherTestConsumer < Msgr::Consumer
|
6
6
|
def index
|
7
|
-
|
7
|
+
self.class.called!
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def calls
|
12
|
+
@calls ||= 0
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_writer :calls
|
16
|
+
|
17
|
+
def called!
|
18
|
+
self.calls += 1
|
19
|
+
end
|
8
20
|
end
|
9
21
|
end
|
10
22
|
|
@@ -19,55 +31,59 @@ describe Msgr::Dispatcher do
|
|
19
31
|
let(:config) { {max: 1} }
|
20
32
|
let(:consumer) { 'DispatcherTestConsumer' }
|
21
33
|
let(:route) do
|
22
|
-
|
34
|
+
instance_double('Msgr::Route').tap do |t|
|
23
35
|
allow(t).to receive(:consumer).and_return consumer
|
24
36
|
allow(t).to receive(:action).and_return 'index'
|
25
37
|
end
|
26
38
|
end
|
27
39
|
let(:channel) do
|
28
|
-
|
40
|
+
instance_double('Msgr::Channel').tap do |c|
|
29
41
|
allow(c).to receive(:ack)
|
30
42
|
end
|
31
43
|
end
|
32
44
|
let(:delivery_info) do
|
33
|
-
|
45
|
+
instance_double('Bunny::DeliveryInfo').tap do |ti|
|
34
46
|
allow(ti).to receive(:delivery_tag).and_return(3)
|
35
47
|
end
|
36
48
|
end
|
37
49
|
let(:payload) { {} }
|
38
50
|
let(:metadata) do
|
39
|
-
|
51
|
+
instance_double('Bunny::MessageProperties').tap do |metadata|
|
40
52
|
allow(metadata).to receive(:content_type).and_return('text/plain')
|
41
53
|
end
|
42
54
|
end
|
43
55
|
let(:message) { Msgr::Message.new channel, delivery_info, metadata, payload, route }
|
44
56
|
let(:action) { -> { dispatcher.call message } }
|
45
57
|
|
46
|
-
it '
|
47
|
-
|
48
|
-
|
58
|
+
it 'consumes message' do
|
59
|
+
expect do
|
60
|
+
dispatcher.call message
|
61
|
+
end.to change(DispatcherTestConsumer, :calls).by(1)
|
49
62
|
end
|
50
63
|
|
51
64
|
context 'with not acknowledged message' do
|
52
|
-
before { dispatcher.call message }
|
53
65
|
subject { message }
|
54
|
-
|
66
|
+
|
67
|
+
before { dispatcher.call message }
|
68
|
+
|
69
|
+
it { is_expected.to be_acked }
|
55
70
|
end
|
56
71
|
|
57
72
|
describe 'exception swallowing' do
|
58
73
|
let(:consumer) { 'DispatcherRaiseConsumer' }
|
74
|
+
|
59
75
|
before do
|
60
76
|
allow(message).to receive(:nack)
|
61
77
|
end
|
62
78
|
|
63
|
-
it '
|
79
|
+
it 'swallows exceptions by default' do
|
64
80
|
expect { dispatcher.call(message) }.not_to raise_error
|
65
81
|
end
|
66
82
|
|
67
83
|
context 'with raise_exceptions configuration option and a synchronous pool' do
|
68
84
|
let(:config) { super().merge(raise_exceptions: true) }
|
69
85
|
|
70
|
-
it '
|
86
|
+
it 'raises the exception' do
|
71
87
|
expect { dispatcher.call(message) }.to raise_error(ArgumentError)
|
72
88
|
end
|
73
89
|
end
|
@@ -6,139 +6,29 @@ describe Msgr::Railtie do
|
|
6
6
|
describe 'configuration options' do
|
7
7
|
let(:config) { Rails.configuration }
|
8
8
|
|
9
|
-
it '
|
9
|
+
it 'has `msgr` key' do
|
10
10
|
expect(config).to respond_to :msgr
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe '#parse_config' do
|
15
|
-
let(:settings) { {} }
|
16
|
-
let(:action) { described_class.parse_config settings }
|
17
|
-
subject { action }
|
18
|
-
|
19
|
-
context 'with incorrect settings' do
|
20
|
-
subject { -> { action } }
|
21
|
-
|
22
|
-
context 'with config without url' do
|
23
|
-
let(:settings) { {'test' => {hans: 'otto'}} }
|
24
|
-
|
25
|
-
it { should raise_error 'Could not load rabbitmq environment config: URI missing.' }
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'with invalid autostart value' do
|
29
|
-
let(:settings) { {'test' => {uri: 'hans', autostart: 'unvalid'}} }
|
30
|
-
|
31
|
-
it { should raise_error 'Invalid value for rabbitmq config autostart: "unvalid"' }
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'with invalid checkcredentials value' do
|
35
|
-
let(:settings) { {'test' => {uri: 'hans', checkcredentials: 'unvalid'}} }
|
36
|
-
|
37
|
-
it { should raise_error 'Invalid value for rabbitmq config checkcredentials: "unvalid"' }
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with invalid raise_exceptions value' do
|
41
|
-
let(:settings) { {'test' => {uri: 'franz', raise_exceptions: 'unvalid'}} }
|
42
|
-
|
43
|
-
it { should raise_error 'Invalid value for rabbitmq config raise_exceptions: "unvalid"' }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context 'without set routes file' do
|
48
|
-
let(:settings) { {'test' => {uri: 'test'}} }
|
49
|
-
|
50
|
-
context '[:routing_file]' do
|
51
|
-
subject { super()[:routing_file] }
|
52
|
-
it { should eq Rails.root.join('config/msgr.rb').to_s }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'with set routes file' do
|
57
|
-
let(:settings) { {'test' => {uri: 'test', 'routing_file' => 'my fancy file'}} }
|
58
|
-
|
59
|
-
context '[:routing_file]' do
|
60
|
-
subject { super()[:routing_file] }
|
61
|
-
it { should eq 'my fancy file' }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'with uri as symbol' do
|
66
|
-
let(:settings) { {'test' => {uri: 'hans'}} }
|
67
|
-
|
68
|
-
context '[:uri]' do
|
69
|
-
subject { super()[:uri] }
|
70
|
-
it { should eq 'hans' }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'with uri as string' do
|
75
|
-
let(:settings) { {'test' => {'uri' => 'hans'}} }
|
76
|
-
|
77
|
-
context '[:uri]' do
|
78
|
-
subject { super()[:uri] }
|
79
|
-
it { should eq 'hans' }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context 'without raise_exceptions config' do
|
84
|
-
let(:settings) { {'test' => {'uri' => 'hans'}, 'development' => {'uri' => 'hans_dev'}} }
|
85
|
-
|
86
|
-
describe '[:raise_exceptions]' do
|
87
|
-
subject { super()[:raise_exceptions] }
|
88
|
-
it { should eq false }
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
14
|
describe '#load' do
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
cfg
|
98
|
-
end
|
99
|
-
|
100
|
-
context 'with autostart is true' do
|
101
|
-
it 'should not start Msgr' do
|
102
|
-
expect(Msgr).to receive(:start)
|
103
|
-
expect(Msgr::Railtie).to receive(:load_config).and_return('test' => {uri: 'test', autostart: true})
|
104
|
-
Msgr::Railtie.load config
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context 'without autostart value' do
|
109
|
-
it 'should not start Msgr' do
|
110
|
-
expect(Msgr).to_not receive(:start)
|
111
|
-
expect(Msgr::Railtie).to receive(:load_config).and_return('test' => {uri: 'test'})
|
112
|
-
Msgr::Railtie.load config
|
113
|
-
end
|
15
|
+
before do
|
16
|
+
allow(Msgr).to receive(:start)
|
17
|
+
allow(Msgr.client).to receive(:connect)
|
114
18
|
end
|
115
19
|
|
116
20
|
context 'without checkcredentials value' do
|
117
|
-
it '
|
118
|
-
|
119
|
-
expect(Msgr
|
120
|
-
Msgr::Railtie.load config
|
21
|
+
it 'connects to rabbitmq directly to check credentials' do
|
22
|
+
described_class.load({})
|
23
|
+
expect(Msgr.client).to have_received(:connect)
|
121
24
|
end
|
122
25
|
end
|
123
26
|
|
124
27
|
context 'with checkcredentials is false' do
|
125
|
-
it '
|
126
|
-
|
127
|
-
expect(Msgr
|
128
|
-
Msgr::Railtie.load config
|
28
|
+
it 'connects to rabbitmq directly to check credentials' do
|
29
|
+
described_class.load({checkcredentials: false})
|
30
|
+
expect(Msgr.client).not_to have_received(:connect)
|
129
31
|
end
|
130
32
|
end
|
131
33
|
end
|
132
|
-
|
133
|
-
# describe '#load_config'
|
134
|
-
# let(:options) { {} }
|
135
|
-
|
136
|
-
# subject { Msgr::Railtie.load_config options }
|
137
|
-
|
138
|
-
# if Rails::Application.methods.include(:config_for)
|
139
|
-
# it 'should use config_for' do
|
140
|
-
|
141
|
-
# end
|
142
|
-
# end
|
143
|
-
# end
|
144
34
|
end
|
@@ -10,15 +10,14 @@ Coveralls.wear! do
|
|
10
10
|
add_filter 'spec'
|
11
11
|
end
|
12
12
|
|
13
|
-
#
|
14
13
|
ENV['RAILS_ENV'] ||= 'test'
|
15
14
|
ENV['RAILS_GROUPS'] = ['rails', ENV['RAILS_GROUPS']].reject(&:nil?).join(',')
|
16
|
-
require File.expand_path('
|
15
|
+
require File.expand_path('dummy/config/environment', __dir__)
|
17
16
|
require 'rspec/rails'
|
18
17
|
|
19
18
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
20
19
|
# in spec/support/ and its subdirectories.
|
21
|
-
Dir[File.expand_path('
|
20
|
+
Dir[File.expand_path('support/**/*.rb', __dir__)].sort.each {|f| require f }
|
22
21
|
|
23
22
|
# Checks for pending migrations before tests are run.
|
24
23
|
# If you are not using ActiveRecord, you can remove this line.
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Msgr::Client do
|
6
|
+
subject(:client) { described_class.new config }
|
7
|
+
|
8
|
+
let(:config) { {} }
|
9
|
+
|
10
|
+
describe '#uri' do
|
11
|
+
subject(:uri) { client.uri.to_s }
|
12
|
+
|
13
|
+
context 'with default config' do
|
14
|
+
it 'uses the default config' do
|
15
|
+
expect(uri).to eq 'amqp://127.0.0.1'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'without vhost' do
|
20
|
+
let(:config) { {uri: 'amqp://rabbit'} }
|
21
|
+
|
22
|
+
it 'does not specify a vhost' do
|
23
|
+
expect(uri).to eq 'amqp://rabbit'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with empty vhost' do
|
28
|
+
let(:config) { {uri: 'amqp://rabbit/'} }
|
29
|
+
|
30
|
+
it 'does not specify a vhost' do
|
31
|
+
expect(uri).to eq 'amqp://rabbit'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with explicit vhost' do
|
36
|
+
let(:config) { {uri: 'amqp://rabbit/some_vhost'} }
|
37
|
+
|
38
|
+
# This behavior is due to legacy parsing in Msgr's config.
|
39
|
+
# We interpret the entire path (incl. the leading slash)
|
40
|
+
# as vhost. As per AMQP rules, this means the leading slash
|
41
|
+
# is part of the vhost, which means it has to be URL encoded.
|
42
|
+
# This will likely change with the next major release.
|
43
|
+
it 'uses the entire path as vhost' do
|
44
|
+
expect(uri).to eq 'amqp://rabbit/%2Fsome_vhost'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with URI and vhost' do
|
49
|
+
let(:config) { {uri: 'amqp://rabbit/some_vhost', vhost: 'real_vhost'} }
|
50
|
+
|
51
|
+
# This is currently the only way to specify a vhost without
|
52
|
+
# leading slash (as a vhost in the :uri config would have
|
53
|
+
# an extra URL encoded leading slash).
|
54
|
+
it 'uses the explicit vhost' do
|
55
|
+
expect(uri).to eq 'amqp://rabbit/real_vhost'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'drain' do
|
61
|
+
subject(:drain) { client.drain }
|
62
|
+
|
63
|
+
let(:config) { {routing_file: 'spec/fixtures/msgr_routes_test_drain.rb'} }
|
64
|
+
let(:channel_stub) { instance_double('Msgr::Channel', prefetch: true) }
|
65
|
+
let(:queue_stub) { instance_double('Bunny::Queue', purge: true) }
|
66
|
+
|
67
|
+
before do
|
68
|
+
allow(Msgr::Channel).to receive(:new).and_return(channel_stub)
|
69
|
+
allow(channel_stub).to receive(:queue).and_return(queue_stub).at_most(3).times
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'requests purges for all configured routes' do
|
73
|
+
drain
|
74
|
+
|
75
|
+
expect(Msgr::Channel).to have_received(:new).exactly(3).times
|
76
|
+
expect(channel_stub).to have_received(:queue).with('msgr.consumer.Consumer1Consumer.action1', passive: true).once
|
77
|
+
expect(channel_stub).to have_received(:queue).with('msgr.consumer.Consumer1Consumer.action2', passive: true).once
|
78
|
+
expect(channel_stub).to have_received(:queue).with('msgr.consumer.Consumer2Consumer.action1', passive: true).once
|
79
|
+
|
80
|
+
expect(queue_stub).to have_received(:purge).exactly(3).times
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -6,7 +6,7 @@ describe Msgr::Connection do
|
|
6
6
|
describe '#rebind' do
|
7
7
|
let(:conn) { double }
|
8
8
|
let(:routes) { Msgr::Routes.new }
|
9
|
-
let(:connection) {
|
9
|
+
let(:connection) { described_class.new conn, routes, dispatcher }
|
10
10
|
|
11
11
|
pending 'some tests missing -> only lets written'
|
12
12
|
end
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class MsgrAutoAckConsumer < Msgr::Consumer
|
6
|
+
self.auto_ack = true
|
7
|
+
|
8
|
+
def index; end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MsgrManualAckConsumer < Msgr::Consumer
|
12
|
+
self.auto_ack = false
|
13
|
+
|
14
|
+
def index; end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Msgr::Dispatcher do
|
18
|
+
subject { dispatcher }
|
19
|
+
|
20
|
+
let(:config) { {} }
|
21
|
+
let(:args) { [config] }
|
22
|
+
let(:dispatcher) { described_class.new(*args) }
|
23
|
+
|
24
|
+
describe 'dispatch' do
|
25
|
+
it 'acks messages automatically if auto_ack is enabled' do
|
26
|
+
route_db = instance_double('Msgr::Route', consumer: 'MsgrAutoAckConsumer', action: :index)
|
27
|
+
msg_db = instance_spy('Msgr::Message', route: route_db, acked?: false)
|
28
|
+
|
29
|
+
dispatcher.dispatch(msg_db)
|
30
|
+
|
31
|
+
expect(msg_db).to have_received(:ack)
|
32
|
+
expect(msg_db).not_to have_received(:nack)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'does not ack messages if auto_ack is disabled' do
|
36
|
+
route_db = instance_double('Msgr::Route', consumer: 'MsgrManualAckConsumer', action: :index)
|
37
|
+
msg_db = instance_spy('Msgr::Message', route: route_db, acked?: false)
|
38
|
+
|
39
|
+
dispatcher.dispatch(msg_db)
|
40
|
+
|
41
|
+
expect(msg_db).not_to have_received(:ack)
|
42
|
+
expect(msg_db).not_to have_received(:nack)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -3,61 +3,76 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Msgr::Route do
|
6
|
+
subject { route }
|
7
|
+
|
6
8
|
let(:routing_key) { 'routing.key.#' }
|
7
9
|
let(:options) { {to: 'test#index'} }
|
8
10
|
let(:args) { [routing_key, options] }
|
9
|
-
let(:route) {
|
10
|
-
subject { route }
|
11
|
+
let(:route) { described_class.new(*args) }
|
11
12
|
|
12
13
|
describe '#initialize' do
|
13
|
-
it '
|
14
|
+
it 'requires `to` option' do
|
14
15
|
expect do
|
15
|
-
|
16
|
+
described_class.new(routing_key, {})
|
16
17
|
end.to raise_error(ArgumentError)
|
17
18
|
end
|
18
19
|
|
19
|
-
it '
|
20
|
+
it 'requires routing_key' do
|
20
21
|
expect do
|
21
|
-
|
22
|
+
described_class.new nil, options
|
22
23
|
end.to raise_error(ArgumentError)
|
23
24
|
end
|
24
25
|
|
25
|
-
it '
|
26
|
+
it 'requires not empty routing_key' do
|
26
27
|
expect do
|
27
|
-
|
28
|
+
described_class.new '', options
|
28
29
|
end.to raise_error ArgumentError, /routing key required/i
|
29
30
|
end
|
30
31
|
|
31
|
-
it '
|
32
|
+
it 'requires `to: "consumer#action` format' do
|
32
33
|
expect do
|
33
|
-
|
34
|
+
described_class.new routing_key, to: 'abc'
|
34
35
|
end.to raise_error ArgumentError, /invalid consumer format/i
|
35
36
|
end
|
37
|
+
|
38
|
+
it 'allows namespaces in consumer' do
|
39
|
+
expect do
|
40
|
+
described_class.new routing_key, to: 'abc/def#ghi'
|
41
|
+
end.not_to raise_error
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
45
|
describe '#consumer' do
|
39
|
-
it '
|
46
|
+
it 'returns consumer class name' do
|
40
47
|
expect(route.consumer).to eq 'TestConsumer'
|
41
48
|
end
|
42
49
|
|
43
50
|
context 'with underscore consumer name' do
|
44
51
|
let(:options) { super().merge to: 'test_resource_foo#index' }
|
45
52
|
|
46
|
-
it '
|
53
|
+
it 'returns camelized class name' do
|
47
54
|
expect(route.consumer).to eq 'TestResourceFooConsumer'
|
48
55
|
end
|
49
56
|
end
|
57
|
+
|
58
|
+
context 'with nested namespace in consumer name' do
|
59
|
+
let(:options) { super().merge to: 'nested/namespace/foo#index' }
|
60
|
+
|
61
|
+
it 'returns fully classified, classified class name' do
|
62
|
+
expect(route.consumer).to eq 'Nested::Namespace::FooConsumer'
|
63
|
+
end
|
64
|
+
end
|
50
65
|
end
|
51
66
|
|
52
67
|
describe '#action' do
|
53
|
-
it '
|
68
|
+
it 'returns action method name' do
|
54
69
|
expect(route.action).to eq 'index'
|
55
70
|
end
|
56
71
|
|
57
72
|
context 'with camelCase action name' do
|
58
73
|
let(:options) { super().merge to: 'test#myActionMethod' }
|
59
74
|
|
60
|
-
it '
|
75
|
+
it 'returns underscore method name' do
|
61
76
|
expect(route.action).to eq 'my_action_method'
|
62
77
|
end
|
63
78
|
end
|