adhearsion 2.5.4 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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