adhearsion 2.5.4 → 2.6.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +15 -0
  4. data/README.markdown +2 -1
  5. data/Rakefile +1 -6
  6. data/adhearsion.gemspec +4 -3
  7. data/features/cli_daemon.feature +2 -4
  8. data/features/cli_restart.feature +14 -5
  9. data/features/cli_start.feature +0 -2
  10. data/features/cli_stop.feature +15 -6
  11. data/lib/adhearsion.rb +21 -23
  12. data/lib/adhearsion/call.rb +49 -5
  13. data/lib/adhearsion/call_controller.rb +29 -11
  14. data/lib/adhearsion/call_controller/dial.rb +21 -9
  15. data/lib/adhearsion/call_controller/menu_dsl.rb +12 -12
  16. data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +1 -1
  17. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +1 -0
  18. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +1 -1
  19. data/lib/adhearsion/call_controller/output.rb +36 -7
  20. data/lib/adhearsion/call_controller/output/abstract_player.rb +4 -0
  21. data/lib/adhearsion/call_controller/record.rb +1 -0
  22. data/lib/adhearsion/cli_commands/ahn_command.rb +7 -4
  23. data/lib/adhearsion/cli_commands/plugin_command.rb +2 -0
  24. data/lib/adhearsion/generators.rb +2 -4
  25. data/lib/adhearsion/generators/app/templates/simon_game_spec.rb +20 -20
  26. data/lib/adhearsion/initializer.rb +2 -2
  27. data/lib/adhearsion/plugin.rb +6 -6
  28. data/lib/adhearsion/punchblock_plugin.rb +3 -4
  29. data/lib/adhearsion/punchblock_plugin/initializer.rb +2 -1
  30. data/lib/adhearsion/router.rb +7 -7
  31. data/lib/adhearsion/router/route.rb +10 -4
  32. data/lib/adhearsion/rspec.rb +2 -0
  33. data/lib/adhearsion/version.rb +1 -1
  34. data/spec/adhearsion/call_controller/dial_spec.rb +589 -557
  35. data/spec/adhearsion/call_controller/input_spec.rb +91 -91
  36. data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +29 -29
  37. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +6 -6
  38. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +19 -19
  39. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +6 -6
  40. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +1 -1
  41. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +21 -17
  42. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +96 -83
  43. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +5 -5
  44. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +9 -9
  45. data/spec/adhearsion/call_controller/output/async_player_spec.rb +14 -4
  46. data/spec/adhearsion/call_controller/output/formatter_spec.rb +14 -14
  47. data/spec/adhearsion/call_controller/output/player_spec.rb +15 -5
  48. data/spec/adhearsion/call_controller/output_spec.rb +126 -78
  49. data/spec/adhearsion/call_controller/record_spec.rb +38 -26
  50. data/spec/adhearsion/call_controller/utility_spec.rb +11 -11
  51. data/spec/adhearsion/call_controller_spec.rb +176 -136
  52. data/spec/adhearsion/call_spec.rb +443 -218
  53. data/spec/adhearsion/calls_spec.rb +33 -33
  54. data/spec/adhearsion/configuration_spec.rb +61 -61
  55. data/spec/adhearsion/console_spec.rb +29 -29
  56. data/spec/adhearsion/events_spec.rb +14 -14
  57. data/spec/adhearsion/generators_spec.rb +1 -1
  58. data/spec/adhearsion/initializer_spec.rb +42 -42
  59. data/spec/adhearsion/logging_spec.rb +33 -33
  60. data/spec/adhearsion/outbound_call_spec.rb +69 -55
  61. data/spec/adhearsion/plugin_spec.rb +53 -44
  62. data/spec/adhearsion/process_spec.rb +21 -21
  63. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +68 -52
  64. data/spec/adhearsion/punchblock_plugin_spec.rb +6 -6
  65. data/spec/adhearsion/router/evented_route_spec.rb +2 -2
  66. data/spec/adhearsion/router/openended_route_spec.rb +9 -9
  67. data/spec/adhearsion/router/route_spec.rb +61 -31
  68. data/spec/adhearsion/router/unaccepting_route_spec.rb +13 -13
  69. data/spec/adhearsion/router_spec.rb +47 -33
  70. data/spec/adhearsion/statistics/dump_spec.rb +6 -6
  71. data/spec/adhearsion/statistics_spec.rb +9 -9
  72. data/spec/adhearsion_spec.rb +23 -20
  73. data/spec/spec_helper.rb +3 -6
  74. data/spec/support/call_controller_test_helpers.rb +7 -7
  75. data/spec/support/initializer_stubs.rb +1 -1
  76. data/spec/support/punchblock_mocks.rb +1 -1
  77. metadata +22 -10
  78. data/features/support/utils.rb +0 -9
@@ -42,7 +42,10 @@ module Adhearsion
42
42
 
43
43
  subject { Recorder.new controller, options }
44
44
 
45
- its(:record_component) { should == component }
45
+ describe '#record_component' do
46
+ subject { super().record_component }
47
+ it { is_expected.to eq(component) }
48
+ end
46
49
 
47
50
  context "when passing time related options" do
48
51
  let :component_options do
@@ -56,7 +59,7 @@ module Adhearsion
56
59
  end
57
60
 
58
61
  it "takes seconds but sets milliseconds on the command" do
59
- subject.record_component.should == component
62
+ expect(subject.record_component).to eq(component)
60
63
  end
61
64
  end
62
65
 
@@ -78,11 +81,14 @@ module Adhearsion
78
81
  end
79
82
 
80
83
  context "with :interruptible => false" do
81
- its(:stopper_component) { should be_nil }
84
+ describe '#stopper_component' do
85
+ subject { super().stopper_component }
86
+ it { is_expected.to be_nil }
87
+ end
82
88
 
83
89
  it "does not use an Input component" do
84
- controller.should_receive(:execute_component_and_await_completion).once.with(component)
85
- controller.should_receive(:write_and_await_response).never.with(input_component)
90
+ expect(controller).to receive(:execute_component_and_await_completion).once.with(component)
91
+ expect(controller).to receive(:write_and_await_response).never.with(input_component)
86
92
  subject.run
87
93
  end
88
94
  end
@@ -90,7 +96,10 @@ module Adhearsion
90
96
  context "with :interruptible => true" do
91
97
  let(:interruptible) { true }
92
98
 
93
- its(:stopper_component) { should == input_component }
99
+ describe '#stopper_component' do
100
+ subject { super().stopper_component }
101
+ it { is_expected.to eq(input_component) }
102
+ end
94
103
 
95
104
  describe "when the input component completes" do
96
105
  let(:complete_event) { Punchblock::Event::Complete.new }
@@ -101,16 +110,16 @@ module Adhearsion
101
110
  end
102
111
 
103
112
  it "stops the recording" do
104
- subject.record_component.should_receive(:stop!).once
113
+ expect(subject.record_component).to receive(:stop!).once
105
114
  subject.stopper_component.trigger_event_handler complete_event
106
115
  end
107
116
  end
108
117
 
109
118
  describe "when the recording completes" do
110
119
  it "stops the input component" do
111
- controller.should_receive(:execute_component_and_await_completion).once.with(component)
112
- controller.should_receive(:write_and_await_response).once.with(input_component)
113
- subject.stopper_component.should_receive(:stop!).once
120
+ expect(controller).to receive(:execute_component_and_await_completion).once.with(component)
121
+ expect(controller).to receive(:write_and_await_response).once.with(input_component)
122
+ expect(subject.stopper_component).to receive(:stop!).once
114
123
  subject.run
115
124
  end
116
125
  end
@@ -132,7 +141,10 @@ module Adhearsion
132
141
  end
133
142
  end
134
143
 
135
- its(:stopper_component) { should == input_component }
144
+ describe '#stopper_component' do
145
+ subject { super().stopper_component }
146
+ it { is_expected.to eq(input_component) }
147
+ end
136
148
  end
137
149
 
138
150
  describe "setting completion handlers" do
@@ -140,7 +152,7 @@ module Adhearsion
140
152
 
141
153
  it "should execute those handlers when recording completes" do
142
154
  foo = double 'foo'
143
- foo.should_receive(:call).once.with kind_of(Punchblock::Event::Complete)
155
+ expect(foo).to receive(:call).once.with kind_of(Punchblock::Event::Complete)
144
156
  subject.handle_record_completion { |e| foo.call e }
145
157
  subject.record_component.trigger_event_handler complete_event
146
158
  end
@@ -164,7 +176,7 @@ module Adhearsion
164
176
  describe "with :async => true and an :on_complete callback" do
165
177
  before do
166
178
  component
167
- Punchblock::Component::Record.should_receive(:new).once.with(parsed_options).and_return component
179
+ expect(Punchblock::Component::Record).to receive(:new).once.with(parsed_options).and_return component
168
180
  expect_message_waiting_for_response component
169
181
  @rec = Queue.new
170
182
  subject.record(options.merge(async: true)) { |rec| @rec.push rec }
@@ -175,7 +187,7 @@ module Adhearsion
175
187
  it "should execute the callback" do
176
188
  component.trigger_event_handler response
177
189
  Timeout::timeout 5 do
178
- @rec.pop.should be response
190
+ expect(@rec.pop).to be response
179
191
  end
180
192
  end
181
193
  end
@@ -184,14 +196,14 @@ module Adhearsion
184
196
  before do
185
197
  TestException = Class.new StandardError
186
198
  component
187
- Punchblock::Component::Record.should_receive(:new).once.with({}).and_return component
199
+ expect(Punchblock::Component::Record).to receive(:new).once.with({}).and_return component
188
200
  end
189
201
 
190
202
  it "should pass the exception to the events system" do
191
203
  latch = CountDownLatch.new 1
192
204
  Adhearsion::Events.exception do |e, l|
193
- e.should be_a TestException
194
- l.should be subject.logger
205
+ expect(e).to be_a TestException
206
+ expect(l).to be subject.logger
195
207
  latch.countdown!
196
208
  end
197
209
  expect_component_execution component
@@ -199,7 +211,7 @@ module Adhearsion
199
211
  component.request!
200
212
  component.execute!
201
213
  component.trigger_event_handler response
202
- latch.wait(1).should be true
214
+ expect(latch.wait(1)).to be true
203
215
  Adhearsion::Events.clear_handlers :exception
204
216
  end
205
217
  end
@@ -207,7 +219,7 @@ module Adhearsion
207
219
  describe "with :async => false" do
208
220
  before do
209
221
  component
210
- Punchblock::Component::Record.should_receive(:new).once.with(parsed_options).and_return component
222
+ expect(Punchblock::Component::Record).to receive(:new).once.with(parsed_options).and_return component
211
223
  expect_component_execution component
212
224
  @rec = Queue.new
213
225
  subject.record(options.merge(:async => false)) { |rec| @rec.push rec }
@@ -218,7 +230,7 @@ module Adhearsion
218
230
  it 'should execute a passed block' do
219
231
  component.trigger_event_handler response
220
232
  Timeout::timeout 5 do
221
- @rec.pop.should be == response
233
+ expect(@rec.pop).to eq(response)
222
234
  end
223
235
  end
224
236
  end
@@ -226,8 +238,8 @@ module Adhearsion
226
238
  describe "with :interruptible => false" do
227
239
  let(:input_component) { Punchblock::Component::Input.new }
228
240
  it "does not use an Input component" do
229
- subject.should_receive(:execute_component_and_await_completion).once.with(component)
230
- subject.should_receive(:write_and_await_response).never.with(input_component)
241
+ expect(subject).to receive(:execute_component_and_await_completion).once.with(component)
242
+ expect(subject).to receive(:write_and_await_response).never.with(input_component)
231
243
  subject.record(options.merge(:async => false, :interruptible => false)) { |rec| @rec.push rec }
232
244
  end
233
245
  end
@@ -240,8 +252,8 @@ module Adhearsion
240
252
 
241
253
  expect_input_component_complete_event 'dtmf-5'
242
254
 
243
- Punchblock::Component::Record.any_instance.should_receive(:stop!)
244
- subject.should_receive(:execute_component_and_await_completion).once.with(component)
255
+ expect_any_instance_of(Punchblock::Component::Record).to receive(:stop!)
256
+ expect(subject).to receive(:execute_component_and_await_completion).once.with(component)
245
257
  subject.record(options.merge(:async => false, :interruptible => true)) { |rec| @rec.push rec }
246
258
  end
247
259
 
@@ -250,9 +262,9 @@ module Adhearsion
250
262
  describe "check for the return value" do
251
263
  it "returns a Record component" do
252
264
  component
253
- Punchblock::Component::Record.should_receive(:new).once.with(parsed_options).and_return component
265
+ expect(Punchblock::Component::Record).to receive(:new).once.with(parsed_options).and_return component
254
266
  expect_component_execution component
255
- subject.record(options.merge(:async => false)).should be == component
267
+ expect(subject.record(options.merge(:async => false))).to eq(component)
256
268
  component.request!
257
269
  component.execute!
258
270
  end
@@ -22,7 +22,7 @@ module Adhearsion
22
22
  }
23
23
 
24
24
  it 'generates the correct GRXML grammar' do
25
- subject.grammar_digits(2).to_s.should be == grxml.to_s
25
+ expect(subject.grammar_digits(2).to_s).to eq(grxml.to_s)
26
26
  end
27
27
 
28
28
  end # describe #grammar_digits
@@ -40,48 +40,48 @@ module Adhearsion
40
40
  }
41
41
 
42
42
  it 'generates the correct GRXML grammar' do
43
- subject.grammar_accept('35').to_s.should be == grxml.to_s
43
+ expect(subject.grammar_accept('35').to_s).to eq(grxml.to_s)
44
44
  end
45
45
 
46
46
  it 'filters meaningless characters out' do
47
- subject.grammar_accept('3+5').to_s.should be == grxml.to_s
47
+ expect(subject.grammar_accept('3+5').to_s).to eq(grxml.to_s)
48
48
  end
49
49
  end # grammar_accept
50
50
 
51
51
  describe "#parse_dtmf" do
52
52
  context "with a single digit" do
53
53
  it "correctly returns the parsed input" do
54
- subject.parse_dtmf("dtmf-3").should be == '3'
54
+ expect(subject.parse_dtmf("dtmf-3")).to eq('3')
55
55
  end
56
56
 
57
57
  it "correctly returns star as *" do
58
- subject.parse_dtmf("dtmf-star").should be == '*'
58
+ expect(subject.parse_dtmf("dtmf-star")).to eq('*')
59
59
  end
60
60
 
61
61
  it "correctly returns * as *" do
62
- subject.parse_dtmf("*").should be == '*'
62
+ expect(subject.parse_dtmf("*")).to eq('*')
63
63
  end
64
64
 
65
65
  it "correctly returns pound as #" do
66
- subject.parse_dtmf("dtmf-pound").should be == '#'
66
+ expect(subject.parse_dtmf("dtmf-pound")).to eq('#')
67
67
  end
68
68
 
69
69
  it "correctly returns # as #" do
70
- subject.parse_dtmf("#").should be == '#'
70
+ expect(subject.parse_dtmf("#")).to eq('#')
71
71
  end
72
72
 
73
73
  it "correctly parses digits without the dtmf- prefix" do
74
- subject.parse_dtmf('1').should be == '1'
74
+ expect(subject.parse_dtmf('1')).to eq('1')
75
75
  end
76
76
 
77
77
  it "correctly returns nil when input is nil" do
78
- subject.parse_dtmf(nil).should be == nil
78
+ expect(subject.parse_dtmf(nil)).to eq(nil)
79
79
  end
80
80
  end
81
81
 
82
82
  context "with multiple digits separated by spaces" do
83
83
  it "returns the digits without space separation" do
84
- subject.parse_dtmf('1 dtmf-5 dtmf-star # 2').should be == '15*#2'
84
+ expect(subject.parse_dtmf('1 dtmf-5 dtmf-star # 2')).to eq('15*#2')
85
85
  end
86
86
  end
87
87
  end # describe #grammar_accept
@@ -11,26 +11,40 @@ module Adhearsion
11
11
 
12
12
  let(:call) { Adhearsion::Call.new mock_offer(nil, :x_foo => 'bar') }
13
13
 
14
- its(:call) { should be call }
15
- its(:metadata) { should be == {:doo => :dah} }
14
+ describe '#call' do
15
+ subject { super().call }
16
+ it { is_expected.to be call }
17
+ end
18
+
19
+ describe '#metadata' do
20
+ subject { super().metadata }
21
+ it { is_expected.to eq({:doo => :dah}) }
22
+ end
16
23
 
17
24
  describe "setting meta-data" do
18
25
  it "should preserve data correctly" do
19
- subject[:foo].should be nil
26
+ expect(subject[:foo]).to be nil
20
27
  subject[:foo] = 7
21
- subject[:foo].should be == 7
28
+ expect(subject[:foo]).to eq(7)
22
29
  subject[:bar] = 10
23
- subject[:bar].should be == 10
24
- subject[:foo].should be == 7
30
+ expect(subject[:bar]).to eq(10)
31
+ expect(subject[:foo]).to eq(7)
25
32
  end
26
33
  end
27
34
 
28
- its(:logger) { should be call.logger }
29
- its(:variables) { should be call.variables }
35
+ describe '#logger' do
36
+ subject { super().logger }
37
+ it { is_expected.to be call.logger }
38
+ end
39
+
40
+ describe '#variables' do
41
+ subject { super().variables }
42
+ it { is_expected.to be call.variables }
43
+ end
30
44
 
31
45
  describe "#send_message" do
32
46
  it 'should send a message' do
33
- call.should_receive(:send_message).with("Hello World!").once
47
+ expect(call).to receive(:send_message).with("Hello World!").once
34
48
  subject.send_message "Hello World!"
35
49
  end
36
50
  end
@@ -39,46 +53,44 @@ module Adhearsion
39
53
  before { call.terminate }
40
54
 
41
55
  it "should use an unnamed logger" do
42
- subject.logger.should be_a ::Logging::Logger
43
- subject.logger.name.should == "Adhearsion::CallController"
56
+ expect(subject.logger).to be_a ::Logging::Logger
57
+ expect(subject.logger.name).to eq("Adhearsion::CallController")
44
58
  end
45
59
  end
46
60
 
47
61
  describe "execution on a call" do
48
62
  before do
49
- subject.stub :execute_component_and_await_completion => nil
50
- call.wrapped_object.stub :write_and_await_response => nil
63
+ allow(subject).to receive_messages :execute_component_and_await_completion => nil
64
+ allow(call.wrapped_object).to receive_messages :write_and_await_response => nil
51
65
  end
52
66
 
53
67
  it "catches Hangup exceptions and logs the hangup" do
54
- subject.should_receive(:run).once.ordered.and_raise(Call::Hangup)
55
- subject.logger.should_receive(:info).once.with(/Call was hung up/).ordered
56
- subject.execute!
68
+ expect(subject).to receive(:run).once.ordered.and_raise(Call::Hangup)
69
+ subject.exec
57
70
  end
58
71
 
59
72
  context "when trying to execute a command against a dead call" do
60
73
  before do
61
- subject.should_receive(:run).once.ordered.and_raise(Call::ExpiredError)
74
+ expect(subject).to receive(:run).once.ordered.and_raise(Call::ExpiredError)
62
75
  end
63
76
 
64
77
  it "gracefully terminates " do
65
- subject.logger.should_receive(:info).once.with(/Call was hung up/).ordered
66
- subject.execute!
78
+ subject.exec
67
79
  end
68
80
  end
69
81
 
70
82
  it "catches standard errors, triggering an exception event" do
71
- subject.should_receive(:run).once.ordered.and_raise(StandardError)
83
+ expect(subject).to receive(:run).once.ordered.and_raise(StandardError)
72
84
  latch = CountDownLatch.new 1
73
85
  ex = lo = nil
74
86
  Events.exception do |e, l|
75
87
  ex, lo = e, l
76
88
  latch.countdown!
77
89
  end
78
- subject.execute!
79
- latch.wait(1).should be true
80
- ex.should be_a StandardError
81
- lo.should be subject.logger
90
+ expect { subject.exec }.to raise_error
91
+ expect(latch.wait(1)).to be true
92
+ expect(ex).to be_a StandardError
93
+ expect(lo).to be subject.logger
82
94
  end
83
95
 
84
96
  context "when a block is specified" do
@@ -88,16 +100,19 @@ module Adhearsion
88
100
  Proc.new { foo value }
89
101
  end
90
102
 
91
- its(:block) { should be block }
103
+ describe '#block' do
104
+ subject { super().block }
105
+ it { is_expected.to be block }
106
+ end
92
107
 
93
108
  it "should execute the block in the context of the controller" do
94
- subject.stub :value => :bar
95
- subject.should_receive(:foo).once.with(:bar)
109
+ allow(subject).to receive_messages :value => :bar
110
+ expect(subject).to receive(:foo).once.with(:bar)
96
111
  subject.run
97
112
  end
98
113
 
99
114
  it "should make the block's context available" do
100
- subject.should_receive(:foo).once.with(:bar)
115
+ expect(subject).to receive(:foo).once.with(:bar)
101
116
  subject.run
102
117
  end
103
118
  end
@@ -146,39 +161,39 @@ module Adhearsion
146
161
  subject { InvokeController.new call }
147
162
 
148
163
  before do
149
- subject.stub :execute_component_and_await_completion => nil
150
- call.wrapped_object.stub :write_and_await_response => nil
151
- call.stub :register_controller => nil
152
- Events.should_receive(:trigger).with(:exception, Exception).never
164
+ allow(subject).to receive_messages :execute_component_and_await_completion => nil
165
+ allow(call.wrapped_object).to receive_messages :write_and_await_response => nil
166
+ allow(call).to receive_messages :register_controller => nil
167
+ expect(Events).to receive(:trigger).with(:exception, Exception).never
153
168
  end
154
169
 
155
170
  it "should invoke another controller before returning to the current controller" do
156
- subject.should_receive(:before).once.ordered
157
- call.should_receive(:answer).once.ordered
158
- subject.should_receive(:after).once.ordered
171
+ expect(subject).to receive(:before).once.ordered
172
+ expect(call).to receive(:answer).once.ordered
173
+ expect(subject).to receive(:after).once.ordered
159
174
 
160
- subject.execute!
175
+ subject.exec
161
176
  end
162
177
 
163
178
  it "should return the outer controller's run method return value" do
164
- SecondController.any_instance.should_receive(:run).once.and_return(:run_result)
165
- subject.execute!
166
- subject.metadata[:invoke_result].should be == :run_result
179
+ expect_any_instance_of(SecondController).to receive(:run).once.and_return(:run_result)
180
+ subject.exec
181
+ expect(subject.metadata[:invoke_result]).to eq(:run_result)
167
182
  end
168
183
 
169
184
  it "should invoke the new controller with metadata" do
170
- SecondController.any_instance.should_receive(:md_check).once.with :foo => 'bar'
171
- subject.execute!
185
+ expect_any_instance_of(SecondController).to receive(:md_check).once.with :foo => 'bar'
186
+ subject.exec
172
187
  end
173
188
 
174
189
  it "should allow the outer controller to cease execution and handle remote hangups" do
175
190
  subject[:second_controller] = SecondControllerWithRemoteHangup
176
191
 
177
- subject.should_receive(:before).once.ordered
178
- call.should_receive(:answer).once.ordered
179
- subject.should_receive(:after).never.ordered
192
+ expect(subject).to receive(:before).once.ordered
193
+ expect(call).to receive(:answer).once.ordered
194
+ expect(subject).to receive(:after).never.ordered
180
195
 
181
- subject.execute!
196
+ subject.exec
182
197
  end
183
198
  end
184
199
 
@@ -207,25 +222,25 @@ module Adhearsion
207
222
  subject { pass_controller.new call }
208
223
 
209
224
  before do
210
- call.wrapped_object.stub :write_and_await_response => nil
211
- call.stub :register_controller => nil
212
- subject.stub :execute_component_and_await_completion => nil
213
- SecondController.any_instance.should_receive(:md_check).once.with :foo => 'bar'
214
- Events.should_receive(:trigger).with(:exception, Exception).never
225
+ allow(call.wrapped_object).to receive_messages :write_and_await_response => nil
226
+ allow(call).to receive_messages :register_controller => nil
227
+ allow(subject).to receive_messages :execute_component_and_await_completion => nil
228
+ expect_any_instance_of(SecondController).to receive(:md_check).once.with :foo => 'bar'
229
+ expect(Events).to receive(:trigger).with(:exception, Exception).never
215
230
  end
216
231
 
217
232
  it "should cease execution of the current controller, and instruct the call to execute another" do
218
- subject.should_receive(:before).once.ordered
219
- call.should_receive(:answer).once.ordered
220
- subject.should_receive(:after).never.ordered
233
+ expect(subject).to receive(:before).once.ordered
234
+ expect(call).to receive(:answer).once.ordered
235
+ expect(subject).to receive(:after).never.ordered
221
236
 
222
237
  subject.exec
223
238
  end
224
239
 
225
240
  it "should execute after_call callbacks before passing control" do
226
- subject.should_receive(:before).once.ordered
227
- subject.should_receive(:foobar).once.ordered
228
- call.should_receive(:answer).once.ordered
241
+ expect(subject).to receive(:before).once.ordered
242
+ expect(subject).to receive(:foobar).once.ordered
243
+ expect(call).to receive(:answer).once.ordered
229
244
 
230
245
  subject.exec
231
246
  end
@@ -243,17 +258,17 @@ module Adhearsion
243
258
  subject { pass_controller.new call }
244
259
 
245
260
  before do
246
- call.wrapped_object.stub(:write_and_await_response).and_return do |command|
261
+ allow(call.wrapped_object).to receive(:write_and_await_response) do |command|
247
262
  command.request!
248
263
  command.execute!
249
264
  end
250
- call.stub register_controller: nil
251
- SecondController.any_instance.should_receive(:md_check).once.with :foo => 'bar'
252
- Events.should_receive(:trigger).with(:exception, Exception).never
265
+ allow(call).to receive_messages register_controller: nil
266
+ expect_any_instance_of(SecondController).to receive(:md_check).once.with :foo => 'bar'
267
+ expect(Events).to receive(:trigger).with(:exception, Exception).never
253
268
  end
254
269
 
255
270
  it "should cease execution of the current controller, and instruct the call to execute another" do
256
- call.should_receive(:answer).once.ordered
271
+ expect(call).to receive(:answer).once.ordered
257
272
 
258
273
  subject.exec
259
274
  end
@@ -278,17 +293,17 @@ module Adhearsion
278
293
 
279
294
  context "but not yet received a complete event" do
280
295
  it "should terminate the components" do
281
- subject.output1.should_receive(:stop!).once
282
- subject.output2.should_receive(:stop!).once
296
+ expect(subject.output1).to receive(:stop!).once
297
+ expect(subject.output2).to receive(:stop!).once
283
298
 
284
299
  subject.exec
285
300
  end
286
301
 
287
302
  context "and some fail to terminate" do
288
- before { subject.output1.should_receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
303
+ before { expect(subject.output1).to receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
289
304
 
290
305
  it "should terminate the others" do
291
- subject.output2.should_receive(:stop!).once
306
+ expect(subject.output2).to receive(:stop!).once
292
307
  subject.exec
293
308
  end
294
309
  end
@@ -298,8 +313,8 @@ module Adhearsion
298
313
  before { subject.output1.trigger_event_handler Punchblock::Event::Complete.new }
299
314
 
300
315
  it "should not terminate the completed components" do
301
- subject.output1.should_receive(:stop!).never
302
- subject.output2.should_receive(:stop!).once
316
+ expect(subject.output1).to receive(:stop!).never
317
+ expect(subject.output2).to receive(:stop!).once
303
318
 
304
319
  subject.exec
305
320
  end
@@ -327,28 +342,28 @@ module Adhearsion
327
342
 
328
343
  context "when components have been executed on the controller" do
329
344
  before do
330
- call.wrapped_object.stub(:write_and_await_response).and_return do |command|
345
+ allow(call.wrapped_object).to receive(:write_and_await_response) do |command|
331
346
  command.request!
332
347
  command.execute!
333
348
  end
334
- call.stub register_controller: nil
335
- Events.should_receive(:trigger).with(:exception, Exception).never
349
+ allow(call).to receive_messages register_controller: nil
350
+ expect(Events).to receive(:trigger).with(:exception, Exception).never
336
351
  subject.prep_output
337
352
  end
338
353
 
339
354
  context "when they have not yet received a complete event" do
340
355
  it "should terminate the components" do
341
- subject.output1.should_receive(:stop!).once
342
- subject.output2.should_receive(:stop!).once
356
+ expect(subject.output1).to receive(:stop!).once
357
+ expect(subject.output2).to receive(:stop!).once
343
358
 
344
359
  subject.exec
345
360
  end
346
361
 
347
362
  context "and some fail to terminate" do
348
- before { subject.output1.should_receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
363
+ before { expect(subject.output1).to receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
349
364
 
350
365
  it "should terminate the others" do
351
- subject.output2.should_receive(:stop!).once
366
+ expect(subject.output2).to receive(:stop!).once
352
367
  subject.exec
353
368
  end
354
369
  end
@@ -358,8 +373,8 @@ module Adhearsion
358
373
  before { subject.output1.trigger_event_handler Punchblock::Event::Complete.new }
359
374
 
360
375
  it "should not terminate the completed components" do
361
- subject.output1.should_receive(:stop!).never
362
- subject.output2.should_receive(:stop!).once
376
+ expect(subject.output1).to receive(:stop!).never
377
+ expect(subject.output2).to receive(:stop!).once
363
378
 
364
379
  subject.exec
365
380
  end
@@ -371,10 +386,21 @@ module Adhearsion
371
386
  let(:message) { Punchblock::Command::Accept.new }
372
387
 
373
388
  it "delegates to the call, blocking first until it is allowed to execute" do
374
- subject.should_receive(:block_until_resumed).once.ordered
375
- subject.call.should_receive(:write_and_await_response).once.ordered.with(message)
389
+ expect(subject).to receive(:block_until_resumed).once.ordered
390
+ expect(subject.call).to receive(:write_and_await_response).once.ordered.with(message)
376
391
  subject.write_and_await_response message
377
392
  end
393
+
394
+ it "allows complete events to bubble" do
395
+ bubbled = false
396
+ message = Punchblock::Component::Output.new
397
+ expect(subject.call).to receive(:write_and_await_response)
398
+ subject.write_and_await_response message
399
+ message.register_event_handler(Punchblock::Event::Complete) { bubbled = true }
400
+ expect(bubbled).to be false
401
+ message.trigger_event_handler Punchblock::Event::Complete.new
402
+ expect(bubbled).to be true
403
+ end
378
404
  end
379
405
 
380
406
  [ :answer,
@@ -382,8 +408,8 @@ module Adhearsion
382
408
  :unmute].each do |method_name|
383
409
  describe "##{method_name}" do
384
410
  it "delegates to the call, blocking first until it is allowed to execute" do
385
- subject.should_receive(:block_until_resumed).once.ordered
386
- subject.call.should_receive(method_name).once.ordered
411
+ expect(subject).to receive(:block_until_resumed).once.ordered
412
+ expect(subject.call).to receive(method_name).once.ordered
387
413
  subject.send method_name
388
414
  end
389
415
  end
@@ -391,76 +417,77 @@ module Adhearsion
391
417
 
392
418
  [
393
419
  :hangup,
394
- :reject
420
+ :reject,
421
+ :redirect
395
422
  ].each do |method_name|
396
423
  describe "##{method_name}" do
397
424
  it "delegates to the call, blocking first until it is allowed to execute, and raises Call::Hangup" do
398
- subject.should_receive(:block_until_resumed).once.ordered
399
- subject.call.should_receive(method_name).once.ordered
400
- lambda { subject.send method_name }.should raise_error Call::Hangup
425
+ expect(subject).to receive(:block_until_resumed).once.ordered
426
+ expect(subject.call).to receive(method_name).once.ordered
427
+ expect { subject.send method_name }.to raise_error Call::Hangup
401
428
  end
402
429
  end
403
430
  end
404
431
 
405
432
  describe "#join" do
406
433
  it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
407
- subject.should_receive(:block_until_resumed).once.ordered
408
- call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
434
+ expect(subject).to receive(:block_until_resumed).once.ordered
435
+ expect(call.wrapped_object).to receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
409
436
  latch = CountDownLatch.new 1
410
437
  Thread.new do
411
438
  subject.join 'call1', :foo => :bar
412
439
  latch.countdown!
413
440
  end
414
- latch.wait(1).should be false
441
+ expect(latch.wait(1)).to be false
415
442
  subject.call << Punchblock::Event::Joined.new(call_uri: 'call1')
416
- latch.wait(1).should be false
443
+ expect(latch.wait(1)).to be false
417
444
  subject.call << Punchblock::Event::Unjoined.new(call_uri: 'call1')
418
- latch.wait(1).should be true
445
+ expect(latch.wait(1)).to be true
419
446
  end
420
447
 
421
448
  context "with a mixer" do
422
449
  it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
423
- subject.should_receive(:block_until_resumed).once.ordered
424
- call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
450
+ expect(subject).to receive(:block_until_resumed).once.ordered
451
+ expect(call.wrapped_object).to receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
425
452
  latch = CountDownLatch.new 1
426
453
  Thread.new do
427
454
  subject.join :mixer_name => 'foobar', :foo => :bar
428
455
  latch.countdown!
429
456
  end
430
- latch.wait(1).should be false
457
+ expect(latch.wait(1)).to be false
431
458
  subject.call << Punchblock::Event::Joined.new(:mixer_name => 'foobar')
432
- latch.wait(1).should be false
459
+ expect(latch.wait(1)).to be false
433
460
  subject.call << Punchblock::Event::Unjoined.new(:mixer_name => 'foobar')
434
- latch.wait(1).should be true
461
+ expect(latch.wait(1)).to be true
435
462
  end
436
463
  end
437
464
 
438
465
  context "with :async => true" do
439
466
  it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
440
- subject.should_receive(:block_until_resumed).once.ordered
441
- call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
467
+ expect(subject).to receive(:block_until_resumed).once.ordered
468
+ expect(call.wrapped_object).to receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
442
469
  latch = CountDownLatch.new 1
443
470
  Thread.new do
444
471
  subject.join 'call1', :foo => :bar, :async => true
445
472
  latch.countdown!
446
473
  end
447
- latch.wait(1).should be false
474
+ expect(latch.wait(1)).to be false
448
475
  subject.call << Punchblock::Event::Joined.new(call_uri: 'call1')
449
- latch.wait(1).should be true
476
+ expect(latch.wait(1)).to be true
450
477
  end
451
478
 
452
479
  context "with a mixer" do
453
480
  it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
454
- subject.should_receive(:block_until_resumed).once.ordered
455
- call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
481
+ expect(subject).to receive(:block_until_resumed).once.ordered
482
+ expect(call.wrapped_object).to receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
456
483
  latch = CountDownLatch.new 1
457
484
  Thread.new do
458
485
  subject.join :mixer_name => 'foobar', :foo => :bar, :async => true
459
486
  latch.countdown!
460
487
  end
461
- latch.wait(1).should be false
488
+ expect(latch.wait(1)).to be false
462
489
  subject.call << Punchblock::Event::Joined.new(:mixer_name => 'foobar')
463
- latch.wait(1).should be true
490
+ expect(latch.wait(1)).to be true
464
491
  end
465
492
  end
466
493
  end
@@ -473,7 +500,7 @@ module Adhearsion
473
500
  subject.block_until_resumed
474
501
  t2 = Time.now
475
502
 
476
- (t2 - t1).should < 0.2
503
+ expect(t2 - t1).to be < 0.2
477
504
  end
478
505
  end
479
506
 
@@ -494,9 +521,9 @@ module Adhearsion
494
521
 
495
522
  subject.resume!
496
523
 
497
- latch.wait(1).should be_true
524
+ expect(latch.wait(1)).to be_truthy
498
525
 
499
- (t2 - t1).should >= 0.5
526
+ expect(t2 - t1).to be >= 0.5
500
527
  end
501
528
  end
502
529
  end
@@ -518,13 +545,13 @@ module Adhearsion
518
545
 
519
546
  it "takes a block which is executed after acknowledgement but before waiting on completion" do
520
547
  @comp = nil
521
- subject.execute_component_and_await_completion(component) { |comp| @comp = comp }.should be == component
522
- @comp.should be == component
548
+ expect(subject.execute_component_and_await_completion(component) { |comp| @comp = comp }).to eq(component)
549
+ expect(@comp).to eq(component)
523
550
  end
524
551
 
525
552
  describe "with a successful completion" do
526
553
  it "returns the executed component" do
527
- subject.execute_component_and_await_completion(component).should be component
554
+ expect(subject.execute_component_and_await_completion(component)).to be component
528
555
  end
529
556
  end
530
557
 
@@ -540,7 +567,7 @@ module Adhearsion
540
567
  let(:details) { "Oh noes, it's all borked" }
541
568
 
542
569
  it "raises the error" do
543
- lambda { subject.execute_component_and_await_completion component }.should raise_error(Adhearsion::Error, "#{details}: #{component}")
570
+ expect { subject.execute_component_and_await_completion component }.to raise_error(Adhearsion::Error, "#{details}: #{component}")
544
571
  end
545
572
  end
546
573
 
@@ -554,7 +581,7 @@ module Adhearsion
554
581
  end
555
582
  starting_time = Time.now
556
583
  subject.execute_component_and_await_completion slow_component
557
- (Time.now - starting_time).should > 0.5
584
+ expect(Time.now - starting_time).to be > 0.5
558
585
  end
559
586
  end
560
587
 
@@ -563,7 +590,7 @@ module Adhearsion
563
590
  let(:other) { CallController.new call, metadata }
564
591
 
565
592
  it "should be equal" do
566
- subject.should == other
593
+ expect(subject).to eq(other)
567
594
  end
568
595
  end
569
596
 
@@ -571,7 +598,7 @@ module Adhearsion
571
598
  let(:other) { Class.new(CallController).new call, metadata }
572
599
 
573
600
  it "should not be equal" do
574
- subject.should_not == other
601
+ expect(subject).not_to eq(other)
575
602
  end
576
603
  end
577
604
 
@@ -579,7 +606,7 @@ module Adhearsion
579
606
  let(:other) { CallController.new Call.new, metadata }
580
607
 
581
608
  it "should not be equal" do
582
- subject.should_not == other
609
+ expect(subject).not_to eq(other)
583
610
  end
584
611
  end
585
612
 
@@ -587,7 +614,7 @@ module Adhearsion
587
614
  let(:other) { CallController.new call, something: 'else' }
588
615
 
589
616
  it "should not be equal" do
590
- subject.should_not == other
617
+ expect(subject).not_to eq(other)
591
618
  end
592
619
  end
593
620
  end
@@ -601,12 +628,18 @@ class ExampleCallController < Adhearsion::CallController
601
628
  after_call { clean_up_models }
602
629
  after_call :clean_up_models
603
630
 
631
+ on_error { apologize_for_failure }
632
+ on_error :apologize_for_failure
633
+
604
634
  def setup_models
605
635
  end
606
636
 
607
637
  def clean_up_models
608
638
  end
609
639
 
640
+ def apologize_for_failure
641
+ end
642
+
610
643
  def run
611
644
  join_to_conference
612
645
  hangup unless metadata[:skip_hangup]
@@ -624,44 +657,51 @@ describe ExampleCallController do
624
657
  include CallControllerTestHelpers
625
658
 
626
659
  before do
627
- subject.stub :execute_component_and_await_completion => nil
628
- call.wrapped_object.stub :write_and_await_response => nil
660
+ allow(subject).to receive_messages :execute_component_and_await_completion => nil
661
+ allow(call.wrapped_object).to receive_messages :write_and_await_response => nil
629
662
  end
630
663
 
631
664
  it "should execute the before_call callbacks before processing the call" do
632
- subject.should_receive(:setup_models).twice.ordered
633
- subject.should_receive(:join_to_conference).once.ordered
634
- subject.execute!
665
+ expect(subject).to receive(:setup_models).twice.ordered
666
+ expect(subject).to receive(:join_to_conference).once.ordered
667
+ subject.exec
635
668
  end
636
669
 
637
670
  it "should execute the after_call callbacks after the call is hung up" do
638
- subject.should_receive(:join_to_conference).once.ordered
639
- subject.should_receive(:clean_up_models).twice.ordered
640
- subject.should_receive(:foobar).never
641
- subject.execute!
671
+ expect(subject).to receive(:join_to_conference).once.ordered
672
+ expect(subject).to receive(:clean_up_models).twice.ordered
673
+ expect(subject).to receive(:foobar).never
674
+ subject.exec
642
675
  end
643
676
 
644
677
  it "should capture errors in callbacks" do
645
- subject.should_receive(:setup_models).twice.and_raise StandardError
646
- subject.should_receive(:clean_up_models).twice.and_raise StandardError
678
+ expect(subject).to receive(:setup_models).twice.and_raise StandardError
679
+ expect(subject).to receive(:clean_up_models).twice.and_raise StandardError
647
680
  latch = CountDownLatch.new 4
648
681
  Adhearsion::Events.exception do |e, l|
649
- e.should be_a StandardError
650
- l.should be subject.logger
682
+ expect(e).to be_a StandardError
683
+ expect(l).to be subject.logger
651
684
  latch.countdown!
652
685
  end
653
- subject.execute!
654
- latch.wait(1).should be true
686
+ subject.exec
687
+ expect(latch.wait(1)).to be true
655
688
  Adhearsion::Events.clear_handlers :exception
656
689
  end
657
690
 
691
+ it "should call the requested method when an exception is encountered" do
692
+ expect(subject).to receive(:join_to_conference).once.and_raise StandardError
693
+ expect(subject).to receive(:apologize_for_failure).twice.ordered
694
+
695
+ expect { subject.exec }.to raise_error
696
+ end
697
+
658
698
  describe "when the controller finishes without a hangup" do
659
699
  it "should execute the after_call callbacks" do
660
700
  subject[:skip_hangup] = true
661
- subject.should_receive(:join_to_conference).once.ordered
662
- subject.should_receive(:foobar).once.ordered
663
- subject.should_receive(:clean_up_models).twice.ordered
664
- subject.execute!
701
+ expect(subject).to receive(:join_to_conference).once.ordered
702
+ expect(subject).to receive(:foobar).once.ordered
703
+ expect(subject).to receive(:clean_up_models).twice.ordered
704
+ subject.exec
665
705
  end
666
706
  end
667
707
 
@@ -670,13 +710,13 @@ describe ExampleCallController do
670
710
 
671
711
  it "should allow mixing in a module globally on all CallController classes" do
672
712
  Adhearsion::CallController.mixin TestBiscuit
673
- Adhearsion::CallController.new(call).should respond_to :throwadogabone
713
+ expect(Adhearsion::CallController.new(call)).to respond_to :throwadogabone
674
714
  end
675
715
 
676
716
  it "should allow mixing in a module on a single CallController class" do
677
717
  FinancialWizard.mixin MarmaladeIsBetterThanJam
678
- FinancialWizard.new(call).should respond_to :sobittersweet
679
- Adhearsion::CallController.new(call).should_not respond_to :sobittersweet
718
+ expect(FinancialWizard.new(call)).to respond_to :sobittersweet
719
+ expect(Adhearsion::CallController.new(call)).not_to respond_to :sobittersweet
680
720
  end
681
721
  end
682
722
  end