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.
Files changed (236) hide show
  1. data/.gitignore +17 -10
  2. data/CHANGELOG.md +273 -0
  3. data/Gemfile +1 -1
  4. data/Guardfile +17 -0
  5. data/README.markdown +61 -9
  6. data/Rakefile +16 -48
  7. data/adhearsion.gemspec +21 -7
  8. data/bin/ahn +3 -1
  9. data/cucumber.yml +4 -0
  10. data/features/app_generator.feature +42 -0
  11. data/features/cli.feature +108 -0
  12. data/features/step_definitions/app_generator_steps.rb +6 -0
  13. data/features/step_definitions/cli_steps.rb +74 -0
  14. data/features/support/aruba_helper.rb +22 -0
  15. data/features/support/env.rb +37 -0
  16. data/features/support/utils.rb +8 -0
  17. data/lib/adhearsion.rb +85 -41
  18. data/lib/adhearsion/call.rb +176 -0
  19. data/lib/adhearsion/call_controller.rb +134 -0
  20. data/lib/adhearsion/call_controller/dial.rb +70 -0
  21. data/lib/adhearsion/call_controller/input.rb +173 -0
  22. data/lib/adhearsion/call_controller/menu.rb +124 -0
  23. data/lib/adhearsion/call_controller/output.rb +267 -0
  24. data/lib/adhearsion/call_controller/record.rb +42 -0
  25. data/lib/adhearsion/call_controller/utility.rb +60 -0
  26. data/lib/adhearsion/calls.rb +81 -0
  27. data/lib/adhearsion/cli.rb +1 -3
  28. data/lib/adhearsion/cli_commands.rb +142 -0
  29. data/lib/adhearsion/configuration.rb +149 -0
  30. data/lib/adhearsion/console.rb +19 -8
  31. data/lib/adhearsion/dialplan_controller.rb +9 -0
  32. data/lib/adhearsion/events.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +0 -7
  34. data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
  35. data/lib/adhearsion/foundation/exception_handler.rb +9 -0
  36. data/lib/adhearsion/foundation/object.rb +26 -8
  37. data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
  38. data/lib/adhearsion/foundation/thread_safety.rb +17 -1
  39. data/lib/adhearsion/generators/app/app_generator.rb +4 -13
  40. data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
  41. data/lib/adhearsion/generators/app/templates/Procfile +1 -0
  42. data/lib/adhearsion/generators/app/templates/README.md +28 -0
  43. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
  44. data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
  45. data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
  46. data/lib/adhearsion/initializer.rb +151 -293
  47. data/lib/adhearsion/initializer/logging.rb +33 -0
  48. data/lib/adhearsion/logging.rb +65 -69
  49. data/lib/adhearsion/menu_dsl.rb +15 -0
  50. data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
  52. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
  53. data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
  54. data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
  55. data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
  56. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
  57. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
  58. data/lib/adhearsion/outbound_call.rb +64 -0
  59. data/lib/adhearsion/plugin.rb +319 -0
  60. data/lib/adhearsion/plugin/collection.rb +19 -0
  61. data/lib/adhearsion/plugin/initializer.rb +37 -0
  62. data/lib/adhearsion/plugin/methods_container.rb +6 -0
  63. data/lib/adhearsion/process.rb +94 -0
  64. data/lib/adhearsion/punchblock_plugin.rb +29 -0
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
  66. data/lib/adhearsion/router.rb +30 -0
  67. data/lib/adhearsion/router/route.rb +42 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -2
  69. data/lib/adhearsion/tasks.rb +14 -9
  70. data/lib/adhearsion/tasks/configuration.rb +26 -0
  71. data/lib/adhearsion/tasks/plugins.rb +17 -0
  72. data/lib/adhearsion/version.rb +8 -14
  73. data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
  74. data/spec/adhearsion/call_controller/input_spec.rb +278 -0
  75. data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
  76. data/spec/adhearsion/call_controller/output_spec.rb +466 -0
  77. data/spec/adhearsion/call_controller/record_spec.rb +125 -0
  78. data/spec/adhearsion/call_controller_spec.rb +395 -0
  79. data/spec/adhearsion/call_spec.rb +438 -0
  80. data/spec/adhearsion/calls_spec.rb +47 -0
  81. data/spec/adhearsion/configuration_spec.rb +308 -0
  82. data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
  83. data/spec/adhearsion/events_spec.rb +112 -0
  84. data/spec/adhearsion/initializer/logging_spec.rb +58 -0
  85. data/spec/adhearsion/initializer_spec.rb +209 -122
  86. data/spec/adhearsion/logging_spec.rb +58 -47
  87. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
  88. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
  89. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
  90. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
  91. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
  92. data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
  93. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
  94. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
  95. data/spec/adhearsion/menu_dsl_spec.rb +12 -0
  96. data/spec/adhearsion/outbound_call_spec.rb +174 -0
  97. data/spec/adhearsion/plugin_spec.rb +489 -0
  98. data/spec/adhearsion/process_spec.rb +34 -0
  99. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
  100. data/spec/adhearsion/router/route_spec.rb +99 -0
  101. data/spec/adhearsion/router_spec.rb +106 -0
  102. data/spec/adhearsion_spec.rb +46 -0
  103. data/spec/spec_helper.rb +14 -14
  104. data/spec/support/call_controller_test_helpers.rb +48 -0
  105. data/spec/support/initializer_stubs.rb +8 -13
  106. data/spec/support/punchblock_mocks.rb +6 -0
  107. metadata +255 -253
  108. data/CHANGELOG +0 -174
  109. data/bin/ahnctl +0 -68
  110. data/bin/jahn +0 -43
  111. data/examples/asterisk_manager_interface/standalone.rb +0 -51
  112. data/lib/adhearsion/commands.rb +0 -302
  113. data/lib/adhearsion/component_manager.rb +0 -278
  114. data/lib/adhearsion/component_manager/component_tester.rb +0 -54
  115. data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
  116. data/lib/adhearsion/events_support.rb +0 -65
  117. data/lib/adhearsion/foundation/blank_slate.rb +0 -3
  118. data/lib/adhearsion/foundation/event_socket.rb +0 -205
  119. data/lib/adhearsion/foundation/future_resource.rb +0 -36
  120. data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
  121. data/lib/adhearsion/foundation/numeric.rb +0 -13
  122. data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
  123. data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
  124. data/lib/adhearsion/foundation/string.rb +0 -26
  125. data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
  126. data/lib/adhearsion/generators/app/templates/README +0 -8
  127. data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
  128. data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
  129. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
  130. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
  131. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
  132. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
  133. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
  134. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
  135. data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
  136. data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
  137. data/lib/adhearsion/generators/app/templates/events.rb +0 -33
  138. data/lib/adhearsion/host_definitions.rb +0 -67
  139. data/lib/adhearsion/initializer/asterisk.rb +0 -86
  140. data/lib/adhearsion/initializer/configuration.rb +0 -324
  141. data/lib/adhearsion/initializer/database.rb +0 -60
  142. data/lib/adhearsion/initializer/drb.rb +0 -31
  143. data/lib/adhearsion/initializer/freeswitch.rb +0 -22
  144. data/lib/adhearsion/initializer/ldap.rb +0 -57
  145. data/lib/adhearsion/initializer/rails.rb +0 -41
  146. data/lib/adhearsion/initializer/xmpp.rb +0 -42
  147. data/lib/adhearsion/tasks/components.rb +0 -32
  148. data/lib/adhearsion/tasks/database.rb +0 -5
  149. data/lib/adhearsion/tasks/deprecations.rb +0 -59
  150. data/lib/adhearsion/tasks/generating.rb +0 -20
  151. data/lib/adhearsion/tasks/lint.rb +0 -4
  152. data/lib/adhearsion/voip/asterisk.rb +0 -4
  153. data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
  154. data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
  155. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
  156. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
  157. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
  158. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
  159. data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
  160. data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
  161. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
  162. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
  163. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
  164. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
  165. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
  166. data/lib/adhearsion/voip/call.rb +0 -521
  167. data/lib/adhearsion/voip/call_routing.rb +0 -64
  168. data/lib/adhearsion/voip/commands.rb +0 -17
  169. data/lib/adhearsion/voip/constants.rb +0 -39
  170. data/lib/adhearsion/voip/conveniences.rb +0 -18
  171. data/lib/adhearsion/voip/dial_plan.rb +0 -252
  172. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
  173. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
  174. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
  175. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
  176. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
  177. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
  178. data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
  179. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
  180. data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
  181. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
  182. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
  183. data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
  184. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
  185. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
  186. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
  187. data/lib/adhearsion/xmpp/connection.rb +0 -61
  188. data/lib/theatre.rb +0 -147
  189. data/lib/theatre/README.markdown +0 -64
  190. data/lib/theatre/callback_definition_loader.rb +0 -86
  191. data/lib/theatre/guid.rb +0 -23
  192. data/lib/theatre/invocation.rb +0 -131
  193. data/lib/theatre/namespace_manager.rb +0 -153
  194. data/lib/theatre/version.rb +0 -2
  195. data/spec/adhearsion/cli_spec.rb +0 -306
  196. data/spec/adhearsion/component_manager_spec.rb +0 -292
  197. data/spec/adhearsion/constants_spec.rb +0 -8
  198. data/spec/adhearsion/drb_spec.rb +0 -65
  199. data/spec/adhearsion/fixtures/dialplan.rb +0 -3
  200. data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
  201. data/spec/adhearsion/host_definitions_spec.rb +0 -79
  202. data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
  203. data/spec/adhearsion/initializer/loading_spec.rb +0 -154
  204. data/spec/adhearsion/initializer/paths_spec.rb +0 -74
  205. data/spec/adhearsion/relationship_properties_spec.rb +0 -54
  206. data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
  207. data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
  208. data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
  209. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
  210. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
  211. data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
  212. data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
  213. data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
  214. data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
  215. data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
  216. data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
  217. data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
  218. data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
  219. data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
  220. data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
  221. data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
  222. data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
  223. data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
  224. data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
  225. data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
  226. data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
  227. data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
  228. data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
  229. data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
  230. data/spec/support/the_following_code.rb +0 -3
  231. data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
  232. data/spec/theatre/dsl_spec.rb +0 -69
  233. data/spec/theatre/invocation_spec.rb +0 -182
  234. data/spec/theatre/namespace_spec.rb +0 -125
  235. data/spec/theatre/spec_helper_spec.rb +0 -28
  236. data/spec/theatre/theatre_class_spec.rb +0 -148
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ module MenuDSL
5
+
6
+ describe RangeMatchCalculator do
7
+ it "matching with a Range should handle the case of two potential matches in the range" do
8
+ digits_that_begin_with_eleven = [110..119, 1100..1111].map { |x| Array(x) }.flatten
9
+ calculator = RangeMatchCalculator.new 11..1111, :match_payload_doesnt_matter
10
+ match = calculator.match 11
11
+ match.exact_matches.should == [11]
12
+ match.potential_matches.should == digits_that_begin_with_eleven
13
+ end
14
+
15
+ it "return values of #match should be an instance of CalculatedMatch" do
16
+ calculator = RangeMatchCalculator.new 1..9, :match_payload_doesnt_matter
17
+ calculator.match(0).should be_an_instance_of CalculatedMatch
18
+ calculator.match(1000).should be_an_instance_of CalculatedMatch
19
+ end
20
+
21
+ it "returns a failed match if the query is not numeric or coercible to numeric" do
22
+ calculator = RangeMatchCalculator.new 1..9, :match_payload_doesnt_matter
23
+ calculator.match("ABC").should be_an_instance_of CalculatedMatch
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ module MenuDSL
5
+ describe StringMatchCalculator do
6
+
7
+ let(:match_payload) { :doesnt_matter }
8
+
9
+ it "numerical digits mixed with special digits" do
10
+ %w[5*11#3 5*** ###].each do |str|
11
+ calculator = StringMatchCalculator.new str, match_payload
12
+
13
+ match_case = calculator.match str[0,2]
14
+ match_case.exact_match?.should_not be true
15
+ match_case.potential_match?.should be true
16
+ match_case.potential_matches.should == [str]
17
+
18
+ match_case = calculator.match str
19
+ match_case.exact_match?.should be true
20
+ match_case.potential_match?.should_not be true
21
+ match_case.exact_matches.should == [str]
22
+ end
23
+ end
24
+
25
+ it "matching the special DTMF characters such as * and #" do
26
+ %w[* #].each do |special_digit|
27
+ calculator = StringMatchCalculator.new(special_digit, match_payload)
28
+ match_case = calculator.match special_digit
29
+ match_case.potential_match?.should_not be true
30
+ match_case.exact_match?.should be true
31
+ match_case.exact_matches.first.should == special_digit
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ describe MenuDSL do
5
+ it "should accept hash options"
6
+
7
+ it "should accept hash options and block"
8
+
9
+ it "should accept hash options and block and evaluate block"
10
+ end
11
+ end
12
+
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ describe OutboundCall do
5
+ it { should be_a Call }
6
+
7
+ its(:id) { should be_nil }
8
+ its(:variables) { should == {} }
9
+
10
+ let(:mock_client) { flexmock 'Punchblock Client' }
11
+
12
+ before do
13
+ PunchblockPlugin::Initializer.client = mock_client
14
+ end
15
+
16
+ its(:client) { should be mock_client }
17
+
18
+ describe ".originate" do
19
+ let(:to) { 'sip:foo@bar.com' }
20
+
21
+ let(:mock_call) { OutboundCall.new }
22
+
23
+ def mock_dial
24
+ flexmock(OutboundCall).new_instances.should_receive(:dial).and_return true
25
+ end
26
+
27
+ it "should create a new call and return it" do
28
+ mock_dial
29
+ OutboundCall.originate(to).should be_a OutboundCall
30
+ end
31
+
32
+ it "should dial the call to the correct endpoint" do
33
+ mock_call
34
+ flexmock(OutboundCall).should_receive(:new).and_return mock_call
35
+ flexmock(mock_call).should_receive(:dial).with(to, :from => 'foo').once
36
+ OutboundCall.originate to, :from => 'foo'
37
+ end
38
+
39
+ it "should run through the router when the call is answered" do
40
+ mock_call
41
+
42
+ flexmock(OutboundCall).should_receive(:new).and_return mock_call
43
+ flexmock(mock_call).should_receive(:dial).once
44
+
45
+ mock_dispatcher = flexmock 'dispatcher'
46
+ mock_dispatcher.should_receive(:call).once.with mock_call
47
+ flexmock(Adhearsion.router).should_receive(:handle).once.with(mock_call).and_return mock_dispatcher
48
+
49
+ OutboundCall.originate(to).deliver_message Punchblock::Event::Answered.new
50
+ end
51
+ end
52
+
53
+ describe "event handlers" do
54
+ let(:response) { flexmock 'Response' }
55
+
56
+ describe "for answered events" do
57
+ let(:event) { Punchblock::Event::Answered.new }
58
+
59
+ it "should trigger any on_answer callbacks set" do
60
+ response.should_receive(:call).once.with(event)
61
+ subject.on_answer { |event| response.call event }
62
+ subject << event
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "#dial" do
68
+ def expect_message_waiting_for_response(message)
69
+ flexmock(subject).should_receive(:write_and_await_response).once.with(message).and_return do
70
+ message.call_id = call_id
71
+ message
72
+ end
73
+ end
74
+
75
+ let(:call_id) { 'abc123' }
76
+ let(:to) { '+1800 555-0199' }
77
+ let(:from) { '+1800 555-0122' }
78
+
79
+ let(:expected_dial_command) { Punchblock::Command::Dial.new(:to => to, :from => from) }
80
+
81
+ before do
82
+ expect_message_waiting_for_response expected_dial_command
83
+ end
84
+
85
+ it "should send a dial stanza, wait for the response" do
86
+ subject.dial to, :from => from
87
+ end
88
+
89
+ it "should set the dial command" do
90
+ subject.dial to, :from => from
91
+ subject.dial_command.should == expected_dial_command
92
+ end
93
+
94
+ it "should set the call ID from the dial command" do
95
+ subject.dial to, :from => from
96
+ subject.id.should == call_id
97
+ end
98
+
99
+ it "should add the call to the active calls registry" do
100
+ Adhearsion.active_calls.clear!
101
+ subject.dial to, :from => from
102
+ Adhearsion.active_calls[call_id].should be subject
103
+ end
104
+ end
105
+
106
+ describe "basic control commands" do
107
+ def expect_no_message_waiting_for_response
108
+ flexmock(subject).should_receive(:write_and_await_response).never
109
+ end
110
+
111
+ describe '#accept' do
112
+ describe "with no headers" do
113
+ it 'should not send any message' do
114
+ expect_no_message_waiting_for_response
115
+ subject.accept
116
+ end
117
+ end
118
+
119
+ describe "with headers set" do
120
+ it 'should not send any message' do
121
+ expect_no_message_waiting_for_response
122
+ subject.accept :foo => 'bar'
123
+ end
124
+ end
125
+ end
126
+
127
+ describe '#answer' do
128
+ describe "with no headers" do
129
+ it 'should not send any message' do
130
+ expect_no_message_waiting_for_response
131
+ subject.answer
132
+ end
133
+ end
134
+
135
+ describe "with headers set" do
136
+ it 'should not send any message' do
137
+ expect_no_message_waiting_for_response
138
+ subject.answer :foo => 'bar'
139
+ end
140
+ end
141
+ end
142
+
143
+ describe '#reject' do
144
+ describe "with a reason given" do
145
+ it 'should not send any message' do
146
+ expect_no_message_waiting_for_response
147
+ subject.reject :decline
148
+ end
149
+ end
150
+
151
+ describe "with no reason given" do
152
+ it 'should not send any message' do
153
+ expect_no_message_waiting_for_response
154
+ subject.reject
155
+ end
156
+ end
157
+
158
+ describe "with no headers" do
159
+ it 'should not send any message' do
160
+ expect_no_message_waiting_for_response
161
+ subject.reject
162
+ end
163
+ end
164
+
165
+ describe "with headers set" do
166
+ it 'should not send any message' do
167
+ expect_no_message_waiting_for_response
168
+ subject.reject nil, :foo => 'bar'
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,489 @@
1
+ require 'spec_helper'
2
+
3
+ include InitializerStubs
4
+
5
+ describe Adhearsion::Plugin do
6
+
7
+ describe "inheritance" do
8
+ after do
9
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
10
+ end
11
+
12
+ it "should provide the plugin name in a plugin class" do
13
+ ::FooBar = Class.new Adhearsion::Plugin
14
+ ::FooBar.plugin_name.should == "foo_bar"
15
+ end
16
+
17
+ it "should provide the plugin name in a plugin instance" do
18
+ ::FooBar = Class.new Adhearsion::Plugin
19
+ ::FooBar.new.plugin_name.should == "foo_bar"
20
+ end
21
+
22
+ it "should provide a setter for plugin name" do
23
+ ::FooBar = Class.new Adhearsion::Plugin do
24
+ self.plugin_name = "bar_foo"
25
+ end
26
+
27
+ ::FooBar.plugin_name.should == "bar_foo"
28
+ end
29
+ end
30
+
31
+ describe "metaprogramming" do
32
+ Adhearsion::Plugin::SCOPE_NAMES.each do |method|
33
+ it "should respond to #{method.to_s}" do
34
+ Adhearsion::Plugin.should respond_to method
35
+ end
36
+
37
+ it "should respond to #{method.to_s}_module" do
38
+ Adhearsion::Plugin.should respond_to "#{method.to_s}_module"
39
+ end
40
+ end
41
+ end
42
+
43
+ [:rpc, :dialplan, :console].each do |method|
44
+
45
+ describe "extending an object with #{method.to_s} scope methods" do
46
+
47
+ before(:all) do
48
+ A = Class.new do
49
+ def bar
50
+ "bar"
51
+ end
52
+ end
53
+ end
54
+
55
+ after(:all) do
56
+ defined?(A) and Object.send(:remove_const, :"A")
57
+ end
58
+
59
+ before do
60
+ FooBar = Class.new Adhearsion::Plugin do
61
+ self.method(method).call(:foo) do
62
+ "foo".concat bar
63
+ end
64
+
65
+ end
66
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
67
+ Adhearsion::Plugin.load_plugins
68
+ Adhearsion::Plugin.send("#{method.to_s}_module".to_sym).instance_methods.map{|x| x.to_s}.include?("foo").should == true
69
+ end
70
+
71
+ after do
72
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
73
+ end
74
+
75
+ describe "when extending a Class" do
76
+ it "should respond to any of the #{method.to_s} scope methods and have visibility to the own instance methods" do
77
+
78
+ Adhearsion::Plugin.send("add_#{method}_methods".to_sym, A)
79
+ a = A.new
80
+ a.should respond_to :foo
81
+ a.foo.should == "foobar"
82
+ end
83
+ end
84
+
85
+ describe "when extending an instance" do
86
+ it "should respond to any of the scope methods and have visibility to the own instance methods" do
87
+
88
+ a = A.new
89
+ Adhearsion::Plugin.send("add_#{method}_methods".to_sym, a)
90
+ a.should respond_to :foo
91
+ a.foo.should == "foobar"
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "While adding console methods" do
98
+
99
+ it "should add a new method to Console" do
100
+ FooBar = Class.new Adhearsion::Plugin do
101
+ console :config do
102
+ Adhearsion.config
103
+ end
104
+ end
105
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
106
+ Adhearsion::Plugin.load_plugins
107
+ Adhearsion::Console.should respond_to(:config)
108
+ Adhearsion::Console.config.should == Adhearsion.config
109
+ end
110
+ end
111
+
112
+ describe "While configuring plugins" do
113
+ after(:each) do
114
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
115
+ end
116
+
117
+ subject {
118
+ Class.new Adhearsion::Plugin do
119
+ config :bar_foo do
120
+ name "user" , :desc => "name to authenticate user"
121
+ password "password" , :desc => "authentication password"
122
+ host "localhost", :desc => "valid IP or hostname"
123
+ end
124
+ end
125
+ }
126
+
127
+ its(:plugin_name) { should == :bar_foo }
128
+
129
+ its(:config) { should be_instance_of Loquacious::Configuration }
130
+
131
+ it "should keep a default configuration and a description" do
132
+ [:name, :password, :host].each do |value|
133
+ subject.config.should respond_to value
134
+ end
135
+
136
+ subject.config.name.should == "user"
137
+ subject.config.password.should == "password"
138
+ subject.config.host.should == "localhost"
139
+ end
140
+
141
+ it "should return a description of configuration options" do
142
+ subject.show_description.should be_kind_of Loquacious::Configuration::Help
143
+ end
144
+
145
+ describe "while updating config values" do
146
+ it "should return the updated value" do
147
+ subject.config.name = "usera"
148
+ subject.config.name.should == "usera"
149
+ end
150
+ end
151
+
152
+ end
153
+
154
+ describe "add and delete on the air" do
155
+ AhnPluginDemo = Class.new Adhearsion::Plugin
156
+
157
+ it "should add plugins on the air" do
158
+ Adhearsion::Plugin.delete_all
159
+ Adhearsion::Plugin.add AhnPluginDemo
160
+ Adhearsion::Plugin.count.should eql 1
161
+ end
162
+
163
+ it "should delete plugins on the air" do
164
+ Adhearsion::Plugin.delete_all
165
+ Adhearsion::Plugin.add AhnPluginDemo
166
+ Adhearsion::Plugin.count.should eql 1
167
+ Adhearsion::Plugin.delete AhnPluginDemo
168
+ Adhearsion::Plugin.count.should eql 0
169
+ end
170
+ end
171
+
172
+ describe "#count" do
173
+ after(:each) do
174
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
175
+ end
176
+
177
+ it "should count the number of registered plugins" do
178
+ number = Adhearsion::Plugin.count
179
+ FooBar = Class.new Adhearsion::Plugin
180
+ Adhearsion::Plugin.count.should eql(number + 1)
181
+ end
182
+ end
183
+
184
+ describe "Adhearsion::Plugin.load_plugins" do
185
+ before do
186
+ Adhearsion::Plugin.class_eval do
187
+ def self.reset_methods_scope
188
+ @methods_scope = Hash.new { |hash, key| hash[key] = Module.new }
189
+ end
190
+
191
+ def self.reset_subclasses
192
+ @subclasses = nil
193
+ end
194
+ end
195
+
196
+ Adhearsion::Plugin.reset_methods_scope
197
+ Adhearsion::Plugin.reset_subclasses
198
+ end
199
+
200
+ after do
201
+ Adhearsion::Plugin.initializers.clear
202
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
203
+ defined?(FooBarBaz) and Object.send(:remove_const, :"FooBarBaz")
204
+ defined?(FooBarBazz) and Object.send(:remove_const, :"FooBarBazz")
205
+ end
206
+
207
+ describe "while registering plugins initializers" do
208
+ it "should do nothing with a Plugin that has no init method call" do
209
+ FooBar = Class.new Adhearsion::Plugin
210
+
211
+ # 1 => Punchblock. Must be empty once punchblock initializer is an external Plugin
212
+ Adhearsion::Plugin.initializers.should have(1).initializers
213
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
214
+ Adhearsion::Plugin.load_plugins
215
+ end
216
+
217
+ it "should add a initializer when Plugin defines it" do
218
+ FooBar = Class.new Adhearsion::Plugin do
219
+ init :foo_bar do
220
+ FooBar.log "foo bar"
221
+ end
222
+ def self.log
223
+ end
224
+ end
225
+
226
+ flexmock(FooBar).should_receive(:log).once
227
+ Adhearsion::Plugin.initializers.length.should be 1
228
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
229
+ Adhearsion::Plugin.load_plugins
230
+ end
231
+
232
+ it "should initialize all Plugin childs, including deep childs" do
233
+ FooBar = Class.new Adhearsion::Plugin do
234
+ init :foo_bar do
235
+ FooBar.log "foo bar"
236
+ end
237
+
238
+ def self.log
239
+ end
240
+ end
241
+
242
+ FooBarBaz = Class.new FooBar do
243
+ init :foo_bar_baz do
244
+ FooBar.log "foo bar baz"
245
+ end
246
+ end
247
+ FooBarBazz = Class.new FooBar do
248
+ init :foo_bar_bazz do
249
+ FooBar.log "foo bar bazz"
250
+ end
251
+ end
252
+
253
+ flexmock(FooBar).should_receive(:log).times(3)
254
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
255
+ Adhearsion::Plugin.load_plugins
256
+ end
257
+
258
+ it "should allow to include an initializer before another one" do
259
+ FooBar = Class.new Adhearsion::Plugin do
260
+ init :foo_bar do
261
+ FooBar.log "foo bar"
262
+ end
263
+
264
+ def self.log
265
+ end
266
+ end
267
+
268
+ FooBarBaz = Class.new FooBar do
269
+ init :foo_bar_baz, :before => :foo_bar do
270
+ FooBar.log "foo bar baz"
271
+ end
272
+ end
273
+
274
+ Adhearsion::Plugin.initializers.tsort.first.name.should eql :foo_bar_baz
275
+ Adhearsion::Plugin.initializers.tsort.last.name.should eql :foo_bar
276
+ end
277
+
278
+ it "should allow to include an initializer after another one" do
279
+ FooBar = Class.new Adhearsion::Plugin do
280
+ init :foo_bar do
281
+ FooBar.log "foo bar"
282
+ end
283
+
284
+ def self.log
285
+ end
286
+ end
287
+
288
+ FooBarBaz = Class.new FooBar do
289
+ init :foo_bar_baz, :after => :foo_bar_bazz do
290
+ FooBar.log "foo bar baz"
291
+ end
292
+ end
293
+
294
+ FooBarBazz = Class.new FooBar do
295
+ init :foo_bar_bazz do
296
+ FooBar.log "foo bar bazz"
297
+ end
298
+ end
299
+
300
+ Adhearsion::Plugin.initializers.length.should eql 3
301
+ Adhearsion::Plugin.initializers.tsort.first.name.should eql :foo_bar
302
+ Adhearsion::Plugin.initializers.tsort.last.name.should eql :foo_bar_baz
303
+ end
304
+ end
305
+
306
+ [:rpc, :dialplan].each do |method|
307
+ describe "Plugin subclass with #{method.to_s}_method definition" do
308
+ it "should add a method defined using #{method.to_s} method" do
309
+ FooBar = Class.new Adhearsion::Plugin do
310
+ self.method(method).call(:foo)
311
+
312
+ def self.foo(call)
313
+ "bar"
314
+ end
315
+ end
316
+
317
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
318
+ Adhearsion::Plugin.load_plugins
319
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
320
+ end
321
+
322
+ it "should add a method defined using #{method.to_s} method with a block" do
323
+ FooBar = Class.new Adhearsion::Plugin do
324
+ block = lambda{|call| "bar"}
325
+ self.method(method).call(:foo, &block)
326
+ end
327
+
328
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
329
+ Adhearsion::Plugin.load_plugins
330
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
331
+ end
332
+
333
+ it "should add an instance method defined using #{method.to_s} method" do
334
+ FooBar = Class.new Adhearsion::Plugin do
335
+ self.method(method).call(:foo)
336
+ def foo(call)
337
+ call
338
+ end
339
+ end
340
+
341
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
342
+ Adhearsion::Plugin.load_plugins
343
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
344
+ end
345
+
346
+ it "should add an array of methods defined using #{method.to_s} method" do
347
+ FooBar = Class.new Adhearsion::Plugin do
348
+ self.method(method).call([:foo, :bar])
349
+
350
+ def self.foo(call)
351
+ call
352
+ end
353
+
354
+ def self.bar(call)
355
+ "foo"
356
+ end
357
+ end
358
+
359
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
360
+ Adhearsion::Plugin.load_plugins
361
+ [:foo, :bar].each do |_method|
362
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(_method.to_s).should be true
363
+ end
364
+ Adhearsion::Plugin.methods_scope[method].instance_methods.length.should eql 2
365
+ end
366
+
367
+ it "should add an array of instance methods defined using #{method.to_s} method" do
368
+ FooBar = Class.new Adhearsion::Plugin do
369
+ self.method(method).call([:foo, :bar])
370
+ def foo(call)
371
+ call
372
+ end
373
+
374
+ def bar(call)
375
+ call
376
+ end
377
+ end
378
+
379
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
380
+ Adhearsion::Plugin.load_plugins
381
+ [:foo, :bar].each do |_method|
382
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(_method.to_s).should be true
383
+ end
384
+ end
385
+
386
+ it "should add an array of instance and singleton methods defined using #{method.to_s} method" do
387
+ FooBar = Class.new Adhearsion::Plugin do
388
+ self.method(method).call([:foo, :bar])
389
+ def self.foo(call)
390
+ call
391
+ end
392
+
393
+ def bar(call)
394
+ call
395
+ end
396
+ end
397
+
398
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
399
+ Adhearsion::Plugin.load_plugins
400
+ [:foo, :bar].each do |_method|
401
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(_method.to_s).should be true
402
+ end
403
+ end
404
+
405
+ it "should add a method defined using #{method.to_s} method with a specific block" do
406
+ FooBar = Class.new Adhearsion::Plugin do
407
+ self.method(method).call(:foo) do
408
+ "foo"
409
+ end
410
+ end
411
+
412
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
413
+ Adhearsion::Plugin.load_plugins
414
+ Adhearsion::Plugin.methods_scope[method].instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
415
+ Adhearsion::Plugin.send("#{method.to_s}_module".to_sym).instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
416
+ end
417
+ end
418
+ end
419
+
420
+ describe "Plugin subclass with rpc_method and dialplan_method definitions" do
421
+ it "should add a method defined using rpc and a method defined using dialplan" do
422
+ FooBar = Class.new Adhearsion::Plugin do
423
+ rpc :foo
424
+ dialplan :foo
425
+
426
+ def self.foo(call)
427
+ "bar"
428
+ end
429
+ end
430
+
431
+ flexmock(Adhearsion::PunchblockPlugin::Initializer).should_receive(:start).and_return true
432
+ Adhearsion::Plugin.load_plugins
433
+ [:dialplan_module, :rpc_module].each do |_module|
434
+ Adhearsion::Plugin.send(_module).instance_methods.map{|x| x.to_s}.include?(:foo.to_s).should be true
435
+ end
436
+ end
437
+ end
438
+ end
439
+
440
+ describe "while loading rake tasks" do
441
+
442
+ after do
443
+ Adhearsion::Plugin.reset_rake_tasks
444
+ defined?(FooBar) and Object.send(:remove_const, :"FooBar")
445
+ end
446
+
447
+ subject { Adhearsion::Plugin.tasks }
448
+
449
+ it "should return an Array" do
450
+ subject.should be_instance_of Array
451
+ end
452
+
453
+ its(:length) { should == 0 }
454
+
455
+ it "should not load a new task when there is no block in the method call" do
456
+ subject.length.should == 0
457
+ FooBar = Class.new Adhearsion::Plugin do
458
+ tasks
459
+ end
460
+
461
+ subject.length.should == 0
462
+ end
463
+
464
+ it "should load a new task when there is a block in the method call" do
465
+ subject.length.should == 0
466
+ FooBar = Class.new Adhearsion::Plugin do
467
+ tasks do
468
+ puts "foo bar"
469
+ end
470
+ end
471
+ Adhearsion::Plugin.tasks.length.should == 1
472
+ end
473
+
474
+ it "should execute the tasks blocks while loading rake tasks" do
475
+ subject.length.should == 0
476
+ FooBar = Class.new Adhearsion::Plugin do
477
+ tasks do
478
+ FooBar.foo
479
+ end
480
+ def self.foo
481
+ end
482
+ end
483
+ flexmock(FooBar).should_receive(:foo).once
484
+ Adhearsion::Plugin.load_tasks
485
+ end
486
+
487
+ end
488
+
489
+ end