adhearsion 2.6.4 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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,1030 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Adhearsion::Rayo::Component::Output do
6
+ it 'registers itself' do
7
+ expect(Adhearsion::Rayo::RayoNode.class_from_registration(:output, 'urn:xmpp:rayo:output:1')).to eq(described_class)
8
+ end
9
+
10
+ describe 'default values' do
11
+ describe '#interrupt_on' do
12
+ subject { super().interrupt_on }
13
+ it { is_expected.to be nil }
14
+ end
15
+
16
+ describe '#start_offset' do
17
+ subject { super().start_offset }
18
+ it { is_expected.to be nil }
19
+ end
20
+
21
+ describe '#start_paused' do
22
+ subject { super().start_paused }
23
+ it { is_expected.to be nil }
24
+ end
25
+
26
+ describe '#repeat_interval' do
27
+ subject { super().repeat_interval }
28
+ it { is_expected.to be nil }
29
+ end
30
+
31
+ describe '#repeat_times' do
32
+ subject { super().repeat_times }
33
+ it { is_expected.to be nil }
34
+ end
35
+
36
+ describe '#max_time' do
37
+ subject { super().max_time }
38
+ it { is_expected.to be nil }
39
+ end
40
+
41
+ describe '#voice' do
42
+ subject { super().voice }
43
+ it { is_expected.to be nil }
44
+ end
45
+
46
+ describe '#renderer' do
47
+ subject { super().renderer }
48
+ it { is_expected.to be nil }
49
+ end
50
+
51
+ describe '#render_documents' do
52
+ subject { super().render_documents }
53
+ it { is_expected.to eq([]) }
54
+ end
55
+ end
56
+
57
+ def ssml_doc(mode = :ordinal)
58
+ RubySpeech::SSML.draw do
59
+ say_as(:interpret_as => mode) { string '100' }
60
+ end
61
+ end
62
+
63
+ describe "when setting options in initializer" do
64
+ subject(:command) do
65
+ described_class.new :interrupt_on => :voice,
66
+ :start_offset => 2000,
67
+ :start_paused => false,
68
+ :repeat_interval => 2000,
69
+ :repeat_times => 10,
70
+ :max_time => 30000,
71
+ :voice => 'allison',
72
+ :renderer => 'swift',
73
+ :render_document => {:value => ssml_doc},
74
+ :headers => { 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' }
75
+ end
76
+
77
+ describe '#interrupt_on' do
78
+ subject { super().interrupt_on }
79
+ it { is_expected.to eq(:voice) }
80
+ end
81
+
82
+ describe '#start_offset' do
83
+ subject { super().start_offset }
84
+ it { is_expected.to eq(2000) }
85
+ end
86
+
87
+ describe '#start_paused' do
88
+ subject { super().start_paused }
89
+ it { is_expected.to eq(false) }
90
+ end
91
+
92
+ describe '#repeat_interval' do
93
+ subject { super().repeat_interval }
94
+ it { is_expected.to eq(2000) }
95
+ end
96
+
97
+ describe '#repeat_times' do
98
+ subject { super().repeat_times }
99
+ it { is_expected.to eq(10) }
100
+ end
101
+
102
+ describe '#max_time' do
103
+ subject { super().max_time }
104
+ it { is_expected.to eq(30000) }
105
+ end
106
+
107
+ describe '#voice' do
108
+ subject { super().voice }
109
+ it { is_expected.to eq('allison') }
110
+ end
111
+
112
+ describe '#renderer' do
113
+ subject { super().renderer }
114
+ it { is_expected.to eq('swift') }
115
+ end
116
+
117
+ describe '#render_documents' do
118
+ subject { super().render_documents }
119
+ it { is_expected.to eq([described_class::Document.new(:value => ssml_doc)]) }
120
+ end
121
+
122
+ context "using #ssml=" do
123
+ subject do
124
+ described_class.new :ssml => ssml_doc
125
+ end
126
+
127
+ describe '#render_documents' do
128
+ subject { super().render_documents }
129
+ it { is_expected.to eq([described_class::Document.new(:value => ssml_doc)]) }
130
+ end
131
+ end
132
+
133
+ context "with multiple documents" do
134
+ subject do
135
+ described_class.new :render_documents => [
136
+ {:value => ssml_doc},
137
+ {:value => ssml_doc(:cardinal)}
138
+ ]
139
+ end
140
+
141
+ describe '#render_documents' do
142
+ subject { super().render_documents }
143
+ it { is_expected.to eq([
144
+ described_class::Document.new(:value => ssml_doc),
145
+ described_class::Document.new(:value => ssml_doc(:cardinal))
146
+ ])}
147
+ end
148
+ end
149
+
150
+ context "with a urilist" do
151
+ subject do
152
+ described_class.new render_document: {
153
+ content_type: 'text/uri-list',
154
+ value: Adhearsion::URIList.new('http://example.com/hello.mp3')
155
+ }
156
+ end
157
+
158
+ describe '#render_documents' do
159
+ subject { super().render_documents }
160
+ it { is_expected.to eq([described_class::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3'])]) }
161
+ end
162
+
163
+ describe "exporting to Rayo" do
164
+ it "should export to XML that can be understood by its parser" do
165
+ new_instance = Adhearsion::Rayo::RayoNode.from_xml Nokogiri::XML(subject.to_rayo.to_xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root
166
+ expect(new_instance.render_documents).to eq([described_class::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3'])])
167
+ end
168
+ end
169
+ end
170
+
171
+ context "with a nil document" do
172
+ it "removes all documents" do
173
+ subject.render_document = nil
174
+ expect(subject.render_documents).to eq([])
175
+ end
176
+ end
177
+
178
+ context "without any documents" do
179
+ subject { described_class.new }
180
+
181
+ describe '#render_documents' do
182
+ subject { super().render_documents }
183
+ it { is_expected.to eq([]) }
184
+ end
185
+ end
186
+
187
+ describe '#headers' do
188
+ subject { super().headers }
189
+ it { is_expected.to eq({ 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' }) }
190
+ end
191
+
192
+ describe "exporting to Rayo" do
193
+ it "should export to XML that can be understood by its parser" do
194
+ new_instance = Adhearsion::Rayo::RayoNode.from_xml Nokogiri::XML(subject.to_rayo.to_xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root
195
+ expect(new_instance).to be_instance_of described_class
196
+ expect(new_instance.interrupt_on).to eq(:voice)
197
+ expect(new_instance.start_offset).to eq(2000)
198
+ expect(new_instance.start_paused).to eq(false)
199
+ expect(new_instance.repeat_interval).to eq(2000)
200
+ expect(new_instance.repeat_times).to eq(10)
201
+ expect(new_instance.max_time).to eq(30000)
202
+ expect(new_instance.voice).to eq('allison')
203
+ expect(new_instance.renderer).to eq('swift')
204
+ expect(new_instance.render_documents).to eq([described_class::Document.new(:value => ssml_doc)])
205
+ expect(new_instance.headers).to eq({ 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' })
206
+ end
207
+
208
+ it "should wrap the document value in CDATA" do
209
+ grammar_node = subject.to_rayo.at_xpath('ns:document', ns: described_class.registered_ns)
210
+ expect(grammar_node.children.first).to be_a Nokogiri::XML::CDATA
211
+ end
212
+
213
+ it "should render to a parent node if supplied" do
214
+ doc = Nokogiri::XML::Document.new
215
+ parent = Nokogiri::XML::Node.new 'foo', doc
216
+ doc.root = parent
217
+ rayo_doc = subject.to_rayo(parent)
218
+ expect(rayo_doc).to eq(parent)
219
+ end
220
+
221
+ context "with a string SSML document" do
222
+ let(:ssml_string) { "<speak/>" }
223
+
224
+ subject do
225
+ described_class.new ssml: ssml_string
226
+ end
227
+
228
+ it "passes the string right through" do
229
+ content = subject.to_rayo.at_xpath('//ns:output/ns:document/text()', ns: described_class.registered_ns).content
230
+ expect(content).to eq(ssml_string)
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ describe "from a stanza" do
237
+ let :stanza do
238
+ <<-MESSAGE
239
+ <output xmlns='urn:xmpp:rayo:output:1'
240
+ interrupt-on='voice'
241
+ start-offset='2000'
242
+ start-paused='false'
243
+ repeat-interval='2000'
244
+ repeat-times='10'
245
+ max-time='30000'
246
+ voice='allison'
247
+ renderer='swift'>
248
+ <document content-type="application/ssml+xml">
249
+ <![CDATA[
250
+ <speak version="1.0"
251
+ xmlns="http://www.w3.org/2001/10/synthesis"
252
+ xml:lang="en-US">
253
+ <say-as interpret-as="ordinal">100</say-as>
254
+ </speak>
255
+ ]]>
256
+ </document>
257
+ <document content-type="application/ssml+xml">
258
+ <![CDATA[
259
+ <speak version="1.0"
260
+ xmlns="http://www.w3.org/2001/10/synthesis"
261
+ xml:lang="en-US">
262
+ <say-as interpret-as="ordinal">100</say-as>
263
+ </speak>
264
+ ]]>
265
+ </document>
266
+ <header xmlns='urn:xmpp:rayo:1' name="Jump-Size" value="2" />
267
+ <header xmlns='urn:xmpp:rayo:1' name="Kill-On-Barge-In" value="false" />
268
+ </output>
269
+ MESSAGE
270
+ end
271
+
272
+ subject { Adhearsion::Rayo::RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
273
+
274
+ it { is_expected.to be_instance_of described_class }
275
+
276
+ describe '#interrupt_on' do
277
+ subject { super().interrupt_on }
278
+ it { is_expected.to eq(:voice) }
279
+ end
280
+
281
+ describe '#start_offset' do
282
+ subject { super().start_offset }
283
+ it { is_expected.to eq(2000) }
284
+ end
285
+
286
+ describe '#start_paused' do
287
+ subject { super().start_paused }
288
+ it { is_expected.to eq(false) }
289
+ end
290
+
291
+ describe '#repeat_interval' do
292
+ subject { super().repeat_interval }
293
+ it { is_expected.to eq(2000) }
294
+ end
295
+
296
+ describe '#repeat_times' do
297
+ subject { super().repeat_times }
298
+ it { is_expected.to eq(10) }
299
+ end
300
+
301
+ describe '#max_time' do
302
+ subject { super().max_time }
303
+ it { is_expected.to eq(30000) }
304
+ end
305
+
306
+ describe '#voice' do
307
+ subject { super().voice }
308
+ it { is_expected.to eq('allison') }
309
+ end
310
+
311
+ describe '#renderer' do
312
+ subject { super().renderer }
313
+ it { is_expected.to eq('swift') }
314
+ end
315
+
316
+ describe '#render_documents' do
317
+ subject { super().render_documents }
318
+ it { is_expected.to eq([described_class::Document.new(:value => ssml_doc), described_class::Document.new(:value => ssml_doc)]) }
319
+ end
320
+
321
+ context "with a urilist" do
322
+ let :stanza do
323
+ <<-MESSAGE
324
+ <output xmlns='urn:xmpp:rayo:output:1'>
325
+ <document content-type="text/uri-list">
326
+ <![CDATA[
327
+ http://example.com/hello.mp3
328
+ http://example.com/goodbye.mp3
329
+ ]]>
330
+ </document>
331
+ </output>
332
+ MESSAGE
333
+ end
334
+
335
+ describe '#render_documents' do
336
+ subject { super().render_documents }
337
+ it { is_expected.to eq([described_class::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'])]) }
338
+ end
339
+ end
340
+
341
+ describe '#headers' do
342
+ subject { super().headers }
343
+ it { is_expected.to eq({ 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' }) }
344
+ end
345
+ end
346
+
347
+ describe described_class::Document do
348
+ describe "when not passing a content type" do
349
+ subject { described_class.new :value => ssml_doc }
350
+
351
+ describe '#content_type' do
352
+ subject { super().content_type }
353
+ it { is_expected.to eq('application/ssml+xml') }
354
+ end
355
+ end
356
+
357
+ describe 'with an SSML document' do
358
+ subject { described_class.new :value => ssml_doc, :content_type => 'application/ssml+xml' }
359
+
360
+ describe '#content_type' do
361
+ subject { super().content_type }
362
+ it { is_expected.to eq('application/ssml+xml') }
363
+ end
364
+
365
+ describe '#value' do
366
+ subject { super().value }
367
+ it { is_expected.to eq(ssml_doc) }
368
+ end
369
+
370
+ describe "comparison" do
371
+ let(:document2) { described_class.new :value => ssml_doc }
372
+ let(:document3) { described_class.new :value => ssml_doc(:normal) }
373
+
374
+ it { is_expected.to eq(document2) }
375
+ it { is_expected.not_to eq(document3) }
376
+ end
377
+ end
378
+
379
+ describe 'with a urilist' do
380
+ subject { described_class.new content_type: 'text/uri-list', value: Adhearsion::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3') }
381
+
382
+ describe '#value' do
383
+ subject { super().value }
384
+ it { is_expected.to eq(Adhearsion::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3')) }
385
+ end
386
+
387
+ describe "comparison" do
388
+ let(:document2) { described_class.new content_type: 'text/uri-list', value: Adhearsion::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3') }
389
+ let(:document3) { described_class.new value: '<speak xmlns="http://www.w3.org/2001/10/synthesis" version="1.0" xml:lang="en-US"><say-as interpret-as="ordinal">100</say-as></speak>' }
390
+ let(:document4) { described_class.new content_type: 'text/uri-list', value: Adhearsion::URIList.new('http://example.com/hello.mp3') }
391
+ let(:document5) { described_class.new content_type: 'text/uri-list', value: Adhearsion::URIList.new('http://example.com/goodbye.mp3', 'http://example.com/hello.mp3') }
392
+
393
+ it { is_expected.to eq(document2) }
394
+ it { is_expected.not_to eq(document3) }
395
+ it { is_expected.not_to eq(document4) }
396
+ it { is_expected.not_to eq(document5) }
397
+ end
398
+ end
399
+
400
+ describe 'with a document reference by URL' do
401
+ let(:url) { 'http://foo.com/bar.grxml' }
402
+
403
+ subject { described_class.new :url => url }
404
+
405
+ describe '#url' do
406
+ subject { super().url }
407
+ it { is_expected.to eq(url) }
408
+ end
409
+
410
+ describe '#content_type' do
411
+ subject { super().content_type }
412
+ it { is_expected.to be nil}
413
+ end
414
+
415
+ describe "comparison" do
416
+ it "should be the same with the same url" do
417
+ expect(described_class.new(:url => url)).to eq(described_class.new(:url => url))
418
+ end
419
+
420
+ it "should be different with a different url" do
421
+ expect(described_class.new(:url => url)).not_to eq(described_class.new(:url => 'http://doo.com/dah'))
422
+ end
423
+ end
424
+ end
425
+ end
426
+
427
+ describe "actions" do
428
+ let(:mock_client) { double 'Client' }
429
+ let(:command) { described_class.new }
430
+
431
+ before do
432
+ command.component_id = 'abc123'
433
+ command.target_call_id = '123abc'
434
+ command.client = mock_client
435
+ end
436
+
437
+ describe '#pause_action' do
438
+ subject { command.pause_action }
439
+
440
+ describe '#to_xml' do
441
+ subject { super().to_xml }
442
+ it { is_expected.to eq('<pause xmlns="urn:xmpp:rayo:output:1"/>') }
443
+ end
444
+
445
+ describe '#component_id' do
446
+ subject { super().component_id }
447
+ it { is_expected.to eq('abc123') }
448
+ end
449
+
450
+ describe '#target_call_id' do
451
+ subject { super().target_call_id }
452
+ it { is_expected.to eq('123abc') }
453
+ end
454
+ end
455
+
456
+ describe '#pause!' do
457
+ describe "when the command is executing" do
458
+ before do
459
+ command.request!
460
+ command.execute!
461
+ end
462
+
463
+ it "should send its command properly" do
464
+ expect(mock_client).to receive(:execute_command).with(command.pause_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
465
+ expect(command).to receive :paused!
466
+ command.pause!
467
+ end
468
+ end
469
+
470
+ describe "when the command is not executing" do
471
+ it "should raise an error" do
472
+ expect { command.pause! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot pause a Output that is not executing")
473
+ end
474
+ end
475
+ end
476
+
477
+ describe "#paused!" do
478
+ before do
479
+ command.request!
480
+ command.execute!
481
+ command.paused!
482
+ end
483
+
484
+ describe '#state_name' do
485
+ subject { command.state_name }
486
+ it { is_expected.to eq(:paused) }
487
+ end
488
+
489
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
490
+ expect { command.paused! }.to raise_error(StateMachine::InvalidTransition)
491
+ end
492
+ end
493
+
494
+ describe '#resume_action' do
495
+ subject { command.resume_action }
496
+
497
+ describe '#to_xml' do
498
+ subject { super().to_xml }
499
+ it { is_expected.to eq('<resume xmlns="urn:xmpp:rayo:output:1"/>') }
500
+ end
501
+
502
+ describe '#component_id' do
503
+ subject { super().component_id }
504
+ it { is_expected.to eq('abc123') }
505
+ end
506
+
507
+ describe '#target_call_id' do
508
+ subject { super().target_call_id }
509
+ it { is_expected.to eq('123abc') }
510
+ end
511
+ end
512
+
513
+ describe '#resume!' do
514
+ describe "when the command is paused" do
515
+ before do
516
+ command.request!
517
+ command.execute!
518
+ command.paused!
519
+ end
520
+
521
+ it "should send its command properly" do
522
+ expect(mock_client).to receive(:execute_command).with(command.resume_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
523
+ expect(command).to receive :resumed!
524
+ command.resume!
525
+ end
526
+ end
527
+
528
+ describe "when the command is not paused" do
529
+ it "should raise an error" do
530
+ expect { command.resume! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot resume a Output that is not paused.")
531
+ end
532
+ end
533
+ end
534
+
535
+ describe "#resumed!" do
536
+ before do
537
+ command.request!
538
+ command.execute!
539
+ command.paused!
540
+ command.resumed!
541
+ end
542
+
543
+ describe '#state_name' do
544
+ subject { command.state_name }
545
+ it { is_expected.to eq(:executing) }
546
+ end
547
+
548
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
549
+ expect { command.resumed! }.to raise_error(StateMachine::InvalidTransition)
550
+ end
551
+ end
552
+
553
+ describe '#stop_action' do
554
+ subject { command.stop_action }
555
+
556
+ describe '#to_xml' do
557
+ subject { super().to_xml }
558
+ it { is_expected.to eq('<stop xmlns="urn:xmpp:rayo:ext:1"/>') }
559
+ end
560
+
561
+ describe '#component_id' do
562
+ subject { super().component_id }
563
+ it { is_expected.to eq('abc123') }
564
+ end
565
+
566
+ describe '#target_call_id' do
567
+ subject { super().target_call_id }
568
+ it { is_expected.to eq('123abc') }
569
+ end
570
+ end
571
+
572
+ describe '#stop!' do
573
+ describe "when the command is executing" do
574
+ before do
575
+ command.request!
576
+ command.execute!
577
+ end
578
+
579
+ it "should send its command properly" do
580
+ expect(mock_client).to receive(:execute_command).with(command.stop_action, :target_call_id => '123abc', :component_id => 'abc123')
581
+ command.stop!
582
+ end
583
+ end
584
+
585
+ describe "when the command is not executing" do
586
+ it "should raise an error" do
587
+ expect { command.stop! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot stop a Output that is new")
588
+ end
589
+ end
590
+ end # #stop!
591
+
592
+ describe "seeking" do
593
+ let(:seek_options) { {:direction => :forward, :amount => 1500} }
594
+
595
+ describe '#seek_action' do
596
+ subject { command.seek_action seek_options }
597
+
598
+ describe '#to_xml' do
599
+ subject { super().to_xml }
600
+ it { is_expected.to eq(Nokogiri::XML('<seek xmlns="urn:xmpp:rayo:output:1" direction="forward" amount="1500"/>').root.to_xml) }
601
+ end
602
+
603
+ describe '#component_id' do
604
+ subject { super().component_id }
605
+ it { is_expected.to eq('abc123') }
606
+ end
607
+
608
+ describe '#target_call_id' do
609
+ subject { super().target_call_id }
610
+ it { is_expected.to eq('123abc') }
611
+ end
612
+ end
613
+
614
+ describe '#seek!' do
615
+ describe "when not seeking" do
616
+ before do
617
+ command.request!
618
+ command.execute!
619
+ end
620
+
621
+ it "should send its command properly" do
622
+ seek_action = command.seek_action seek_options
623
+ allow(command).to receive(:seek_action).and_return seek_action
624
+ expect(mock_client).to receive(:execute_command).with(seek_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
625
+ expect(command).to receive :seeking!
626
+ expect(command).to receive :stopped_seeking!
627
+ command.seek! seek_options
628
+ seek_action.request!
629
+ seek_action.execute!
630
+ end
631
+ end
632
+
633
+ describe "when seeking" do
634
+ before { command.seeking! }
635
+
636
+ it "should raise an error" do
637
+ expect { command.seek! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot seek an Output that is already seeking.")
638
+ end
639
+ end
640
+ end
641
+
642
+ describe "#seeking!" do
643
+ before do
644
+ command.request!
645
+ command.execute!
646
+ command.seeking!
647
+ end
648
+
649
+ describe '#seek_status_name' do
650
+ subject { command.seek_status_name }
651
+ it { is_expected.to eq(:seeking) }
652
+ end
653
+
654
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
655
+ expect { command.seeking! }.to raise_error(StateMachine::InvalidTransition)
656
+ end
657
+ end
658
+
659
+ describe "#stopped_seeking!" do
660
+ before do
661
+ command.request!
662
+ command.execute!
663
+ command.seeking!
664
+ command.stopped_seeking!
665
+ end
666
+
667
+ describe '#seek_status_name' do
668
+ subject { super().seek_status_name }
669
+ it { is_expected.to eq(:not_seeking) }
670
+ end
671
+
672
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
673
+ expect { command.stopped_seeking! }.to raise_error(StateMachine::InvalidTransition)
674
+ end
675
+ end
676
+ end
677
+
678
+ describe "adjusting speed" do
679
+ describe '#speed_up_action' do
680
+ subject { command.speed_up_action }
681
+
682
+ describe '#to_xml' do
683
+ subject { super().to_xml }
684
+ it { is_expected.to eq('<speed-up xmlns="urn:xmpp:rayo:output:1"/>') }
685
+ end
686
+
687
+ describe '#component_id' do
688
+ subject { super().component_id }
689
+ it { is_expected.to eq('abc123') }
690
+ end
691
+
692
+ describe '#target_call_id' do
693
+ subject { super().target_call_id }
694
+ it { is_expected.to eq('123abc') }
695
+ end
696
+ end
697
+
698
+ describe '#speed_up!' do
699
+ describe "when not altering speed" do
700
+ before do
701
+ command.request!
702
+ command.execute!
703
+ end
704
+
705
+ it "should send its command properly" do
706
+ speed_up_action = command.speed_up_action
707
+ allow(command).to receive(:speed_up_action).and_return speed_up_action
708
+ expect(mock_client).to receive(:execute_command).with(speed_up_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
709
+ expect(command).to receive :speeding_up!
710
+ expect(command).to receive :stopped_speeding!
711
+ command.speed_up!
712
+ speed_up_action.request!
713
+ speed_up_action.execute!
714
+ end
715
+ end
716
+
717
+ describe "when speeding up" do
718
+ before { command.speeding_up! }
719
+
720
+ it "should raise an error" do
721
+ expect { command.speed_up! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot speed up an Output that is already speeding.")
722
+ end
723
+ end
724
+
725
+ describe "when slowing down" do
726
+ before { command.slowing_down! }
727
+
728
+ it "should raise an error" do
729
+ expect { command.speed_up! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot speed up an Output that is already speeding.")
730
+ end
731
+ end
732
+ end
733
+
734
+ describe "#speeding_up!" do
735
+ before do
736
+ command.request!
737
+ command.execute!
738
+ command.speeding_up!
739
+ end
740
+
741
+ describe '#speed_status_name' do
742
+ subject { command.speed_status_name }
743
+ it { is_expected.to eq(:speeding_up) }
744
+ end
745
+
746
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
747
+ expect { command.speeding_up! }.to raise_error(StateMachine::InvalidTransition)
748
+ end
749
+ end
750
+
751
+ describe '#slow_down_action' do
752
+ subject { command.slow_down_action }
753
+
754
+ describe '#to_xml' do
755
+ subject { super().to_xml }
756
+ it { is_expected.to eq('<speed-down xmlns="urn:xmpp:rayo:output:1"/>') }
757
+ end
758
+
759
+ describe '#component_id' do
760
+ subject { super().component_id }
761
+ it { is_expected.to eq('abc123') }
762
+ end
763
+
764
+ describe '#target_call_id' do
765
+ subject { super().target_call_id }
766
+ it { is_expected.to eq('123abc') }
767
+ end
768
+ end
769
+
770
+ describe '#slow_down!' do
771
+ describe "when not altering speed" do
772
+ before do
773
+ command.request!
774
+ command.execute!
775
+ end
776
+
777
+ it "should send its command properly" do
778
+ slow_down_action = command.slow_down_action
779
+ allow(command).to receive(:slow_down_action).and_return slow_down_action
780
+ expect(mock_client).to receive(:execute_command).with(slow_down_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
781
+ expect(command).to receive :slowing_down!
782
+ expect(command).to receive :stopped_speeding!
783
+ command.slow_down!
784
+ slow_down_action.request!
785
+ slow_down_action.execute!
786
+ end
787
+ end
788
+
789
+ describe "when speeding up" do
790
+ before { command.speeding_up! }
791
+
792
+ it "should raise an error" do
793
+ expect { command.slow_down! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot slow down an Output that is already speeding.")
794
+ end
795
+ end
796
+
797
+ describe "when slowing down" do
798
+ before { command.slowing_down! }
799
+
800
+ it "should raise an error" do
801
+ expect { command.slow_down! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot slow down an Output that is already speeding.")
802
+ end
803
+ end
804
+ end
805
+
806
+ describe "#slowing_down!" do
807
+ before do
808
+ command.request!
809
+ command.execute!
810
+ command.slowing_down!
811
+ end
812
+
813
+ describe '#speed_status_name' do
814
+ subject { command.speed_status_name }
815
+ it { is_expected.to eq(:slowing_down) }
816
+ end
817
+
818
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
819
+ expect { command.slowing_down! }.to raise_error(StateMachine::InvalidTransition)
820
+ end
821
+ end
822
+
823
+ describe "#stopped_speeding!" do
824
+ before do
825
+ command.request!
826
+ command.execute!
827
+ command.speeding_up!
828
+ command.stopped_speeding!
829
+ end
830
+
831
+ describe '#speed_status_name' do
832
+ subject { command.speed_status_name }
833
+ it { is_expected.to eq(:not_speeding) }
834
+ end
835
+
836
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
837
+ expect { command.stopped_speeding! }.to raise_error(StateMachine::InvalidTransition)
838
+ end
839
+ end
840
+ end
841
+
842
+ describe "adjusting volume" do
843
+ describe '#volume_up_action' do
844
+ subject { command.volume_up_action }
845
+
846
+ describe '#to_xml' do
847
+ subject { super().to_xml }
848
+ it { is_expected.to eq('<volume-up xmlns="urn:xmpp:rayo:output:1"/>') }
849
+ end
850
+
851
+ describe '#component_id' do
852
+ subject { super().component_id }
853
+ it { is_expected.to eq('abc123') }
854
+ end
855
+
856
+ describe '#target_call_id' do
857
+ subject { super().target_call_id }
858
+ it { is_expected.to eq('123abc') }
859
+ end
860
+ end
861
+
862
+ describe '#volume_up!' do
863
+ describe "when not altering volume" do
864
+ before do
865
+ command.request!
866
+ command.execute!
867
+ end
868
+
869
+ it "should send its command properly" do
870
+ volume_up_action = command.volume_up_action
871
+ allow(command).to receive(:volume_up_action).and_return volume_up_action
872
+ expect(mock_client).to receive(:execute_command).with(volume_up_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
873
+ expect(command).to receive :voluming_up!
874
+ expect(command).to receive :stopped_voluming!
875
+ command.volume_up!
876
+ volume_up_action.request!
877
+ volume_up_action.execute!
878
+ end
879
+ end
880
+
881
+ describe "when voluming up" do
882
+ before { command.voluming_up! }
883
+
884
+ it "should raise an error" do
885
+ expect { command.volume_up! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot volume up an Output that is already voluming.")
886
+ end
887
+ end
888
+
889
+ describe "when voluming down" do
890
+ before { command.voluming_down! }
891
+
892
+ it "should raise an error" do
893
+ expect { command.volume_up! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot volume up an Output that is already voluming.")
894
+ end
895
+ end
896
+ end
897
+
898
+ describe "#voluming_up!" do
899
+ before do
900
+ command.request!
901
+ command.execute!
902
+ command.voluming_up!
903
+ end
904
+
905
+ describe '#volume_status_name' do
906
+ subject { command.volume_status_name }
907
+ it { is_expected.to eq(:voluming_up) }
908
+ end
909
+
910
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
911
+ expect { command.voluming_up! }.to raise_error(StateMachine::InvalidTransition)
912
+ end
913
+ end
914
+
915
+ describe '#volume_down_action' do
916
+ subject { command.volume_down_action }
917
+
918
+ describe '#to_xml' do
919
+ subject { super().to_xml }
920
+ it { is_expected.to eq('<volume-down xmlns="urn:xmpp:rayo:output:1"/>') }
921
+ end
922
+
923
+ describe '#component_id' do
924
+ subject { super().component_id }
925
+ it { is_expected.to eq('abc123') }
926
+ end
927
+
928
+ describe '#target_call_id' do
929
+ subject { super().target_call_id }
930
+ it { is_expected.to eq('123abc') }
931
+ end
932
+ end
933
+
934
+ describe '#volume_down!' do
935
+ describe "when not altering volume" do
936
+ before do
937
+ command.request!
938
+ command.execute!
939
+ end
940
+
941
+ it "should send its command properly" do
942
+ volume_down_action = command.volume_down_action
943
+ allow(command).to receive(:volume_down_action).and_return volume_down_action
944
+ expect(mock_client).to receive(:execute_command).with(volume_down_action, :target_call_id => '123abc', :component_id => 'abc123').and_return true
945
+ expect(command).to receive :voluming_down!
946
+ expect(command).to receive :stopped_voluming!
947
+ command.volume_down!
948
+ volume_down_action.request!
949
+ volume_down_action.execute!
950
+ end
951
+ end
952
+
953
+ describe "when voluming up" do
954
+ before { command.voluming_up! }
955
+
956
+ it "should raise an error" do
957
+ expect { command.volume_down! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot volume down an Output that is already voluming.")
958
+ end
959
+ end
960
+
961
+ describe "when voluming down" do
962
+ before { command.voluming_down! }
963
+
964
+ it "should raise an error" do
965
+ expect { command.volume_down! }.to raise_error(Adhearsion::Rayo::Component::InvalidActionError, "Cannot volume down an Output that is already voluming.")
966
+ end
967
+ end
968
+ end
969
+
970
+ describe "#voluming_down!" do
971
+ before do
972
+ command.request!
973
+ command.execute!
974
+ command.voluming_down!
975
+ end
976
+
977
+ describe '#volume_status_name' do
978
+ subject { command.volume_status_name }
979
+ it { is_expected.to eq(:voluming_down) }
980
+ end
981
+
982
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
983
+ expect { command.voluming_down! }.to raise_error(StateMachine::InvalidTransition)
984
+ end
985
+ end
986
+
987
+ describe "#stopped_voluming!" do
988
+ before do
989
+ command.request!
990
+ command.execute!
991
+ command.voluming_up!
992
+ command.stopped_voluming!
993
+ end
994
+
995
+ describe '#volume_status_name' do
996
+ subject { command.volume_status_name }
997
+ it { is_expected.to eq(:not_voluming) }
998
+ end
999
+
1000
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
1001
+ expect { command.stopped_voluming! }.to raise_error(StateMachine::InvalidTransition)
1002
+ end
1003
+ end
1004
+ end
1005
+ end
1006
+ end
1007
+
1008
+ {
1009
+ Adhearsion::Rayo::Component::Output::Complete::Finish => :finish,
1010
+ Adhearsion::Rayo::Component::Output::Complete::MaxTime => :'max-time',
1011
+ }.each do |klass, element_name|
1012
+ describe klass do
1013
+ let :stanza do
1014
+ <<-MESSAGE
1015
+ <complete xmlns='urn:xmpp:rayo:ext:1'>
1016
+ <#{element_name} xmlns='urn:xmpp:rayo:output:complete:1' />
1017
+ </complete>
1018
+ MESSAGE
1019
+ end
1020
+
1021
+ subject { Adhearsion::Rayo::RayoNode.from_xml(parse_stanza(stanza).root).reason }
1022
+
1023
+ it { is_expected.to be_instance_of klass }
1024
+
1025
+ describe '#name' do
1026
+ subject { super().name }
1027
+ it { is_expected.to eq(element_name) }
1028
+ end
1029
+ end
1030
+ end