adhearsion 2.0.0.beta1 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -4
- data/CHANGELOG.md +34 -4
- data/README.markdown +2 -1
- data/Rakefile +22 -1
- data/adhearsion.gemspec +1 -0
- data/bin/ahn +0 -2
- data/features/cli_daemon.feature +2 -0
- data/features/cli_restart.feature +19 -0
- data/features/cli_start.feature +4 -6
- data/features/cli_stop.feature +3 -0
- data/features/step_definitions/app_generator_steps.rb +2 -0
- data/features/step_definitions/cli_steps.rb +2 -0
- data/features/support/aruba_helper.rb +2 -0
- data/features/support/env.rb +8 -46
- data/features/support/utils.rb +2 -0
- data/lib/adhearsion.rb +4 -6
- data/lib/adhearsion/call.rb +71 -17
- data/lib/adhearsion/call_controller.rb +25 -14
- data/lib/adhearsion/call_controller/dial.rb +34 -15
- data/lib/adhearsion/call_controller/input.rb +186 -144
- data/lib/adhearsion/call_controller/output.rb +10 -6
- data/lib/adhearsion/call_controller/record.rb +11 -13
- data/lib/adhearsion/call_controller/utility.rb +2 -0
- data/lib/adhearsion/calls.rb +4 -2
- data/lib/adhearsion/cli.rb +4 -0
- data/lib/adhearsion/cli_commands.rb +8 -2
- data/lib/adhearsion/configuration.rb +7 -3
- data/lib/adhearsion/console.rb +17 -17
- data/lib/adhearsion/events.rb +10 -4
- data/lib/adhearsion/foundation.rb +9 -0
- data/lib/adhearsion/foundation/custom_daemonizer.rb +3 -1
- data/lib/adhearsion/foundation/exception_handler.rb +2 -0
- data/lib/adhearsion/foundation/libc.rb +2 -0
- data/lib/adhearsion/foundation/object.rb +3 -0
- data/lib/adhearsion/foundation/thread_safety.rb +5 -11
- data/lib/adhearsion/generators.rb +2 -0
- data/lib/adhearsion/generators/app/app_generator.rb +2 -0
- data/lib/adhearsion/generators/app/templates/README.md +9 -0
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +38 -16
- data/lib/adhearsion/generators/app/templates/config/environment.rb +2 -0
- data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +5 -3
- data/lib/adhearsion/generators/controller/controller_generator.rb +2 -0
- data/lib/adhearsion/generators/controller/templates/lib/controller.rb +2 -0
- data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
- data/lib/adhearsion/generators/generator.rb +3 -1
- data/lib/adhearsion/generators/plugin/plugin_generator.rb +2 -0
- data/lib/adhearsion/initializer.rb +31 -17
- data/lib/adhearsion/linux_proc_name.rb +2 -0
- data/lib/adhearsion/logging.rb +5 -3
- data/lib/adhearsion/menu_dsl.rb +2 -0
- data/lib/adhearsion/menu_dsl/calculated_match.rb +2 -0
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +2 -0
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +2 -0
- data/lib/adhearsion/menu_dsl/match_calculator.rb +2 -0
- data/lib/adhearsion/menu_dsl/menu.rb +58 -4
- data/lib/adhearsion/menu_dsl/menu_builder.rb +14 -1
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +4 -1
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +2 -0
- data/lib/adhearsion/outbound_call.rb +2 -0
- data/lib/adhearsion/plugin.rb +9 -7
- data/lib/adhearsion/plugin/collection.rb +3 -1
- data/lib/adhearsion/plugin/initializer.rb +3 -1
- data/lib/adhearsion/process.rb +8 -2
- data/lib/adhearsion/punchblock_plugin.rb +3 -1
- data/lib/adhearsion/punchblock_plugin/initializer.rb +34 -11
- data/lib/adhearsion/router.rb +4 -2
- data/lib/adhearsion/router/route.rb +2 -0
- data/lib/adhearsion/script_ahn_loader.rb +2 -0
- data/lib/adhearsion/tasks.rb +2 -0
- data/lib/adhearsion/tasks/configuration.rb +2 -0
- data/lib/adhearsion/tasks/debugging.rb +8 -0
- data/lib/adhearsion/tasks/environment.rb +2 -0
- data/lib/adhearsion/tasks/plugins.rb +2 -0
- data/lib/adhearsion/tasks/testing.rb +2 -0
- data/lib/adhearsion/version.rb +3 -1
- data/pre-commit +2 -0
- data/spec/adhearsion/call_controller/dial_spec.rb +114 -25
- data/spec/adhearsion/call_controller/input_spec.rb +192 -169
- data/spec/adhearsion/call_controller/output_spec.rb +26 -12
- data/spec/adhearsion/call_controller/record_spec.rb +29 -77
- data/spec/adhearsion/call_controller/utility_spec.rb +69 -0
- data/spec/adhearsion/call_controller_spec.rb +90 -15
- data/spec/adhearsion/call_spec.rb +92 -24
- data/spec/adhearsion/calls_spec.rb +9 -7
- data/spec/adhearsion/configuration_spec.rb +58 -56
- data/spec/adhearsion/console_spec.rb +4 -2
- data/spec/adhearsion/events_spec.rb +9 -7
- data/spec/adhearsion/generators_spec.rb +3 -1
- data/spec/adhearsion/initializer_spec.rb +16 -14
- data/spec/adhearsion/logging_spec.rb +11 -9
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +6 -4
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +6 -4
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +3 -1
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +2 -0
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +42 -11
- data/spec/adhearsion/menu_dsl/menu_spec.rb +197 -36
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +4 -2
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +5 -3
- data/spec/adhearsion/outbound_call_spec.rb +7 -5
- data/spec/adhearsion/plugin_spec.rb +19 -15
- data/spec/adhearsion/process_spec.rb +12 -7
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +35 -15
- data/spec/adhearsion/punchblock_plugin_spec.rb +4 -1
- data/spec/adhearsion/router/route_spec.rb +8 -6
- data/spec/adhearsion/router_spec.rb +12 -10
- data/spec/adhearsion_spec.rb +13 -2
- data/spec/capture_warnings.rb +33 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/call_controller_test_helpers.rb +2 -4
- data/spec/support/initializer_stubs.rb +8 -5
- data/spec/support/logging_helpers.rb +2 -0
- data/spec/support/punchblock_mocks.rb +2 -0
- metadata +84 -71
- data/EVENTS +0 -11
- data/lib/adhearsion/call_controller/menu.rb +0 -124
- data/lib/adhearsion/foundation/all.rb +0 -8
- data/spec/adhearsion/call_controller/menu_spec.rb +0 -120
- data/spec/adhearsion/menu_dsl_spec.rb +0 -12
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module Adhearsion
|
@@ -12,111 +14,61 @@ module Adhearsion
|
|
12
14
|
:max_duration => 5000
|
13
15
|
}
|
14
16
|
end
|
15
|
-
let(:component) { Punchblock::Component::Record.new options }
|
16
|
-
let(:response) { Punchblock::Event::Complete.new }
|
17
|
+
let(:component) { ::Punchblock::Component::Record.new options }
|
18
|
+
let(:response) { ::Punchblock::Event::Complete.new }
|
17
19
|
|
18
20
|
describe "with :async => true and an :on_complete callback" do
|
19
|
-
let(:callback) { lambda { |rec| @rec.push rec } }
|
20
|
-
|
21
21
|
before do
|
22
|
-
|
22
|
+
component
|
23
|
+
flexmock(::Punchblock::Component::Record).should_receive(:new).once.with(options).and_return component
|
24
|
+
expect_message_waiting_for_response component
|
23
25
|
@rec = Queue.new
|
24
|
-
options.merge
|
25
|
-
subject.record options
|
26
|
-
component.request!
|
26
|
+
subject.record(options.merge(async: true)) { |rec| @rec.push rec }
|
27
27
|
component.execute!
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should execute the callback" do
|
31
31
|
component.trigger_event_handler response
|
32
32
|
Timeout::timeout 5 do
|
33
|
-
@rec.pop.should
|
33
|
+
@rec.pop.should be response
|
34
34
|
end
|
35
35
|
end
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
describe "when the callback raises an exception" do
|
39
|
+
before do
|
40
|
+
TestException = Class.new StandardError
|
41
|
+
component
|
42
|
+
flexmock(::Punchblock::Component::Record).should_receive(:new).once.with({}).and_return component
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
it "should pass the exception to the events system" do
|
46
|
+
flexmock(Events).should_receive(:trigger).once.with(:exception, TestException)
|
47
|
+
expect_component_execution component
|
48
|
+
subject.record { |rec| raise TestException }
|
49
|
+
component.request!
|
50
|
+
component.execute!
|
51
|
+
component.trigger_event_handler response
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
48
55
|
describe "with :async => false" do
|
49
56
|
before do
|
57
|
+
component
|
58
|
+
flexmock(::Punchblock::Component::Record).should_receive(:new).once.with(options).and_return component
|
50
59
|
expect_component_execution component
|
51
|
-
component.request!
|
52
|
-
component.execute!
|
53
|
-
component.add_event response
|
54
60
|
@rec = Queue.new
|
55
61
|
subject.record(options.merge(:async => false)) { |rec| @rec.push rec }
|
62
|
+
component.request!
|
63
|
+
component.execute!
|
56
64
|
end
|
57
65
|
|
58
66
|
it 'should execute a passed block' do
|
67
|
+
component.trigger_event_handler response
|
59
68
|
Timeout::timeout 5 do
|
60
|
-
@rec.pop.should == response
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "#record with default options" do
|
67
|
-
let(:options) {{
|
68
|
-
:start_beep => true,
|
69
|
-
:format => 'mp3',
|
70
|
-
:start_paused => false,
|
71
|
-
:stop_beep => true,
|
72
|
-
:max_duration => 500000,
|
73
|
-
:initial_timeout => 10000,
|
74
|
-
:final_timeout => 30000
|
75
|
-
}}
|
76
|
-
|
77
|
-
let(:component) { Punchblock::Component::Record.new(options) }
|
78
|
-
let(:response) { Punchblock::Event::Complete.new }
|
79
|
-
|
80
|
-
before do
|
81
|
-
expect_message_waiting_for_response component
|
82
|
-
component.execute!
|
83
|
-
component.complete_event = response
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'executes a #record with the correct options' do
|
87
|
-
subject.execute_component_and_await_completion component
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'takes a block which is executed after acknowledgement but before waiting on completion' do
|
91
|
-
@comp = nil
|
92
|
-
subject.execute_component_and_await_completion(component) { |comp| @comp = comp }.should == component
|
93
|
-
@comp.should == component
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "with a successful completion" do
|
97
|
-
it 'returns the executed component' do
|
98
|
-
subject.execute_component_and_await_completion(component).should be component
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe 'with an error response' do
|
103
|
-
let(:response) do
|
104
|
-
Punchblock::Event::Complete.new.tap do |complete|
|
105
|
-
complete << error
|
69
|
+
@rec.pop.should be == response
|
106
70
|
end
|
107
71
|
end
|
108
|
-
|
109
|
-
let(:error) do |error|
|
110
|
-
Punchblock::Event::Complete::Error.new.tap do |error|
|
111
|
-
error << details
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
let(:details) { "Something came up" }
|
116
|
-
|
117
|
-
it 'raises the error' do
|
118
|
-
lambda { subject.execute_component_and_await_completion component }.should raise_error(StandardError, details)
|
119
|
-
end
|
120
72
|
end
|
121
73
|
end
|
122
74
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
describe Utility do
|
8
|
+
include CallControllerTestHelpers
|
9
|
+
|
10
|
+
describe "#grammar_digits" do
|
11
|
+
let(:grxml) {
|
12
|
+
RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'inputdigits' do
|
13
|
+
rule id: 'inputdigits', scope: 'public' do
|
14
|
+
item repeat: '2' do
|
15
|
+
one_of do
|
16
|
+
0.upto(9) { |d| item { d.to_s } }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
it 'generates the correct GRXML grammar' do
|
24
|
+
subject.grammar_digits(2).to_s.should be == grxml.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
end # describe #grammar_digits
|
28
|
+
|
29
|
+
describe "#grammar_accept" do
|
30
|
+
let(:grxml) {
|
31
|
+
RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'inputdigits' do
|
32
|
+
rule id: 'inputdigits', scope: 'public' do
|
33
|
+
one_of do
|
34
|
+
item { '3' }
|
35
|
+
item { '5' }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
}
|
40
|
+
|
41
|
+
it 'generates the correct GRXML grammar' do
|
42
|
+
subject.grammar_accept('35').to_s.should be == grxml.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'filters meaningless characters out' do
|
46
|
+
subject.grammar_accept('3+5').to_s.should be == grxml.to_s
|
47
|
+
end
|
48
|
+
end # grammar_accept
|
49
|
+
|
50
|
+
describe "#parse_single_dtmf" do
|
51
|
+
it "correctly returns the parsed input" do
|
52
|
+
subject.parse_single_dtmf("dtmf-3").should be == '3'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "correctly returns star as *" do
|
56
|
+
subject.parse_single_dtmf("dtmf-star").should be == '*'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "correctly returns pound as #" do
|
60
|
+
subject.parse_single_dtmf("dtmf-pound").should be == '#'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "correctly returns nil when input is nil" do
|
64
|
+
subject.parse_single_dtmf(nil).should be == nil
|
65
|
+
end
|
66
|
+
end # describe #grammar_accept
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
class FinancialWizard < Adhearsion::CallController
|
@@ -10,16 +12,16 @@ module Adhearsion
|
|
10
12
|
let(:call) { Adhearsion::Call.new mock_offer(nil, :x_foo => 'bar') }
|
11
13
|
|
12
14
|
its(:call) { should be call }
|
13
|
-
its(:metadata) { should == {:doo => :dah} }
|
15
|
+
its(:metadata) { should be == {:doo => :dah} }
|
14
16
|
|
15
17
|
describe "setting meta-data" do
|
16
18
|
it "should preserve data correctly" do
|
17
19
|
subject[:foo].should be nil
|
18
20
|
subject[:foo] = 7
|
19
|
-
subject[:foo].should == 7
|
21
|
+
subject[:foo].should be == 7
|
20
22
|
subject[:bar] = 10
|
21
|
-
subject[:bar].should == 10
|
22
|
-
subject[:foo].should == 7
|
23
|
+
subject[:bar].should be == 10
|
24
|
+
subject[:foo].should be == 7
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
@@ -33,15 +35,23 @@ module Adhearsion
|
|
33
35
|
end
|
34
36
|
|
35
37
|
it "catches Hangup exceptions and logs the hangup" do
|
36
|
-
subject.should_receive(:run).once.and_raise(Hangup).ordered
|
38
|
+
subject.should_receive(:run).once.and_raise(Call::Hangup).ordered
|
37
39
|
flexmock(subject.logger).should_receive(:info).once.with(/Call was hung up/).ordered
|
38
40
|
subject.execute!
|
39
41
|
end
|
40
42
|
|
41
43
|
it "catches standard errors, triggering an exception event" do
|
42
44
|
subject.should_receive(:run).once.and_raise(StandardError).ordered
|
43
|
-
|
45
|
+
latch = CountDownLatch.new 1
|
46
|
+
ex = lo = nil
|
47
|
+
Events.exception do |e, l|
|
48
|
+
ex, lo = e, l
|
49
|
+
latch.countdown!
|
50
|
+
end
|
44
51
|
subject.execute!
|
52
|
+
latch.wait(1).should be true
|
53
|
+
ex.should be_a StandardError
|
54
|
+
lo.should be subject.logger
|
45
55
|
end
|
46
56
|
|
47
57
|
context "when a block is specified" do
|
@@ -76,7 +86,7 @@ module Adhearsion
|
|
76
86
|
end
|
77
87
|
|
78
88
|
def simulate_remote_hangup
|
79
|
-
raise Hangup
|
89
|
+
raise Call::Hangup
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
@@ -193,8 +203,7 @@ module Adhearsion
|
|
193
203
|
:reject,
|
194
204
|
:hangup,
|
195
205
|
:mute,
|
196
|
-
:unmute
|
197
|
-
:join].each do |method_name|
|
206
|
+
:unmute].each do |method_name|
|
198
207
|
describe "##{method_name}" do
|
199
208
|
it "delegates to the call, blocking first until it is allowed to execute" do
|
200
209
|
flexmock(subject).should_receive(:block_until_resumed).once.ordered
|
@@ -204,6 +213,70 @@ module Adhearsion
|
|
204
213
|
end
|
205
214
|
end
|
206
215
|
|
216
|
+
describe "#join" do
|
217
|
+
it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
|
218
|
+
flexmock(subject).should_receive(:block_until_resumed).once.ordered
|
219
|
+
flexmock(subject.call).should_receive(:join).once.with('call1', :foo => :bar).ordered.and_return Punchblock::Command::Join.new(:other_call_id => 'call1')
|
220
|
+
latch = CountDownLatch.new 1
|
221
|
+
Thread.new do
|
222
|
+
subject.join 'call1', :foo => :bar
|
223
|
+
latch.countdown!
|
224
|
+
end
|
225
|
+
latch.wait(1).should be false
|
226
|
+
subject.call << Punchblock::Event::Joined.new(:other_call_id => 'call1')
|
227
|
+
latch.wait(1).should be false
|
228
|
+
subject.call << Punchblock::Event::Unjoined.new(:other_call_id => 'call1')
|
229
|
+
latch.wait(1).should be true
|
230
|
+
end
|
231
|
+
|
232
|
+
context "with a mixer" do
|
233
|
+
it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
|
234
|
+
flexmock(subject).should_receive(:block_until_resumed).once.ordered
|
235
|
+
flexmock(subject.call).should_receive(:join).once.with({:mixer_name => 'foobar', :foo => :bar}, {}).ordered.and_return Punchblock::Command::Join.new(:mixer_name => 'foobar')
|
236
|
+
latch = CountDownLatch.new 1
|
237
|
+
Thread.new do
|
238
|
+
subject.join :mixer_name => 'foobar', :foo => :bar
|
239
|
+
latch.countdown!
|
240
|
+
end
|
241
|
+
latch.wait(1).should be false
|
242
|
+
subject.call << Punchblock::Event::Joined.new(:mixer_name => 'foobar')
|
243
|
+
latch.wait(1).should be false
|
244
|
+
subject.call << Punchblock::Event::Unjoined.new(:mixer_name => 'foobar')
|
245
|
+
latch.wait(1).should be true
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context "with :async => true" do
|
250
|
+
it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
|
251
|
+
flexmock(subject).should_receive(:block_until_resumed).once.ordered
|
252
|
+
flexmock(subject.call).should_receive(:join).once.with('call1', :foo => :bar).ordered.and_return Punchblock::Command::Join.new(:other_call_id => 'call1')
|
253
|
+
latch = CountDownLatch.new 1
|
254
|
+
Thread.new do
|
255
|
+
subject.join 'call1', :foo => :bar, :async => true
|
256
|
+
latch.countdown!
|
257
|
+
end
|
258
|
+
latch.wait(1).should be false
|
259
|
+
subject.call << Punchblock::Event::Joined.new(:other_call_id => 'call1')
|
260
|
+
latch.wait(1).should be true
|
261
|
+
end
|
262
|
+
|
263
|
+
context "with a mixer" do
|
264
|
+
it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
|
265
|
+
flexmock(subject).should_receive(:block_until_resumed).once.ordered
|
266
|
+
flexmock(subject.call).should_receive(:join).once.with({:mixer_name => 'foobar', :foo => :bar}, {}).ordered.and_return Punchblock::Command::Join.new(:mixer_name => 'foobar')
|
267
|
+
latch = CountDownLatch.new 1
|
268
|
+
Thread.new do
|
269
|
+
subject.join :mixer_name => 'foobar', :foo => :bar, :async => true
|
270
|
+
latch.countdown!
|
271
|
+
end
|
272
|
+
latch.wait(1).should be false
|
273
|
+
subject.call << Punchblock::Event::Joined.new(:mixer_name => 'foobar')
|
274
|
+
latch.wait(1).should be true
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
207
280
|
describe "#block_until_resumed" do
|
208
281
|
context "when the controller has not been paused" do
|
209
282
|
it "should not block" do
|
@@ -221,7 +294,7 @@ module Adhearsion
|
|
221
294
|
it "should unblock when the controller is unpaused" do
|
222
295
|
t1 = t2 = nil
|
223
296
|
latch = CountDownLatch.new 1
|
224
|
-
|
297
|
+
Thread.new do
|
225
298
|
t1 = Time.now
|
226
299
|
subject.block_until_resumed
|
227
300
|
t2 = Time.now
|
@@ -255,8 +328,8 @@ module Adhearsion
|
|
255
328
|
|
256
329
|
it "takes a block which is executed after acknowledgement but before waiting on completion" do
|
257
330
|
@comp = nil
|
258
|
-
subject.execute_component_and_await_completion(component) { |comp| @comp = comp }.should == component
|
259
|
-
@comp.should == component
|
331
|
+
subject.execute_component_and_await_completion(component) { |comp| @comp = comp }.should be == component
|
332
|
+
@comp.should be == component
|
260
333
|
end
|
261
334
|
|
262
335
|
describe "with a successful completion" do
|
@@ -273,20 +346,22 @@ module Adhearsion
|
|
273
346
|
end
|
274
347
|
|
275
348
|
let(:error) do |error|
|
276
|
-
Punchblock::Event::Complete::Error.new.tap do |
|
277
|
-
|
349
|
+
Punchblock::Event::Complete::Error.new.tap do |e|
|
350
|
+
e << details
|
278
351
|
end
|
279
352
|
end
|
280
353
|
|
281
354
|
let(:details) { "Oh noes, it's all borked" }
|
282
355
|
|
283
356
|
it "raises the error" do
|
284
|
-
lambda { subject.execute_component_and_await_completion component }.should raise_error(StandardError, details)
|
357
|
+
lambda { subject.execute_component_and_await_completion component }.should raise_error(StandardError, "#{details}: #{component}")
|
285
358
|
end
|
286
359
|
end
|
287
360
|
|
288
361
|
it "blocks until the component receives a complete event" do
|
289
362
|
slow_component = Punchblock::Component::Output.new
|
363
|
+
slow_component.request!
|
364
|
+
slow_component.execute!
|
290
365
|
Thread.new do
|
291
366
|
sleep 0.5
|
292
367
|
slow_component.complete_event = response
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module Adhearsion
|
4
6
|
describe Call do
|
5
|
-
let(:mock_client) { flexmock('Client').tap
|
7
|
+
let(:mock_client) { flexmock('Client').tap(&:should_ignore_missing) }
|
6
8
|
|
7
9
|
let(:call_id) { rand }
|
8
10
|
let(:headers) { nil }
|
@@ -27,32 +29,31 @@ module Adhearsion
|
|
27
29
|
|
28
30
|
it { should respond_to :<< }
|
29
31
|
|
30
|
-
its(:end_reason) { should == nil }
|
32
|
+
its(:end_reason) { should be == nil }
|
31
33
|
it { should be_active }
|
32
34
|
|
33
|
-
its(:commands) { should be_a Call::CommandRegistry }
|
34
35
|
its(:commands) { should be_empty }
|
35
36
|
|
36
|
-
its(:id) { should == call_id }
|
37
|
-
its(:to) { should == to }
|
38
|
-
its(:from) { should == from }
|
37
|
+
its(:id) { should be == call_id }
|
38
|
+
its(:to) { should be == to }
|
39
|
+
its(:from) { should be == from }
|
39
40
|
its(:offer) { should be offer }
|
40
41
|
its(:client) { should be mock_client }
|
41
42
|
|
42
|
-
its(:after_end_hold_time) { should == 30 }
|
43
|
+
its(:after_end_hold_time) { should be == 30 }
|
43
44
|
|
44
45
|
describe "its variables" do
|
45
46
|
context "with an offer with headers" do
|
46
47
|
let(:headers) { {:x_foo => 'bar'} }
|
47
|
-
its(:variables) { should == headers }
|
48
|
+
its(:variables) { should be == headers }
|
48
49
|
|
49
50
|
it "should be made available via []" do
|
50
|
-
subject[:x_foo].should == 'bar'
|
51
|
+
subject[:x_foo].should be == 'bar'
|
51
52
|
end
|
52
53
|
|
53
54
|
it "should be alterable using []=" do
|
54
55
|
subject[:x_foo] = 'baz'
|
55
|
-
subject[:x_foo].should == 'baz'
|
56
|
+
subject[:x_foo].should be == 'baz'
|
56
57
|
end
|
57
58
|
|
58
59
|
context "when receiving an event with headers" do
|
@@ -60,7 +61,7 @@ module Adhearsion
|
|
60
61
|
|
61
62
|
it "should merge later headers" do
|
62
63
|
subject << event
|
63
|
-
subject.variables.should == {:x_foo => 'bar', :x_bar => 'foo'}
|
64
|
+
subject.variables.should be == {:x_foo => 'bar', :x_bar => 'foo'}
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -69,19 +70,19 @@ module Adhearsion
|
|
69
70
|
|
70
71
|
it "should merge later headers" do
|
71
72
|
subject.write_command command
|
72
|
-
subject.variables.should == {:x_foo => 'bar', :x_bar => 'foo'}
|
73
|
+
subject.variables.should be == {:x_foo => 'bar', :x_bar => 'foo'}
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
77
78
|
context "with an offer without headers" do
|
78
79
|
let(:headers) { nil }
|
79
|
-
its(:variables) { should == {} }
|
80
|
+
its(:variables) { should be == {} }
|
80
81
|
end
|
81
82
|
|
82
83
|
context "without an offer" do
|
83
84
|
let(:offer) { nil }
|
84
|
-
its(:variables) { should == {} }
|
85
|
+
its(:variables) { should be == {} }
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
@@ -133,7 +134,7 @@ module Adhearsion
|
|
133
134
|
|
134
135
|
it "should set the end reason" do
|
135
136
|
subject << end_event
|
136
|
-
subject.end_reason.should == :hangup
|
137
|
+
subject.end_reason.should be == :hangup
|
137
138
|
end
|
138
139
|
|
139
140
|
it "should instruct the command registry to terminate" do
|
@@ -145,10 +146,10 @@ module Adhearsion
|
|
145
146
|
size_before = Adhearsion.active_calls.size
|
146
147
|
|
147
148
|
Adhearsion.active_calls << subject
|
148
|
-
Adhearsion.active_calls.size.should > size_before
|
149
|
+
Adhearsion.active_calls.size.should be > size_before
|
149
150
|
|
150
151
|
subject << end_event
|
151
|
-
Adhearsion.active_calls.size.should == size_before
|
152
|
+
Adhearsion.active_calls.size.should be == size_before
|
152
153
|
end
|
153
154
|
|
154
155
|
it "shuts down the actor" do
|
@@ -190,7 +191,7 @@ module Adhearsion
|
|
190
191
|
subject.tag :female
|
191
192
|
subject.remove_tag :female
|
192
193
|
subject.tag :male
|
193
|
-
subject.tags.should == [:moderator, :male]
|
194
|
+
subject.tags.should be == [:moderator, :male]
|
194
195
|
end
|
195
196
|
|
196
197
|
describe "#tagged_with?" do
|
@@ -214,7 +215,7 @@ module Adhearsion
|
|
214
215
|
it "should asynchronously write the command to the Punchblock connection" do
|
215
216
|
mock_client = flexmock('Client')
|
216
217
|
flexmock(subject.wrapped_object).should_receive(:client).once.and_return mock_client
|
217
|
-
mock_client.should_receive(:execute_command).once.with(mock_command, :call_id => subject.id).and_return true
|
218
|
+
mock_client.should_receive(:execute_command).once.with(mock_command, :call_id => subject.id, :async => true).and_return true
|
218
219
|
subject.write_command mock_command
|
219
220
|
end
|
220
221
|
|
@@ -224,7 +225,7 @@ module Adhearsion
|
|
224
225
|
end
|
225
226
|
|
226
227
|
it "should raise a Hangup exception" do
|
227
|
-
lambda { subject.write_command mock_command }.should raise_error(Hangup)
|
228
|
+
lambda { subject.write_command mock_command }.should raise_error(Call::Hangup)
|
228
229
|
end
|
229
230
|
|
230
231
|
describe "if the command is a Hangup" do
|
@@ -258,6 +259,7 @@ module Adhearsion
|
|
258
259
|
|
259
260
|
it "blocks until a response is received" do
|
260
261
|
slow_command = Punchblock::Command::Dial.new
|
262
|
+
slow_command.request!
|
261
263
|
Thread.new do
|
262
264
|
sleep 0.5
|
263
265
|
slow_command.response = response
|
@@ -274,13 +276,22 @@ module Adhearsion
|
|
274
276
|
end
|
275
277
|
|
276
278
|
describe "with an error response" do
|
277
|
-
let(:new_exception) {
|
279
|
+
let(:new_exception) { Punchblock::ProtocolError }
|
278
280
|
let(:response) { new_exception.new }
|
279
281
|
|
280
282
|
it "raises the error" do
|
281
283
|
flexmock(Events).should_receive(:trigger).never
|
282
284
|
lambda { subject.write_and_await_response message }.should raise_error new_exception
|
283
285
|
end
|
286
|
+
|
287
|
+
context "where the name is :item_not_found" do
|
288
|
+
let(:response) { new_exception.new :item_not_found }
|
289
|
+
|
290
|
+
it "should raise a Hangup exception" do
|
291
|
+
flexmock(Events).should_receive(:trigger).never
|
292
|
+
lambda { subject.write_and_await_response message }.should raise_error Call::Hangup
|
293
|
+
end
|
294
|
+
end
|
284
295
|
end
|
285
296
|
|
286
297
|
describe "when the response times out" do
|
@@ -289,7 +300,7 @@ module Adhearsion
|
|
289
300
|
end
|
290
301
|
|
291
302
|
it "should raise the error in the caller but not crash the actor" do
|
292
|
-
lambda { subject.write_and_await_response message }.should raise_error
|
303
|
+
lambda { subject.write_and_await_response message }.should raise_error Call::CommandTimeout, message.to_s
|
293
304
|
sleep 0.5
|
294
305
|
subject.should be_alive
|
295
306
|
end
|
@@ -497,6 +508,63 @@ module Adhearsion
|
|
497
508
|
end
|
498
509
|
end
|
499
510
|
|
511
|
+
describe "#unjoin" do
|
512
|
+
def expect_unjoin_with_options(options = {})
|
513
|
+
Punchblock::Command::Unjoin.new(options).tap do |unjoin|
|
514
|
+
expect_message_waiting_for_response unjoin
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
context "with a call" do
|
519
|
+
let(:call_id) { rand.to_s }
|
520
|
+
let(:target) { flexmock Call.new, :id => call_id }
|
521
|
+
|
522
|
+
it "should send an unjoin command unjoining from the provided call ID" do
|
523
|
+
expect_unjoin_with_options :other_call_id => call_id
|
524
|
+
subject.unjoin target
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context "with a call ID" do
|
529
|
+
let(:target) { rand.to_s }
|
530
|
+
|
531
|
+
it "should send an unjoin command unjoining from the provided call ID" do
|
532
|
+
expect_unjoin_with_options :other_call_id => target
|
533
|
+
subject.unjoin target
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context "with a call ID as a hash key" do
|
538
|
+
let(:call_id) { rand.to_s }
|
539
|
+
let(:target) { { :call_id => call_id } }
|
540
|
+
|
541
|
+
it "should send an unjoin command unjoining from the provided call ID" do
|
542
|
+
expect_unjoin_with_options :other_call_id => call_id
|
543
|
+
subject.unjoin target
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
context "with a mixer name as a hash key" do
|
548
|
+
let(:mixer_name) { rand.to_s }
|
549
|
+
let(:target) { { :mixer_name => mixer_name } }
|
550
|
+
|
551
|
+
it "should send an unjoin command unjoining from the provided call ID" do
|
552
|
+
expect_unjoin_with_options :mixer_name => mixer_name
|
553
|
+
subject.unjoin target
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
context "with a call ID and a mixer name as hash keys" do
|
558
|
+
let(:call_id) { rand.to_s }
|
559
|
+
let(:mixer_name) { rand.to_s }
|
560
|
+
let(:target) { { :call_id => call_id, :mixer_name => mixer_name } }
|
561
|
+
|
562
|
+
it "should raise an ArgumentError" do
|
563
|
+
lambda { subject.unjoin target }.should raise_error ArgumentError, /call ID and mixer name/
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
500
568
|
describe "#mute" do
|
501
569
|
it 'should send a Mute message' do
|
502
570
|
expect_message_waiting_for_response Punchblock::Command::Mute.new
|
@@ -612,9 +680,9 @@ module Adhearsion
|
|
612
680
|
end
|
613
681
|
subject.terminate
|
614
682
|
commands.each do |command|
|
615
|
-
command.response.should be_a Hangup
|
683
|
+
command.response.should be_a Call::Hangup
|
616
684
|
end
|
617
|
-
finished_command.response.should == :foo
|
685
|
+
finished_command.response.should be == :foo
|
618
686
|
end
|
619
687
|
end
|
620
688
|
end
|