adhearsion 2.0.0.beta1 → 2.0.0.rc1
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.
- 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
|