adhearsion 1.2.6 → 2.0.0.alpha1
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/.gitignore +17 -10
- data/CHANGELOG.md +273 -0
- data/Gemfile +1 -1
- data/Guardfile +17 -0
- data/README.markdown +61 -9
- data/Rakefile +16 -48
- data/adhearsion.gemspec +21 -7
- data/bin/ahn +3 -1
- data/cucumber.yml +4 -0
- data/features/app_generator.feature +42 -0
- data/features/cli.feature +108 -0
- data/features/step_definitions/app_generator_steps.rb +6 -0
- data/features/step_definitions/cli_steps.rb +74 -0
- data/features/support/aruba_helper.rb +22 -0
- data/features/support/env.rb +37 -0
- data/features/support/utils.rb +8 -0
- data/lib/adhearsion.rb +85 -41
- data/lib/adhearsion/call.rb +176 -0
- data/lib/adhearsion/call_controller.rb +134 -0
- data/lib/adhearsion/call_controller/dial.rb +70 -0
- data/lib/adhearsion/call_controller/input.rb +173 -0
- data/lib/adhearsion/call_controller/menu.rb +124 -0
- data/lib/adhearsion/call_controller/output.rb +267 -0
- data/lib/adhearsion/call_controller/record.rb +42 -0
- data/lib/adhearsion/call_controller/utility.rb +60 -0
- data/lib/adhearsion/calls.rb +81 -0
- data/lib/adhearsion/cli.rb +1 -3
- data/lib/adhearsion/cli_commands.rb +142 -0
- data/lib/adhearsion/configuration.rb +149 -0
- data/lib/adhearsion/console.rb +19 -8
- data/lib/adhearsion/dialplan_controller.rb +9 -0
- data/lib/adhearsion/events.rb +84 -0
- data/lib/adhearsion/foundation/all.rb +0 -7
- data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
- data/lib/adhearsion/foundation/exception_handler.rb +9 -0
- data/lib/adhearsion/foundation/object.rb +26 -8
- data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
- data/lib/adhearsion/foundation/thread_safety.rb +17 -1
- data/lib/adhearsion/generators/app/app_generator.rb +4 -13
- data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
- data/lib/adhearsion/generators/app/templates/Procfile +1 -0
- data/lib/adhearsion/generators/app/templates/README.md +28 -0
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
- data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
- data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
- data/lib/adhearsion/initializer.rb +151 -293
- data/lib/adhearsion/initializer/logging.rb +33 -0
- data/lib/adhearsion/logging.rb +65 -69
- data/lib/adhearsion/menu_dsl.rb +15 -0
- data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
- data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
- data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
- data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
- data/lib/adhearsion/outbound_call.rb +64 -0
- data/lib/adhearsion/plugin.rb +319 -0
- data/lib/adhearsion/plugin/collection.rb +19 -0
- data/lib/adhearsion/plugin/initializer.rb +37 -0
- data/lib/adhearsion/plugin/methods_container.rb +6 -0
- data/lib/adhearsion/process.rb +94 -0
- data/lib/adhearsion/punchblock_plugin.rb +29 -0
- data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
- data/lib/adhearsion/router.rb +30 -0
- data/lib/adhearsion/router/route.rb +42 -0
- data/lib/adhearsion/script_ahn_loader.rb +2 -2
- data/lib/adhearsion/tasks.rb +14 -9
- data/lib/adhearsion/tasks/configuration.rb +26 -0
- data/lib/adhearsion/tasks/plugins.rb +17 -0
- data/lib/adhearsion/version.rb +8 -14
- data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
- data/spec/adhearsion/call_controller/input_spec.rb +278 -0
- data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
- data/spec/adhearsion/call_controller/output_spec.rb +466 -0
- data/spec/adhearsion/call_controller/record_spec.rb +125 -0
- data/spec/adhearsion/call_controller_spec.rb +395 -0
- data/spec/adhearsion/call_spec.rb +438 -0
- data/spec/adhearsion/calls_spec.rb +47 -0
- data/spec/adhearsion/configuration_spec.rb +308 -0
- data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
- data/spec/adhearsion/events_spec.rb +112 -0
- data/spec/adhearsion/initializer/logging_spec.rb +58 -0
- data/spec/adhearsion/initializer_spec.rb +209 -122
- data/spec/adhearsion/logging_spec.rb +58 -47
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
- data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
- data/spec/adhearsion/menu_dsl_spec.rb +12 -0
- data/spec/adhearsion/outbound_call_spec.rb +174 -0
- data/spec/adhearsion/plugin_spec.rb +489 -0
- data/spec/adhearsion/process_spec.rb +34 -0
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
- data/spec/adhearsion/router/route_spec.rb +99 -0
- data/spec/adhearsion/router_spec.rb +106 -0
- data/spec/adhearsion_spec.rb +46 -0
- data/spec/spec_helper.rb +14 -14
- data/spec/support/call_controller_test_helpers.rb +48 -0
- data/spec/support/initializer_stubs.rb +8 -13
- data/spec/support/punchblock_mocks.rb +6 -0
- metadata +255 -253
- data/CHANGELOG +0 -174
- data/bin/ahnctl +0 -68
- data/bin/jahn +0 -43
- data/examples/asterisk_manager_interface/standalone.rb +0 -51
- data/lib/adhearsion/commands.rb +0 -302
- data/lib/adhearsion/component_manager.rb +0 -278
- data/lib/adhearsion/component_manager/component_tester.rb +0 -54
- data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
- data/lib/adhearsion/events_support.rb +0 -65
- data/lib/adhearsion/foundation/blank_slate.rb +0 -3
- data/lib/adhearsion/foundation/event_socket.rb +0 -205
- data/lib/adhearsion/foundation/future_resource.rb +0 -36
- data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
- data/lib/adhearsion/foundation/numeric.rb +0 -13
- data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
- data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
- data/lib/adhearsion/foundation/string.rb +0 -26
- data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
- data/lib/adhearsion/generators/app/templates/README +0 -8
- data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
- data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
- data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
- data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
- data/lib/adhearsion/generators/app/templates/events.rb +0 -33
- data/lib/adhearsion/host_definitions.rb +0 -67
- data/lib/adhearsion/initializer/asterisk.rb +0 -86
- data/lib/adhearsion/initializer/configuration.rb +0 -324
- data/lib/adhearsion/initializer/database.rb +0 -60
- data/lib/adhearsion/initializer/drb.rb +0 -31
- data/lib/adhearsion/initializer/freeswitch.rb +0 -22
- data/lib/adhearsion/initializer/ldap.rb +0 -57
- data/lib/adhearsion/initializer/rails.rb +0 -41
- data/lib/adhearsion/initializer/xmpp.rb +0 -42
- data/lib/adhearsion/tasks/components.rb +0 -32
- data/lib/adhearsion/tasks/database.rb +0 -5
- data/lib/adhearsion/tasks/deprecations.rb +0 -59
- data/lib/adhearsion/tasks/generating.rb +0 -20
- data/lib/adhearsion/tasks/lint.rb +0 -4
- data/lib/adhearsion/voip/asterisk.rb +0 -4
- data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
- data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
- data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
- data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
- data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
- data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
- data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
- data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
- data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
- data/lib/adhearsion/voip/call.rb +0 -521
- data/lib/adhearsion/voip/call_routing.rb +0 -64
- data/lib/adhearsion/voip/commands.rb +0 -17
- data/lib/adhearsion/voip/constants.rb +0 -39
- data/lib/adhearsion/voip/conveniences.rb +0 -18
- data/lib/adhearsion/voip/dial_plan.rb +0 -252
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
- data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
- data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
- data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
- data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
- data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
- data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
- data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
- data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
- data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
- data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
- data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
- data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
- data/lib/adhearsion/xmpp/connection.rb +0 -61
- data/lib/theatre.rb +0 -147
- data/lib/theatre/README.markdown +0 -64
- data/lib/theatre/callback_definition_loader.rb +0 -86
- data/lib/theatre/guid.rb +0 -23
- data/lib/theatre/invocation.rb +0 -131
- data/lib/theatre/namespace_manager.rb +0 -153
- data/lib/theatre/version.rb +0 -2
- data/spec/adhearsion/cli_spec.rb +0 -306
- data/spec/adhearsion/component_manager_spec.rb +0 -292
- data/spec/adhearsion/constants_spec.rb +0 -8
- data/spec/adhearsion/drb_spec.rb +0 -65
- data/spec/adhearsion/fixtures/dialplan.rb +0 -3
- data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
- data/spec/adhearsion/host_definitions_spec.rb +0 -79
- data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
- data/spec/adhearsion/initializer/loading_spec.rb +0 -154
- data/spec/adhearsion/initializer/paths_spec.rb +0 -74
- data/spec/adhearsion/relationship_properties_spec.rb +0 -54
- data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
- data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
- data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
- data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
- data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
- data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
- data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
- data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
- data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
- data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
- data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
- data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
- data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
- data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
- data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
- data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
- data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
- data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
- data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
- data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
- data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
- data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
- data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
- data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
- data/spec/support/the_following_code.rb +0 -3
- data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
- data/spec/theatre/dsl_spec.rb +0 -69
- data/spec/theatre/invocation_spec.rb +0 -182
- data/spec/theatre/namespace_spec.rb +0 -125
- data/spec/theatre/spec_helper_spec.rb +0 -28
- data/spec/theatre/theatre_class_spec.rb +0 -148
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Adhearsion
|
|
4
|
+
class CallController
|
|
5
|
+
describe Record do
|
|
6
|
+
include CallControllerTestHelpers
|
|
7
|
+
|
|
8
|
+
describe "#record" do
|
|
9
|
+
let(:options) do
|
|
10
|
+
{
|
|
11
|
+
:start_beep => true,
|
|
12
|
+
:max_duration => 5000
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
let(:component) { Punchblock::Component::Record.new options }
|
|
16
|
+
let(:response) { Punchblock::Event::Complete.new }
|
|
17
|
+
|
|
18
|
+
describe "with :async => true and an :on_complete callback" do
|
|
19
|
+
let(:callback) { lambda { |rec| @rec.push rec } }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
expect_component_execution_asynchronously component
|
|
23
|
+
@rec = Queue.new
|
|
24
|
+
options.merge! :async => true, :on_complete => callback
|
|
25
|
+
subject.record options
|
|
26
|
+
component.request!
|
|
27
|
+
component.execute!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should execute the callback" do
|
|
31
|
+
component.trigger_event_handler response
|
|
32
|
+
Timeout::timeout 5 do
|
|
33
|
+
@rec.pop.should == response
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "when the callback raises an exception" do
|
|
38
|
+
before { TestException = Class.new StandardError }
|
|
39
|
+
let(:callback) { lambda { |rec| raise TestException } }
|
|
40
|
+
|
|
41
|
+
it "should pass the exception to the events system" do
|
|
42
|
+
flexmock(Events).should_receive(:trigger).once.with(:exception, TestException)
|
|
43
|
+
component.trigger_event_handler response
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "with :async => false" do
|
|
49
|
+
before do
|
|
50
|
+
expect_component_execution component
|
|
51
|
+
component.request!
|
|
52
|
+
component.execute!
|
|
53
|
+
component.add_event response
|
|
54
|
+
@rec = Queue.new
|
|
55
|
+
subject.record(options.merge(:async => false)) { |rec| @rec.push rec }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should execute a passed block' do
|
|
59
|
+
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
|
|
106
|
+
end
|
|
107
|
+
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
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Adhearsion
|
|
4
|
+
describe CallController do
|
|
5
|
+
include CallControllerTestHelpers
|
|
6
|
+
|
|
7
|
+
let(:call) { Adhearsion::Call.new mock_offer(nil, :x_foo => 'bar') }
|
|
8
|
+
|
|
9
|
+
its(:call) { should be call }
|
|
10
|
+
its(:metadata) { should == {:doo => :dah} }
|
|
11
|
+
|
|
12
|
+
describe "setting meta-data" do
|
|
13
|
+
it "should preserve data correctly" do
|
|
14
|
+
subject[:foo].should be nil
|
|
15
|
+
subject[:foo] = 7
|
|
16
|
+
subject[:foo].should == 7
|
|
17
|
+
subject[:bar] = 10
|
|
18
|
+
subject[:bar].should == 10
|
|
19
|
+
subject[:foo].should == 7
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should add plugin dialplan methods" do
|
|
24
|
+
subject.should respond_to :foo
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
its(:logger) { should be call.logger }
|
|
28
|
+
its(:variables) { should be call.variables }
|
|
29
|
+
|
|
30
|
+
describe "execution on a call" do
|
|
31
|
+
before do
|
|
32
|
+
flexmock subject, :execute_component_and_await_completion => nil
|
|
33
|
+
flexmock call, :write_and_await_response => nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "when auto-accept is enabled" do
|
|
37
|
+
before do
|
|
38
|
+
Adhearsion.config.platform.automatically_accept_incoming_calls = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should accept the call" do
|
|
42
|
+
subject.should_receive(:accept).once.ordered
|
|
43
|
+
subject.should_receive(:run).once.ordered
|
|
44
|
+
subject.execute!
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "and accept is skipped" do
|
|
48
|
+
before { subject.skip_accept! }
|
|
49
|
+
|
|
50
|
+
it "should not accept the call" do
|
|
51
|
+
subject.should_receive(:accept).never
|
|
52
|
+
subject.should_receive(:run).once
|
|
53
|
+
subject.execute!
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "when auto-accept is disabled" do
|
|
59
|
+
before do
|
|
60
|
+
Adhearsion.config.platform.automatically_accept_incoming_calls = false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should not accept the call" do
|
|
64
|
+
subject.should_receive(:accept).never
|
|
65
|
+
subject.should_receive(:run).once
|
|
66
|
+
subject.execute!
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "catches Hangup exceptions and logs the hangup" do
|
|
71
|
+
subject.should_receive(:run).once.and_raise(Hangup).ordered
|
|
72
|
+
flexmock(subject.logger).should_receive(:info).once.with(/Call was hung up/).ordered
|
|
73
|
+
subject.execute!
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "catches standard errors, triggering an exception event" do
|
|
77
|
+
subject.should_receive(:run).once.and_raise(StandardError).ordered
|
|
78
|
+
flexmock(Events).should_receive(:trigger).once.with(:exception, StandardError).ordered
|
|
79
|
+
subject.execute!
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class SecondController < CallController
|
|
84
|
+
def run
|
|
85
|
+
md_check metadata
|
|
86
|
+
answer
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def md_check(md)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class SecondControllerWithRemoteHangup < SecondController
|
|
94
|
+
def run
|
|
95
|
+
super
|
|
96
|
+
simulate_remote_hangup
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def simulate_remote_hangup
|
|
100
|
+
raise Hangup
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "#invoke" do
|
|
105
|
+
class InvokeController < CallController
|
|
106
|
+
def run
|
|
107
|
+
before
|
|
108
|
+
invoke second_controller, :foo => 'bar'
|
|
109
|
+
after
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def before
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def after
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def second_controller
|
|
119
|
+
metadata[:second_controller] || SecondController
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
subject { InvokeController.new call }
|
|
124
|
+
|
|
125
|
+
before do
|
|
126
|
+
flexmock subject, :execute_component_and_await_completion => nil
|
|
127
|
+
flexmock call, :write_and_await_response => nil
|
|
128
|
+
flexmock(Events).should_receive(:trigger).with(:exception, Exception).never
|
|
129
|
+
Adhearsion.config.platform.automatically_accept_incoming_calls = true
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should invoke another controller before returning to the current controller" do
|
|
133
|
+
subject.should_receive(:before).once.ordered
|
|
134
|
+
call.should_receive(:answer).once.ordered
|
|
135
|
+
subject.should_receive(:after).once.ordered
|
|
136
|
+
|
|
137
|
+
subject.execute!
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should invoke the new controller with metadata" do
|
|
141
|
+
flexmock(SecondController).new_instances.should_receive(:md_check).once.with :foo => 'bar'
|
|
142
|
+
subject.execute!
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should not attempt to accept the call again" do
|
|
146
|
+
call.should_receive(:accept).once
|
|
147
|
+
|
|
148
|
+
subject.execute!
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should allow the outer controller to cease execution and handle remote hangups" do
|
|
152
|
+
subject[:second_controller] = SecondControllerWithRemoteHangup
|
|
153
|
+
|
|
154
|
+
subject.should_receive(:before).once.ordered
|
|
155
|
+
call.should_receive(:answer).once.ordered
|
|
156
|
+
subject.should_receive(:after).never.ordered
|
|
157
|
+
|
|
158
|
+
subject.execute!
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
describe "#pass" do
|
|
163
|
+
class PassController < CallController
|
|
164
|
+
after_call :foobar
|
|
165
|
+
|
|
166
|
+
def run
|
|
167
|
+
before
|
|
168
|
+
pass SecondController, :foo => 'bar'
|
|
169
|
+
after
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def before
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def after
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def foobar
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
subject { PassController.new call }
|
|
183
|
+
|
|
184
|
+
before do
|
|
185
|
+
flexmock(call).should_receive(:write_and_await_response).and_return nil
|
|
186
|
+
flexmock subject, :execute_component_and_await_completion => nil
|
|
187
|
+
flexmock(SecondController).new_instances.should_receive(:md_check).once.with :foo => 'bar'
|
|
188
|
+
flexmock(Events).should_receive(:trigger).with(:exception, Exception).never
|
|
189
|
+
Adhearsion.config.platform.automatically_accept_incoming_calls = true
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
let(:latch) { CountDownLatch.new 1 }
|
|
193
|
+
|
|
194
|
+
it "should cease execution of the current controller, and instruct the call to execute another" do
|
|
195
|
+
subject.should_receive(:before).once.ordered
|
|
196
|
+
call.should_receive(:answer).once.ordered
|
|
197
|
+
subject.should_receive(:after).never.ordered
|
|
198
|
+
call.should_receive(:hangup!).once.ordered
|
|
199
|
+
|
|
200
|
+
call.execute_controller subject, latch
|
|
201
|
+
latch.wait(1).should be_true
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should not attempt to accept the call again" do
|
|
205
|
+
call.should_receive(:accept).once
|
|
206
|
+
|
|
207
|
+
CallController.exec subject
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "should execute after_call callbacks before passing control" do
|
|
211
|
+
subject.should_receive(:before).once.ordered
|
|
212
|
+
subject.should_receive(:foobar).once.ordered
|
|
213
|
+
call.should_receive(:answer).once.ordered
|
|
214
|
+
|
|
215
|
+
CallController.exec subject
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
describe '#write_and_await_response' do
|
|
220
|
+
let(:message) { Punchblock::Command::Accept.new }
|
|
221
|
+
|
|
222
|
+
it "delegates to the call" do
|
|
223
|
+
flexmock(subject.call).should_receive(:write_and_await_response).once.with(message, 20)
|
|
224
|
+
subject.write_and_await_response message, 20
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
describe "#execute_component_and_await_completion" do
|
|
229
|
+
let(:component) { Punchblock::Component::Output.new }
|
|
230
|
+
let(:response) { Punchblock::Event::Complete.new }
|
|
231
|
+
|
|
232
|
+
before do
|
|
233
|
+
expect_message_waiting_for_response component
|
|
234
|
+
component.execute!
|
|
235
|
+
component.complete_event = response
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "writes component to the server and waits on response" do
|
|
239
|
+
subject.execute_component_and_await_completion component
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "takes a block which is executed after acknowledgement but before waiting on completion" do
|
|
243
|
+
@comp = nil
|
|
244
|
+
subject.execute_component_and_await_completion(component) { |comp| @comp = comp }.should == component
|
|
245
|
+
@comp.should == component
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
describe "with a successful completion" do
|
|
249
|
+
it "returns the executed component" do
|
|
250
|
+
subject.execute_component_and_await_completion(component).should be component
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
describe "with an error response" do
|
|
255
|
+
let(:response) do
|
|
256
|
+
Punchblock::Event::Complete.new.tap do |complete|
|
|
257
|
+
complete << error
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
let(:error) do |error|
|
|
262
|
+
Punchblock::Event::Complete::Error.new.tap do |error|
|
|
263
|
+
error << details
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
let(:details) { "Oh noes, it's all borked" }
|
|
268
|
+
|
|
269
|
+
it "raises the error" do
|
|
270
|
+
lambda { subject.execute_component_and_await_completion component }.should raise_error(StandardError, details)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it "blocks until the component receives a complete event" do
|
|
275
|
+
slow_component = Punchblock::Component::Output.new
|
|
276
|
+
Thread.new do
|
|
277
|
+
sleep 0.5
|
|
278
|
+
slow_component.complete_event = response
|
|
279
|
+
end
|
|
280
|
+
starting_time = Time.now
|
|
281
|
+
subject.execute_component_and_await_completion slow_component
|
|
282
|
+
(Time.now - starting_time).should > 0.5
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
describe '#accept' do
|
|
287
|
+
it "should delegate to the call" do
|
|
288
|
+
flexmock(subject.call).should_receive(:accept).once.with(:foo)
|
|
289
|
+
subject.accept :foo
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
describe '#answer' do
|
|
294
|
+
it "should delegate to the call" do
|
|
295
|
+
flexmock(subject.call).should_receive(:answer).once.with(:foo)
|
|
296
|
+
subject.answer :foo
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
describe '#reject' do
|
|
301
|
+
it "should delegate to the call" do
|
|
302
|
+
flexmock(subject.call).should_receive(:reject).once.with(:foo, :bar)
|
|
303
|
+
subject.reject :foo, :bar
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
describe '#hangup' do
|
|
308
|
+
it "should delegate to the call" do
|
|
309
|
+
flexmock(subject.call).should_receive(:hangup!).once.with(:foo)
|
|
310
|
+
subject.hangup :foo
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
describe '#mute' do
|
|
315
|
+
it 'should send a Mute message' do
|
|
316
|
+
expect_message_waiting_for_response Punchblock::Command::Mute.new
|
|
317
|
+
subject.mute
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
describe '#unmute' do
|
|
322
|
+
it 'should send an Unmute message' do
|
|
323
|
+
expect_message_waiting_for_response Punchblock::Command::Unmute.new
|
|
324
|
+
subject.unmute
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
class ExampleCallController < Adhearsion::CallController
|
|
331
|
+
before_call { setup_models }
|
|
332
|
+
before_call :setup_models
|
|
333
|
+
|
|
334
|
+
after_call { clean_up_models }
|
|
335
|
+
after_call :clean_up_models
|
|
336
|
+
|
|
337
|
+
def setup_models
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def clean_up_models
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def run
|
|
344
|
+
join_to_conference
|
|
345
|
+
hangup unless metadata[:skip_hangup]
|
|
346
|
+
foobar
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def join_to_conference
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def foobar
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
describe ExampleCallController do
|
|
357
|
+
include CallControllerTestHelpers
|
|
358
|
+
|
|
359
|
+
before do
|
|
360
|
+
flexmock subject, :execute_component_and_await_completion => nil
|
|
361
|
+
flexmock call, :write_and_await_response => nil
|
|
362
|
+
Adhearsion.config.platform.automatically_accept_incoming_calls = true
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "should execute the before_call callbacks before accepting the call" do
|
|
366
|
+
subject.should_receive(:setup_models).twice.ordered
|
|
367
|
+
subject.should_receive(:accept).once.ordered
|
|
368
|
+
subject.should_receive(:join_to_conference).once.ordered
|
|
369
|
+
subject.execute!
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "should execute the after_call callbacks after the call is hung up" do
|
|
373
|
+
subject.should_receive(:join_to_conference).once.ordered
|
|
374
|
+
subject.should_receive(:clean_up_models).twice.ordered
|
|
375
|
+
subject.should_receive(:foobar).once.ordered
|
|
376
|
+
subject.execute!
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it "should capture errors in callbacks" do
|
|
380
|
+
subject.should_receive(:setup_models).and_raise StandardError
|
|
381
|
+
subject.should_receive(:clean_up_models).and_raise StandardError
|
|
382
|
+
flexmock(Adhearsion::Events).should_receive(:trigger).times(4).with :exception, StandardError
|
|
383
|
+
subject.execute!
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
context "when the controller finishes without a hangup" do
|
|
387
|
+
it "should execute the after_call callbacks" do
|
|
388
|
+
subject[:skip_hangup] = true
|
|
389
|
+
subject.should_receive(:join_to_conference).once.ordered
|
|
390
|
+
subject.should_receive(:foobar).once.ordered
|
|
391
|
+
subject.should_receive(:clean_up_models).twice.ordered
|
|
392
|
+
subject.execute!
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|