adhearsion 2.6.4 → 3.0.0.beta1

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -9
  3. data/CHANGELOG.md +22 -7
  4. data/Gemfile +2 -0
  5. data/README.markdown +4 -5
  6. data/Rakefile +1 -2
  7. data/adhearsion.gemspec +19 -8
  8. data/features/cli_create.feature +19 -3
  9. data/features/step_definitions/cli_steps.rb +0 -11
  10. data/features/support/env.rb +3 -4
  11. data/lib/adhearsion.rb +48 -27
  12. data/lib/adhearsion/call.rb +34 -50
  13. data/lib/adhearsion/call_controller.rb +6 -12
  14. data/lib/adhearsion/call_controller/dial.rb +15 -53
  15. data/lib/adhearsion/call_controller/input.rb +39 -162
  16. data/lib/adhearsion/call_controller/input/ask_grammar_builder.rb +44 -0
  17. data/lib/adhearsion/call_controller/input/menu_builder.rb +136 -0
  18. data/lib/adhearsion/call_controller/input/prompt_builder.rb +78 -0
  19. data/lib/adhearsion/call_controller/input/result.rb +46 -0
  20. data/lib/adhearsion/call_controller/output.rb +48 -67
  21. data/lib/adhearsion/call_controller/output/abstract_player.rb +3 -3
  22. data/lib/adhearsion/call_controller/output/async_player.rb +3 -3
  23. data/lib/adhearsion/call_controller/output/player.rb +1 -1
  24. data/lib/adhearsion/call_controller/record.rb +23 -8
  25. data/lib/adhearsion/calls.rb +1 -1
  26. data/lib/adhearsion/cli_commands/ahn_command.rb +2 -65
  27. data/lib/adhearsion/cli_commands/thor_errors.rb +0 -6
  28. data/lib/adhearsion/configuration.rb +91 -39
  29. data/lib/adhearsion/core_ext/blather/stanza.rb +41 -0
  30. data/lib/adhearsion/core_ext/blather/stanza/presence.rb +13 -0
  31. data/lib/adhearsion/error.rb +5 -0
  32. data/lib/adhearsion/event.rb +21 -0
  33. data/lib/adhearsion/event/active_speaker.rb +11 -0
  34. data/lib/adhearsion/event/answered.rb +11 -0
  35. data/lib/adhearsion/event/asterisk.rb +10 -0
  36. data/lib/adhearsion/event/asterisk/ami.rb +34 -0
  37. data/lib/adhearsion/event/complete.rb +75 -0
  38. data/lib/adhearsion/event/dtmf.rb +11 -0
  39. data/lib/adhearsion/event/end.rb +22 -0
  40. data/lib/adhearsion/event/input_timers_started.rb +9 -0
  41. data/lib/adhearsion/event/joined.rb +17 -0
  42. data/lib/adhearsion/event/offer.rb +14 -0
  43. data/lib/adhearsion/event/ringing.rb +11 -0
  44. data/lib/adhearsion/event/started_speaking.rb +13 -0
  45. data/lib/adhearsion/event/stopped_speaking.rb +13 -0
  46. data/lib/adhearsion/event/unjoined.rb +17 -0
  47. data/lib/adhearsion/events.rb +47 -66
  48. data/lib/adhearsion/foundation.rb +0 -1
  49. data/lib/adhearsion/foundation/object.rb +0 -5
  50. data/lib/adhearsion/generators/app/app_generator.rb +4 -1
  51. data/lib/adhearsion/generators/app/templates/Gemfile.erb +2 -10
  52. data/lib/adhearsion/generators/app/templates/adhearsion.erb +9 -9
  53. data/lib/adhearsion/generators/app/templates/config.ru +7 -0
  54. data/lib/adhearsion/generators/app/templates/en.yml +4 -0
  55. data/lib/adhearsion/generators/app/templates/events.erb +2 -2
  56. data/lib/adhearsion/generators/app/templates/hello_world.wav +0 -0
  57. data/lib/adhearsion/generators/app/templates/simon_game.rb +2 -1
  58. data/lib/adhearsion/generators/app/templates/simon_game_spec.rb +2 -2
  59. data/lib/adhearsion/has_headers.rb +34 -0
  60. data/lib/adhearsion/http_server.rb +37 -0
  61. data/lib/adhearsion/initializer.rb +19 -153
  62. data/lib/adhearsion/logging.rb +6 -25
  63. data/lib/adhearsion/outbound_call.rb +5 -5
  64. data/lib/adhearsion/plugin.rb +1 -0
  65. data/lib/adhearsion/protocol_error.rb +26 -0
  66. data/lib/adhearsion/rayo.rb +30 -0
  67. data/lib/adhearsion/rayo/client.rb +62 -0
  68. data/lib/adhearsion/rayo/client/component_registry.rb +33 -0
  69. data/lib/adhearsion/rayo/command.rb +21 -0
  70. data/lib/adhearsion/rayo/command/accept.rb +16 -0
  71. data/lib/adhearsion/rayo/command/answer.rb +16 -0
  72. data/lib/adhearsion/rayo/command/dial.rb +57 -0
  73. data/lib/adhearsion/rayo/command/hangup.rb +16 -0
  74. data/lib/adhearsion/rayo/command/join.rb +43 -0
  75. data/lib/adhearsion/rayo/command/mute.rb +13 -0
  76. data/lib/adhearsion/rayo/command/redirect.rb +23 -0
  77. data/lib/adhearsion/rayo/command/reject.rb +40 -0
  78. data/lib/adhearsion/rayo/command/unjoin.rb +24 -0
  79. data/lib/adhearsion/rayo/command/unmute.rb +13 -0
  80. data/lib/adhearsion/rayo/command_node.rb +47 -0
  81. data/lib/adhearsion/rayo/component.rb +21 -0
  82. data/lib/adhearsion/rayo/component/asterisk.rb +13 -0
  83. data/lib/adhearsion/rayo/component/asterisk/agi.rb +14 -0
  84. data/lib/adhearsion/rayo/component/asterisk/agi/command.rb +46 -0
  85. data/lib/adhearsion/rayo/component/asterisk/ami.rb +14 -0
  86. data/lib/adhearsion/rayo/component/asterisk/ami/action.rb +61 -0
  87. data/lib/adhearsion/rayo/component/component_node.rb +90 -0
  88. data/lib/adhearsion/rayo/component/input.rb +186 -0
  89. data/lib/adhearsion/rayo/component/output.rb +471 -0
  90. data/lib/adhearsion/rayo/component/prompt.rb +53 -0
  91. data/lib/adhearsion/rayo/component/receive_fax.rb +26 -0
  92. data/lib/adhearsion/rayo/component/record.rb +165 -0
  93. data/lib/adhearsion/rayo/component/send_fax.rb +64 -0
  94. data/lib/adhearsion/rayo/component/stop.rb +11 -0
  95. data/lib/adhearsion/rayo/connection.rb +12 -0
  96. data/lib/adhearsion/rayo/connection/asterisk.rb +74 -0
  97. data/lib/adhearsion/rayo/connection/connected.rb +22 -0
  98. data/lib/adhearsion/rayo/connection/generic_connection.rb +22 -0
  99. data/lib/adhearsion/rayo/connection/xmpp.rb +198 -0
  100. data/lib/adhearsion/rayo/disconnected_error.rb +22 -0
  101. data/lib/adhearsion/{punchblock_plugin → rayo}/initializer.rb +19 -19
  102. data/lib/adhearsion/rayo/rayo_node.rb +127 -0
  103. data/lib/adhearsion/rayo/ref.rb +57 -0
  104. data/lib/adhearsion/statistics.rb +1 -1
  105. data/lib/adhearsion/tasks.rb +1 -2
  106. data/lib/adhearsion/tasks/configuration.rb +1 -1
  107. data/lib/adhearsion/tasks/environment.rb +0 -2
  108. data/lib/adhearsion/tasks/i18n.rb +49 -0
  109. data/lib/adhearsion/translator.rb +11 -0
  110. data/lib/adhearsion/translator/asterisk.rb +234 -0
  111. data/lib/adhearsion/translator/asterisk/agi_app.rb +17 -0
  112. data/lib/adhearsion/translator/asterisk/agi_command.rb +45 -0
  113. data/lib/adhearsion/translator/asterisk/ami_error_converter.rb +20 -0
  114. data/lib/adhearsion/translator/asterisk/call.rb +416 -0
  115. data/lib/adhearsion/translator/asterisk/channel.rb +43 -0
  116. data/lib/adhearsion/translator/asterisk/component.rb +88 -0
  117. data/lib/adhearsion/translator/asterisk/component/asterisk.rb +15 -0
  118. data/lib/adhearsion/translator/asterisk/component/asterisk/agi_command.rb +42 -0
  119. data/lib/adhearsion/translator/asterisk/component/asterisk/ami_action.rb +68 -0
  120. data/lib/adhearsion/translator/asterisk/component/composed_prompt.rb +76 -0
  121. data/lib/adhearsion/translator/asterisk/component/dtmf_recognizer.rb +137 -0
  122. data/lib/adhearsion/translator/asterisk/component/input.rb +34 -0
  123. data/lib/adhearsion/translator/asterisk/component/input_component.rb +90 -0
  124. data/lib/adhearsion/translator/asterisk/component/mrcp_native_prompt.rb +71 -0
  125. data/lib/adhearsion/translator/asterisk/component/mrcp_prompt.rb +55 -0
  126. data/lib/adhearsion/translator/asterisk/component/mrcp_recog_prompt.rb +165 -0
  127. data/lib/adhearsion/translator/asterisk/component/output.rb +233 -0
  128. data/lib/adhearsion/translator/asterisk/component/record.rb +101 -0
  129. data/lib/adhearsion/translator/asterisk/component/stop_by_redirect.rb +30 -0
  130. data/lib/adhearsion/translator/asterisk/unimrcp_app.rb +28 -0
  131. data/lib/adhearsion/uri_list.rb +21 -0
  132. data/lib/adhearsion/version.rb +1 -1
  133. data/spec/adhearsion/call_controller/dial_spec.rb +79 -1420
  134. data/spec/adhearsion/call_controller/input_spec.rb +1141 -237
  135. data/spec/adhearsion/call_controller/output/async_player_spec.rb +10 -10
  136. data/spec/adhearsion/call_controller/output/player_spec.rb +8 -8
  137. data/spec/adhearsion/call_controller/output_spec.rb +162 -215
  138. data/spec/adhearsion/call_controller/record_spec.rb +15 -16
  139. data/spec/adhearsion/call_controller_spec.rb +23 -40
  140. data/spec/adhearsion/call_spec.rb +123 -129
  141. data/spec/adhearsion/calls_spec.rb +3 -3
  142. data/spec/adhearsion/configuration_spec.rb +94 -108
  143. data/spec/adhearsion/event/answered_spec.rb +50 -0
  144. data/spec/adhearsion/event/asterisk/Find Results +402 -0
  145. data/spec/adhearsion/event/asterisk/ami_spec.rb +81 -0
  146. data/spec/adhearsion/event/complete_spec.rb +176 -0
  147. data/spec/adhearsion/event/dtmf_spec.rb +35 -0
  148. data/spec/adhearsion/event/end_spec.rb +85 -0
  149. data/spec/adhearsion/event/input_timers_started_spec.rb +19 -0
  150. data/spec/adhearsion/event/joined_spec.rb +53 -0
  151. data/spec/adhearsion/event/offer_spec.rb +106 -0
  152. data/spec/adhearsion/event/ringing_spec.rb +50 -0
  153. data/spec/adhearsion/event/started_speaking_spec.rb +37 -0
  154. data/spec/adhearsion/event/stopped_speaking_spec.rb +37 -0
  155. data/spec/adhearsion/event/unjoined_spec.rb +48 -0
  156. data/spec/adhearsion/event/untitled +0 -0
  157. data/spec/adhearsion/events_spec.rb +19 -45
  158. data/spec/adhearsion/initializer_spec.rb +12 -184
  159. data/spec/adhearsion/logging_spec.rb +5 -20
  160. data/spec/adhearsion/outbound_call_spec.rb +13 -13
  161. data/spec/adhearsion/plugin_spec.rb +3 -4
  162. data/spec/adhearsion/protocol_error_spec.rb +91 -0
  163. data/spec/adhearsion/rayo/client/component_registry_spec.rb +26 -0
  164. data/spec/adhearsion/rayo/client_spec.rb +134 -0
  165. data/spec/adhearsion/rayo/command/accept_spec.rb +63 -0
  166. data/spec/adhearsion/rayo/command/answer_spec.rb +73 -0
  167. data/spec/adhearsion/rayo/command/dial_spec.rb +156 -0
  168. data/spec/adhearsion/rayo/command/hangup_spec.rb +63 -0
  169. data/spec/adhearsion/rayo/command/join_spec.rb +158 -0
  170. data/spec/adhearsion/rayo/command/mute_spec.rb +32 -0
  171. data/spec/adhearsion/rayo/command/redirect_spec.rb +89 -0
  172. data/spec/adhearsion/rayo/command/reject_spec.rb +117 -0
  173. data/spec/adhearsion/rayo/command/unjoin_spec.rb +82 -0
  174. data/spec/adhearsion/rayo/command/unmute_spec.rb +32 -0
  175. data/spec/adhearsion/rayo/command_node_spec.rb +101 -0
  176. data/spec/adhearsion/rayo/component/asterisk/agi/command_spec.rb +111 -0
  177. data/spec/adhearsion/rayo/component/asterisk/ami/action_spec.rb +173 -0
  178. data/spec/adhearsion/rayo/component/component_node_spec.rb +110 -0
  179. data/spec/adhearsion/rayo/component/input_spec.rb +715 -0
  180. data/spec/adhearsion/rayo/component/output_spec.rb +1030 -0
  181. data/spec/adhearsion/rayo/component/prompt_spec.rb +171 -0
  182. data/spec/adhearsion/rayo/component/receive_fax_spec.rb +136 -0
  183. data/spec/adhearsion/rayo/component/record_spec.rb +497 -0
  184. data/spec/adhearsion/rayo/component/send_fax_spec.rb +144 -0
  185. data/spec/adhearsion/rayo/connection/asterisk_spec.rb +118 -0
  186. data/spec/adhearsion/rayo/connection/xmpp_spec.rb +449 -0
  187. data/spec/adhearsion/rayo/initializer_spec.rb +353 -0
  188. data/spec/adhearsion/rayo/ref_spec.rb +168 -0
  189. data/spec/adhearsion/rayo_spec.rb +7 -0
  190. data/spec/adhearsion/router/route_spec.rb +1 -1
  191. data/spec/adhearsion/statistics_spec.rb +2 -5
  192. data/spec/adhearsion/translator/asterisk/call_spec.rb +2047 -0
  193. data/spec/adhearsion/translator/asterisk/component/asterisk/agi_command_spec.rb +256 -0
  194. data/spec/adhearsion/translator/asterisk/component/asterisk/ami_action_spec.rb +151 -0
  195. data/spec/adhearsion/translator/asterisk/component/composed_prompt_spec.rb +257 -0
  196. data/spec/adhearsion/translator/asterisk/component/input_spec.rb +571 -0
  197. data/spec/adhearsion/translator/asterisk/component/mrcp_native_prompt_spec.rb +774 -0
  198. data/spec/adhearsion/translator/asterisk/component/mrcp_prompt_spec.rb +1244 -0
  199. data/spec/adhearsion/translator/asterisk/component/output_spec.rb +1850 -0
  200. data/spec/adhearsion/translator/asterisk/component/record_spec.rb +426 -0
  201. data/spec/adhearsion/translator/asterisk/component/stop_by_redirect_spec.rb +62 -0
  202. data/spec/adhearsion/translator/asterisk/component_spec.rb +83 -0
  203. data/spec/adhearsion/translator/asterisk_spec.rb +685 -0
  204. data/spec/adhearsion/uri_list_spec.rb +88 -0
  205. data/spec/adhearsion_spec.rb +89 -14
  206. data/spec/fixtures/locale/en.yml +13 -0
  207. data/spec/fixtures/locale/it.yml +13 -0
  208. data/spec/spec_helper.rb +18 -5
  209. data/spec/support/call_controller_test_helpers.rb +3 -2
  210. data/spec/support/initializer_stubs.rb +3 -1
  211. data/spec/support/punchblock_examples.rb +65 -0
  212. data/spec/support/punchblock_mocks.rb +12 -0
  213. metadata +412 -70
  214. data/features/cli_daemon.feature +0 -20
  215. data/features/cli_restart.feature +0 -52
  216. data/features/cli_stop.feature +0 -50
  217. data/lib/adhearsion/call_controller/menu_dsl.rb +0 -21
  218. data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +0 -26
  219. data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +0 -43
  220. data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +0 -45
  221. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +0 -11
  222. data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +0 -40
  223. data/lib/adhearsion/call_controller/menu_dsl/menu.rb +0 -207
  224. data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +0 -92
  225. data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +0 -60
  226. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +0 -25
  227. data/lib/adhearsion/call_controller/utility.rb +0 -77
  228. data/lib/adhearsion/foundation/custom_daemonizer.rb +0 -52
  229. data/lib/adhearsion/punchblock_plugin.rb +0 -63
  230. data/scripts/cloc-1.64.pl +0 -10483
  231. data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +0 -76
  232. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +0 -60
  233. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +0 -61
  234. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +0 -39
  235. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +0 -17
  236. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +0 -165
  237. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +0 -420
  238. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +0 -32
  239. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +0 -40
  240. data/spec/adhearsion/call_controller/utility_spec.rb +0 -90
  241. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +0 -356
  242. data/spec/adhearsion/punchblock_plugin_spec.rb +0 -59
@@ -0,0 +1,426 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Adhearsion
6
+ module Translator
7
+ class Asterisk
8
+ module Component
9
+ describe Record do
10
+ include HasMockCallbackConnection
11
+
12
+ let(:channel) { 'SIP/foo' }
13
+ let(:ami_client) { double('AMI Client').as_null_object }
14
+ let(:translator) { Translator::Asterisk.new ami_client, connection }
15
+ let(:mock_call) { Translator::Asterisk::Call.new channel, translator, ami_client, connection }
16
+
17
+ let :original_command do
18
+ Adhearsion::Rayo::Component::Record.new command_options
19
+ end
20
+
21
+ let :command_options do
22
+ {}
23
+ end
24
+
25
+ subject { Record.new original_command, mock_call }
26
+
27
+ describe '#execute' do
28
+ let(:reason) { original_command.complete_event(5).reason }
29
+ let(:recording) { original_command.complete_event(5).recording }
30
+
31
+ before { original_command.request! }
32
+
33
+ it "returns an error if the call is not answered yet" do
34
+ expect(mock_call).to receive(:answered?).and_return(false)
35
+ subject.execute
36
+ error = Adhearsion::ProtocolError.new.setup 'option error', 'Record cannot be used on a call that is not answered.'
37
+ expect(original_command.response(0.1)).to eq(error)
38
+ end
39
+
40
+ before { allow(mock_call).to receive(:answered?).and_return(true) }
41
+
42
+ it "sets command response to a reference to the component" do
43
+ expect(ami_client).to receive(:send_action)
44
+ subject.execute
45
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
46
+ expect(original_command.component_id).to eq(subject.id)
47
+ end
48
+
49
+ it "starts a recording via AMI, using the component ID as the filename" do
50
+ filename = "#{Record::RECORDING_BASE_PATH}/#{subject.id}"
51
+ expect(ami_client).to receive(:send_action).once.with('Monitor', 'Channel' => channel, 'File' => filename, 'Format' => 'wav', 'Mix' => true)
52
+ subject.execute
53
+ end
54
+
55
+ it "sends a max duration complete event when the recording ends" do
56
+ full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
57
+ expect(ami_client).to receive(:send_action)
58
+ subject.execute
59
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
60
+ mock_call.process_ami_event monitor_stop_event
61
+ expect(reason).to be_a Adhearsion::Rayo::Component::Record::Complete::MaxDuration
62
+ expect(recording.uri).to eq(full_filename)
63
+ expect(original_command).to be_complete
64
+ end
65
+
66
+ it "can be called multiple times on the same call" do
67
+ expect(ami_client).to receive(:send_action).twice
68
+ subject.execute
69
+
70
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
71
+
72
+ mock_call.process_ami_event monitor_stop_event
73
+
74
+ Record.new(original_command, mock_call).execute
75
+ Adhearsion::Rayo::Component::Record.new(command_options).request!
76
+ mock_call.process_ami_event monitor_stop_event
77
+ end
78
+
79
+ describe 'start_paused' do
80
+ context "set to nil" do
81
+ let(:command_options) { { :start_paused => nil } }
82
+ it "should execute normally" do
83
+ expect(ami_client).to receive(:send_action).once
84
+ subject.execute
85
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
86
+ end
87
+ end
88
+
89
+ context "set to false" do
90
+ let(:command_options) { { :start_paused => false } }
91
+ it "should execute normally" do
92
+ expect(ami_client).to receive(:send_action).once
93
+ subject.execute
94
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
95
+ end
96
+ end
97
+
98
+ context "set to true" do
99
+ let(:command_options) { { :start_paused => true } }
100
+ it "should return an error and not execute any actions" do
101
+ expect(mock_call).to receive(:execute_agi_command).never
102
+ subject.execute
103
+ error = Adhearsion::ProtocolError.new.setup 'option error', 'A start-paused value of true is unsupported.'
104
+ expect(original_command.response(0.1)).to eq(error)
105
+ end
106
+ end
107
+ end
108
+
109
+ describe 'initial_timeout' do
110
+ context "set to nil" do
111
+ let(:command_options) { { :initial_timeout => nil } }
112
+ it "should execute normally" do
113
+ expect(ami_client).to receive(:send_action).once
114
+ subject.execute
115
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
116
+ end
117
+ end
118
+
119
+ context "set to -1" do
120
+ let(:command_options) { { :initial_timeout => -1 } }
121
+ it "should execute normally" do
122
+ expect(ami_client).to receive(:send_action).once
123
+ subject.execute
124
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
125
+ end
126
+ end
127
+
128
+ context "set to a positive number" do
129
+ let(:command_options) { { :initial_timeout => 10 } }
130
+ it "should return an error and not execute any actions" do
131
+ expect(mock_call).to receive(:execute_agi_command).never
132
+ subject.execute
133
+ error = Adhearsion::ProtocolError.new.setup 'option error', 'An initial-timeout value is unsupported.'
134
+ expect(original_command.response(0.1)).to eq(error)
135
+ end
136
+ end
137
+ end
138
+
139
+ describe 'final_timeout' do
140
+ context "set to nil" do
141
+ let(:command_options) { { :final_timeout => nil } }
142
+ it "should execute normally" do
143
+ expect(ami_client).to receive(:send_action).once
144
+ subject.execute
145
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
146
+ end
147
+ end
148
+
149
+ context "set to -1" do
150
+ let(:command_options) { { :final_timeout => -1 } }
151
+ it "should execute normally" do
152
+ expect(ami_client).to receive(:send_action).once
153
+ subject.execute
154
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
155
+ end
156
+ end
157
+
158
+ context "set to a positive number" do
159
+ let(:command_options) { { :final_timeout => 10 } }
160
+ it "should return an error and not execute any actions" do
161
+ expect(mock_call).to receive(:execute_agi_command).never
162
+ subject.execute
163
+ error = Adhearsion::ProtocolError.new.setup 'option error', 'A final-timeout value is unsupported.'
164
+ expect(original_command.response(0.1)).to eq(error)
165
+ end
166
+ end
167
+ end
168
+
169
+ describe 'format' do
170
+ context "set to nil" do
171
+ let(:command_options) { { :format => nil } }
172
+ it "should execute as 'wav'" do
173
+ expect(ami_client).to receive(:send_action).once.with('Monitor', hash_including('Format' => 'wav'))
174
+ subject.execute
175
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
176
+ end
177
+
178
+ it "provides the correct filename in the recording" do
179
+ expect(ami_client).to receive(:send_action)
180
+ subject.execute
181
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
182
+ mock_call.process_ami_event monitor_stop_event
183
+ expect(recording.uri).to match(/.*\.wav$/)
184
+ end
185
+ end
186
+
187
+ context "set to 'mp3'" do
188
+ let(:command_options) { { :format => 'mp3' } }
189
+ it "should execute as 'mp3'" do
190
+ expect(ami_client).to receive(:send_action).once.with('Monitor', hash_including('Format' => 'mp3'))
191
+ subject.execute
192
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
193
+ end
194
+
195
+ it "provides the correct filename in the recording" do
196
+ expect(ami_client).to receive(:send_action)
197
+ subject.execute
198
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
199
+ mock_call.process_ami_event monitor_stop_event
200
+ expect(recording.uri).to match(/.*\.mp3$/)
201
+ end
202
+ end
203
+ end
204
+
205
+ describe 'start_beep' do
206
+ context "set to nil" do
207
+ let(:command_options) { { :start_beep => nil } }
208
+ it "should execute normally" do
209
+ expect(mock_call).to receive(:execute_agi_command).never.with('STREAM FILE', 'beep', '""')
210
+ expect(ami_client).to receive(:send_action).once
211
+ subject.execute
212
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
213
+ end
214
+ end
215
+
216
+ context "set to false" do
217
+ let(:command_options) { { :start_beep => false } }
218
+ it "should execute normally" do
219
+ expect(mock_call).to receive(:execute_agi_command).never.with('STREAM FILE', 'beep', '""')
220
+ expect(ami_client).to receive(:send_action).once
221
+ subject.execute
222
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
223
+ end
224
+ end
225
+
226
+ context "set to true" do
227
+ let(:command_options) { { :start_beep => true } }
228
+
229
+ it "should play a beep before recording" do
230
+ expect(mock_call).to receive(:execute_agi_command).once.with('STREAM FILE', 'beep', '""').ordered.and_return code: 200
231
+ expect(ami_client).to receive(:send_action).once.ordered
232
+ subject.execute
233
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
234
+ end
235
+
236
+ context "when we get a RubyAMI Error" do
237
+ it "should send an error response" do
238
+ error = RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
239
+ expect(mock_call).to receive(:execute_agi_command).and_raise error
240
+ expect(ami_client).to receive(:send_action).never
241
+ subject.execute
242
+ error = Adhearsion::ProtocolError.new.setup :platform_error, "Terminated due to AMI error 'FooBar'"
243
+ expect(original_command.response(0.1)).to eq(error)
244
+ end
245
+ end
246
+
247
+ context "when the channel is no longer available" do
248
+ it "should send an error complete event" do
249
+ expect(mock_call).to receive(:execute_agi_command).and_raise ChannelGoneError
250
+ expect(ami_client).to receive(:send_action).never
251
+ subject.execute
252
+ error = Adhearsion::ProtocolError.new.setup(:item_not_found, "Could not find a call with ID #{mock_call.id}", mock_call.id)
253
+ expect(original_command.response(0.1)).to eq(error)
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ describe 'max_duration' do
260
+ context "set to nil" do
261
+ let(:command_options) { { :max_duration => nil } }
262
+ it "should execute normally" do
263
+ expect(ami_client).to receive(:send_action).once
264
+ subject.execute
265
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
266
+ end
267
+ end
268
+
269
+ context "set to -1" do
270
+ let(:command_options) { { :max_duration => -1 } }
271
+ it "should execute normally" do
272
+ expect(ami_client).to receive(:send_action).once
273
+ subject.execute
274
+ expect(original_command.response(0.1)).to be_a Adhearsion::Rayo::Ref
275
+ end
276
+ end
277
+
278
+ context 'a negative number other than -1' do
279
+ let(:command_options) { { :max_duration => -1000 } }
280
+
281
+ it "should return an error and not execute any actions" do
282
+ subject.execute
283
+ error = Adhearsion::ProtocolError.new.setup 'option error', 'A max-duration value that is negative (and not -1) is invalid.'
284
+ expect(original_command.response(0.1)).to eq(error)
285
+ end
286
+ end
287
+
288
+ context 'a positive number' do
289
+ let(:reason) { original_command.complete_event(5).reason }
290
+ let(:recording) { original_command.complete_event(5).recording }
291
+ let(:command_options) { { :max_duration => 1000 } }
292
+
293
+ it "executes a StopMonitor action" do
294
+ expect(ami_client).to receive :send_action
295
+ expect(ami_client).to receive(:send_action).once.with('StopMonitor', 'Channel' => channel)
296
+ subject.execute
297
+ sleep 1.2
298
+ end
299
+
300
+ it "should not kill the translator if the channel is down" do
301
+ expect(ami_client).to receive :send_action
302
+ error = RubyAMI::Error.new.tap { |e| e.message = 'No such channel' }
303
+ expect(ami_client).to receive(:send_action).once.with('StopMonitor', 'Channel' => channel).and_raise error
304
+ subject.execute
305
+ sleep 1.2
306
+ expect(translator).to be_alive
307
+ end
308
+
309
+ it "sends the correct complete event" do
310
+ full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
311
+ subject.execute
312
+ sleep 1.2
313
+
314
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
315
+ mock_call.process_ami_event monitor_stop_event
316
+
317
+ expect(reason).to be_a Adhearsion::Rayo::Component::Record::Complete::MaxDuration
318
+ expect(recording.uri).to eq(full_filename)
319
+ expect(original_command).to be_complete
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ describe "#execute_command" do
326
+ let(:reason) { original_command.complete_event(5).reason }
327
+ let(:recording) { original_command.complete_event(5).recording }
328
+
329
+ context "with a command it does not understand" do
330
+ let(:command) { Adhearsion::Rayo::Component::Output::Pause.new }
331
+
332
+ before { command.request! }
333
+ it "returns a Adhearsion::ProtocolError response" do
334
+ subject.execute_command command
335
+ expect(command.response(0.1)).to be_a Adhearsion::ProtocolError
336
+ end
337
+ end
338
+
339
+ context "with a Stop command" do
340
+ let(:command) { Adhearsion::Rayo::Component::Stop.new }
341
+
342
+ before do
343
+ expect(ami_client).to receive :send_action
344
+ expect(mock_call).to receive(:answered?).and_return(true)
345
+ command.request!
346
+ original_command.request!
347
+ subject.execute
348
+ end
349
+
350
+ let :send_stop_event do
351
+ monitor_stop_event = RubyAMI::Event.new 'MonitorStop', 'Channel' => channel
352
+ mock_call.process_ami_event monitor_stop_event
353
+ end
354
+
355
+ it "sets the command response to true" do
356
+ expect(ami_client).to receive :send_action
357
+ subject.execute_command command
358
+ send_stop_event
359
+ expect(command.response(0.1)).to eq(true)
360
+ end
361
+
362
+ it "executes a StopMonitor action" do
363
+ expect(ami_client).to receive(:send_action).once.with('StopMonitor', 'Channel' => channel)
364
+ subject.execute_command command
365
+ end
366
+
367
+ it "sends the correct complete event" do
368
+ expect(ami_client).to receive(:send_action).and_return RubyAMI::Response.new
369
+
370
+ full_filename = "file://#{Record::RECORDING_BASE_PATH}/#{subject.id}.wav"
371
+ subject.execute_command command
372
+ send_stop_event
373
+ expect(reason).to be_a Adhearsion::Event::Complete::Stop
374
+ expect(recording.uri).to eq(full_filename)
375
+ expect(original_command).to be_complete
376
+ end
377
+ end
378
+
379
+ context "with a Pause command" do
380
+ let(:command) { Adhearsion::Rayo::Component::Record::Pause.new }
381
+
382
+ before do
383
+ command.request!
384
+ original_command.request!
385
+ original_command.execute!
386
+ end
387
+
388
+ it "sets the command response to true" do
389
+ expect(ami_client).to receive(:send_action).and_return RubyAMI::Response.new
390
+ subject.execute_command command
391
+ expect(command.response(0.1)).to eq(true)
392
+ end
393
+
394
+ it "pauses the recording via AMI" do
395
+ expect(ami_client).to receive(:send_action).once.with('PauseMonitor', 'Channel' => channel)
396
+ subject.execute_command command
397
+ end
398
+ end
399
+
400
+ context "with a Resume command" do
401
+ let(:command) { Adhearsion::Rayo::Component::Record::Resume.new }
402
+
403
+ before do
404
+ command.request!
405
+ original_command.request!
406
+ original_command.execute!
407
+ end
408
+
409
+ it "sets the command response to true" do
410
+ expect(ami_client).to receive(:send_action).and_return RubyAMI::Response.new
411
+ subject.execute_command command
412
+ expect(command.response(0.1)).to eq(true)
413
+ end
414
+
415
+ it "resumes the recording via AMI" do
416
+ expect(ami_client).to receive(:send_action).once.with('ResumeMonitor', 'Channel' => channel)
417
+ subject.execute_command command
418
+ end
419
+ end
420
+ end
421
+
422
+ end
423
+ end
424
+ end
425
+ end
426
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Adhearsion
6
+ module Translator
7
+ class Asterisk
8
+ module Component
9
+ describe StopByRedirect do
10
+
11
+ class MockComponent < Component
12
+ include StopByRedirect
13
+ def set_complete
14
+ @complete = true
15
+ end
16
+ end
17
+
18
+ let(:connection) { double 'Connection' }
19
+ let(:ami_client) { double('AMI Client').as_null_object }
20
+ let(:translator) { Translator::Asterisk.new ami_client, connection }
21
+ let(:mock_call) { Call.new 'SIP/foo', translator, ami_client, connection }
22
+
23
+ subject { MockComponent.new Hash.new, mock_call }
24
+
25
+ describe "#execute_command" do
26
+ context "with a command it does not understand" do
27
+ let(:command) { Adhearsion::Rayo::Component::Output::Pause.new }
28
+
29
+ before { command.request! }
30
+ it "returns a Adhearsion::ProtocolError response" do
31
+ subject.execute_command command
32
+ expect(command.response(0.1)).to be_a Adhearsion::ProtocolError
33
+ end
34
+ end
35
+
36
+ context "with a Stop command" do
37
+ let(:command) { Adhearsion::Rayo::Component::Stop.new }
38
+
39
+ before do
40
+ command.request!
41
+ end
42
+
43
+ it "sets the command response to true" do
44
+ expect(mock_call).to receive(:redirect_back)
45
+ expect(mock_call).to receive(:register_handler).once.with(:ami, [{:name => 'AsyncAGI', [:[], 'SubEvent']=>'Start'}, {:name => 'AsyncAGIExec'}])
46
+
47
+ subject.execute_command command
48
+ expect(command.response(0.1)).to eq(true)
49
+ end
50
+
51
+ it "returns an error if the component is already complete" do
52
+ subject.set_complete
53
+ subject.execute_command command
54
+ expect(command.response(0.1)).to be_a Adhearsion::ProtocolError
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end