adhearsion 2.0.0.beta1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.travis.yml +2 -4
  2. data/CHANGELOG.md +34 -4
  3. data/README.markdown +2 -1
  4. data/Rakefile +22 -1
  5. data/adhearsion.gemspec +1 -0
  6. data/bin/ahn +0 -2
  7. data/features/cli_daemon.feature +2 -0
  8. data/features/cli_restart.feature +19 -0
  9. data/features/cli_start.feature +4 -6
  10. data/features/cli_stop.feature +3 -0
  11. data/features/step_definitions/app_generator_steps.rb +2 -0
  12. data/features/step_definitions/cli_steps.rb +2 -0
  13. data/features/support/aruba_helper.rb +2 -0
  14. data/features/support/env.rb +8 -46
  15. data/features/support/utils.rb +2 -0
  16. data/lib/adhearsion.rb +4 -6
  17. data/lib/adhearsion/call.rb +71 -17
  18. data/lib/adhearsion/call_controller.rb +25 -14
  19. data/lib/adhearsion/call_controller/dial.rb +34 -15
  20. data/lib/adhearsion/call_controller/input.rb +186 -144
  21. data/lib/adhearsion/call_controller/output.rb +10 -6
  22. data/lib/adhearsion/call_controller/record.rb +11 -13
  23. data/lib/adhearsion/call_controller/utility.rb +2 -0
  24. data/lib/adhearsion/calls.rb +4 -2
  25. data/lib/adhearsion/cli.rb +4 -0
  26. data/lib/adhearsion/cli_commands.rb +8 -2
  27. data/lib/adhearsion/configuration.rb +7 -3
  28. data/lib/adhearsion/console.rb +17 -17
  29. data/lib/adhearsion/events.rb +10 -4
  30. data/lib/adhearsion/foundation.rb +9 -0
  31. data/lib/adhearsion/foundation/custom_daemonizer.rb +3 -1
  32. data/lib/adhearsion/foundation/exception_handler.rb +2 -0
  33. data/lib/adhearsion/foundation/libc.rb +2 -0
  34. data/lib/adhearsion/foundation/object.rb +3 -0
  35. data/lib/adhearsion/foundation/thread_safety.rb +5 -11
  36. data/lib/adhearsion/generators.rb +2 -0
  37. data/lib/adhearsion/generators/app/app_generator.rb +2 -0
  38. data/lib/adhearsion/generators/app/templates/README.md +9 -0
  39. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +38 -16
  40. data/lib/adhearsion/generators/app/templates/config/environment.rb +2 -0
  41. data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +5 -3
  42. data/lib/adhearsion/generators/controller/controller_generator.rb +2 -0
  43. data/lib/adhearsion/generators/controller/templates/lib/controller.rb +2 -0
  44. data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
  45. data/lib/adhearsion/generators/generator.rb +3 -1
  46. data/lib/adhearsion/generators/plugin/plugin_generator.rb +2 -0
  47. data/lib/adhearsion/initializer.rb +31 -17
  48. data/lib/adhearsion/linux_proc_name.rb +2 -0
  49. data/lib/adhearsion/logging.rb +5 -3
  50. data/lib/adhearsion/menu_dsl.rb +2 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match.rb +2 -0
  52. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +2 -0
  53. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +2 -0
  54. data/lib/adhearsion/menu_dsl/match_calculator.rb +2 -0
  55. data/lib/adhearsion/menu_dsl/menu.rb +58 -4
  56. data/lib/adhearsion/menu_dsl/menu_builder.rb +14 -1
  57. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +4 -1
  58. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +2 -0
  59. data/lib/adhearsion/outbound_call.rb +2 -0
  60. data/lib/adhearsion/plugin.rb +9 -7
  61. data/lib/adhearsion/plugin/collection.rb +3 -1
  62. data/lib/adhearsion/plugin/initializer.rb +3 -1
  63. data/lib/adhearsion/process.rb +8 -2
  64. data/lib/adhearsion/punchblock_plugin.rb +3 -1
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +34 -11
  66. data/lib/adhearsion/router.rb +4 -2
  67. data/lib/adhearsion/router/route.rb +2 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -0
  69. data/lib/adhearsion/tasks.rb +2 -0
  70. data/lib/adhearsion/tasks/configuration.rb +2 -0
  71. data/lib/adhearsion/tasks/debugging.rb +8 -0
  72. data/lib/adhearsion/tasks/environment.rb +2 -0
  73. data/lib/adhearsion/tasks/plugins.rb +2 -0
  74. data/lib/adhearsion/tasks/testing.rb +2 -0
  75. data/lib/adhearsion/version.rb +3 -1
  76. data/pre-commit +2 -0
  77. data/spec/adhearsion/call_controller/dial_spec.rb +114 -25
  78. data/spec/adhearsion/call_controller/input_spec.rb +192 -169
  79. data/spec/adhearsion/call_controller/output_spec.rb +26 -12
  80. data/spec/adhearsion/call_controller/record_spec.rb +29 -77
  81. data/spec/adhearsion/call_controller/utility_spec.rb +69 -0
  82. data/spec/adhearsion/call_controller_spec.rb +90 -15
  83. data/spec/adhearsion/call_spec.rb +92 -24
  84. data/spec/adhearsion/calls_spec.rb +9 -7
  85. data/spec/adhearsion/configuration_spec.rb +58 -56
  86. data/spec/adhearsion/console_spec.rb +4 -2
  87. data/spec/adhearsion/events_spec.rb +9 -7
  88. data/spec/adhearsion/generators_spec.rb +3 -1
  89. data/spec/adhearsion/initializer_spec.rb +16 -14
  90. data/spec/adhearsion/logging_spec.rb +11 -9
  91. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +6 -4
  92. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +6 -4
  93. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +3 -1
  94. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +2 -0
  95. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +42 -11
  96. data/spec/adhearsion/menu_dsl/menu_spec.rb +197 -36
  97. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +4 -2
  98. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +5 -3
  99. data/spec/adhearsion/outbound_call_spec.rb +7 -5
  100. data/spec/adhearsion/plugin_spec.rb +19 -15
  101. data/spec/adhearsion/process_spec.rb +12 -7
  102. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +35 -15
  103. data/spec/adhearsion/punchblock_plugin_spec.rb +4 -1
  104. data/spec/adhearsion/router/route_spec.rb +8 -6
  105. data/spec/adhearsion/router_spec.rb +12 -10
  106. data/spec/adhearsion_spec.rb +13 -2
  107. data/spec/capture_warnings.rb +33 -0
  108. data/spec/spec_helper.rb +4 -0
  109. data/spec/support/call_controller_test_helpers.rb +2 -4
  110. data/spec/support/initializer_stubs.rb +8 -5
  111. data/spec/support/logging_helpers.rb +2 -0
  112. data/spec/support/punchblock_mocks.rb +2 -0
  113. metadata +84 -71
  114. data/EVENTS +0 -11
  115. data/lib/adhearsion/call_controller/menu.rb +0 -124
  116. data/lib/adhearsion/foundation/all.rb +0 -8
  117. data/spec/adhearsion/call_controller/menu_spec.rb +0 -120
  118. data/spec/adhearsion/menu_dsl_spec.rb +0 -12
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Adhearsion
@@ -5,63 +7,33 @@ module Adhearsion
5
7
  describe Input do
6
8
  include CallControllerTestHelpers
7
9
 
8
- describe "#grammar_digits" do
9
- let(:grxml) {
10
- RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'inputdigits' do
11
- rule id: 'inputdigits', scope: 'public' do
12
- item repeat: '2' do
13
- one_of do
14
- 0.upto(9) { |d| item { d.to_s } }
15
- end
16
- end
17
- end
18
- end
19
- }
10
+ describe "#play_sound_files_for_menu" do
11
+ let(:options) { Hash.new }
12
+ let(:menu_instance) { Adhearsion::MenuDSL::Menu.new(options) }
13
+ let(:sound_file) { "press a button" }
14
+ let(:sound_files) { [sound_file] }
20
15
 
21
- it 'generates the correct GRXML grammar' do
22
- subject.grammar_digits(2).to_s.should == grxml.to_s
16
+ it "should play the sound files for the menu" do
17
+ subject.should_receive(:interruptible_play).with(sound_file).and_return("1")
18
+ subject.play_sound_files_for_menu(menu_instance, sound_files).should be == '1'
23
19
  end
24
20
 
25
- end # describe #grammar_digits
26
-
27
- describe "#grammar_accept" do
28
- let(:grxml) {
29
- RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'inputdigits' do
30
- rule id: 'inputdigits', scope: 'public' do
31
- one_of do
32
- item { '3' }
33
- item { '5' }
34
- end
35
- end
36
- end
37
- }
38
-
39
- it 'generates the correct GRXML grammar' do
40
- subject.grammar_accept('35').to_s.should == grxml.to_s
41
- end
42
-
43
- it 'filters meaningless characters out' do
44
- subject.grammar_accept('3+5').to_s.should == grxml.to_s
45
- end
46
- end # grammar_accept
47
-
48
- describe "#parse_single_dtmf" do
49
- it "correctly returns the parsed input" do
50
- subject.parse_single_dtmf("dtmf-3").should == '3'
51
- end
52
-
53
- it "correctly returns star as *" do
54
- subject.parse_single_dtmf("dtmf-star").should == '*'
21
+ it "should wait for digit if nothing is pressed during playback" do
22
+ subject.should_receive(:interruptible_play).with(sound_file).and_return(nil)
23
+ subject.should_receive(:wait_for_digit).with(menu_instance.timeout).and_return("1")
24
+ subject.play_sound_files_for_menu(menu_instance, sound_files).should be == '1'
55
25
  end
56
26
 
57
- it "correctly returns pound as #" do
58
- subject.parse_single_dtmf("dtmf-pound").should == '#'
59
- end
27
+ context "when the menu is not interruptible" do
28
+ let(:options) { { :interruptible => false } }
60
29
 
61
- it "correctly returns nil when input is nil" do
62
- subject.parse_single_dtmf(nil).should == nil
30
+ it "should play the sound files and wait for digit" do
31
+ subject.should_receive(:play).with(sound_file).and_return true
32
+ subject.should_receive(:wait_for_digit).with(menu_instance.timeout).and_return("1")
33
+ subject.play_sound_files_for_menu(menu_instance, sound_files).should be == '1'
34
+ end
63
35
  end
64
- end # describe #grammar_accept
36
+ end#play_sound_files_for_menu
65
37
 
66
38
  describe "#wait_for_digit" do
67
39
  let(:timeout) { 2 }
@@ -109,7 +81,7 @@ module Adhearsion
109
81
  it "returns the correct pressed digit" do
110
82
  expect_component_complete_event
111
83
  subject.should_receive(:execute_component_and_await_completion).once.with(Punchblock::Component::Input).and_return input_component
112
- subject.wait_for_digit(timeout).should == '5'
84
+ subject.wait_for_digit(timeout).should be == '5'
113
85
  end
114
86
 
115
87
  context "with a nil timeout" do
@@ -124,155 +96,206 @@ module Adhearsion
124
96
  end
125
97
  end # wait_for_digit
126
98
 
127
- describe "#input!" do
128
- describe "simple usage" do
129
- let(:timeout) { 3000 }
99
+ describe "#jump_to" do
100
+ let(:match_object) { flexmock(Class.new) }
101
+ let(:overrides) { Hash.new(:extension => "1") }
102
+ let(:block) { Proc.new {} }
130
103
 
131
- it "can be called with no arguments" do
132
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
133
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
134
- subject.input!
135
- end
104
+ it "calls instance_exec if the match object has a block" do
105
+ match_object.should_receive(:block).and_return(block)
106
+ subject.should_receive(:instance_exec).with(overrides[:extension], block)
107
+ subject.jump_to(match_object, overrides)
108
+ end
136
109
 
137
- it "can be called with 1 digit as an argument" do
138
- subject.should_receive(:wait_for_digit).with(nil)
139
- subject.input! 1
140
- end
110
+ it "calls invoke if the match object does not have a block" do
111
+ match_object.should_receive(:block).and_return(false)
112
+ match_object.should_receive(:match_payload).and_return(:payload)
113
+ subject.should_receive(:invoke).with(:payload, overrides)
114
+ subject.jump_to(match_object, overrides)
115
+ end
116
+ end#jump_to
141
117
 
142
- it "accepts a timeout argument" do
143
- subject.should_receive(:wait_for_digit).with(3000)
144
- subject.input! :timeout => timeout
145
- end
118
+ describe "#menu" do
119
+ let(:sound_files) { ["press", "button"] }
120
+
121
+ let(:menu_instance) do
122
+ MenuDSL::Menu.new { match(1) {} }
146
123
  end
147
124
 
148
- describe "any number of digits with a terminator" do
149
- let(:terminator) { '9' }
125
+ let(:result_done) { MenuDSL::Menu::MenuResultDone.new }
126
+ let(:result_terminated) { MenuDSL::Menu::MenuTerminated.new }
127
+ let(:result_limit_reached) { MenuDSL::Menu::MenuLimitReached.new }
128
+ let(:result_invalid) { MenuDSL::Menu::MenuResultInvalid.new }
129
+ let(:result_get_another_or_timeout) { MenuDSL::Menu::MenuGetAnotherDigitOrTimeout.new }
130
+ let(:result_get_another_or_finish) { MenuDSL::Menu::MenuGetAnotherDigitOrFinish.new(:match_object, :new_extension) }
131
+ let(:result_found) { MenuDSL::Menu::MenuResultFound.new(:match_object, :new_extension) }
150
132
 
151
- it "called with no arguments, it returns any number of digits taking a terminating digit" do
152
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
153
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
154
- subject.input!.should == '1'
155
- end
133
+ let(:status) { :foo }
134
+ let(:response) { '1234' }
156
135
 
157
- it "allows to set a different terminator" do
158
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
159
- subject.should_receive(:wait_for_digit).once.with(nil).and_return(terminator)
160
- subject.input!(:terminator => terminator).should == '1'
161
- end
136
+ before do
137
+ flexmock menu_instance, :status => status, :result => response
138
+ flexmock(MenuDSL::Menu).should_receive(:new).and_return(menu_instance)
162
139
  end
163
140
 
164
- describe "with a fixed number or digits" do
165
- it "accepts and returns three digits without a terminator" do
166
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
167
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('2')
168
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('3')
169
- subject.input!(3).should == '123'
170
- end
141
+ it "exits the function if MenuResultDone" do
142
+ menu_instance.should_receive(:should_continue?).and_return(true)
143
+ menu_instance.should_receive(:continue).and_return(result_done)
144
+ result = subject.menu sound_files
145
+ result.menu.should be menu_instance
146
+ result.response.should be response
171
147
  end
172
148
 
173
- describe "with play arguments" do
174
- let(:string_play) { "Thanks for calling" }
175
- let(:ssml_play) { RubySpeech::SSML.draw { string "Please stand by" } }
176
- let(:hash_play) { {:value => Time.parse("24/10/2011"), :strftime => "%H:%M"} }
177
- let(:hash_value) { Time.parse "24/10/2011" }
178
- let(:hash_options) { {:strftime => "%H:%M"} }
179
-
180
- it "plays a string argument" do
181
- subject.should_receive(:interruptible_play!).with(string_play)
182
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
183
- subject.input! :play => string_play
184
- end
149
+ it "exits the function if MenuTerminated" do
150
+ menu_instance.should_receive(:should_continue?).and_return(true)
151
+ menu_instance.should_receive(:continue).and_return(result_terminated)
152
+ result = subject.menu sound_files
153
+ result.menu.should be menu_instance
154
+ result.response.should be response
155
+ end
185
156
 
186
- it "plays a SSML argument" do
187
- subject.should_receive(:interruptible_play!).with(ssml_play)
188
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
189
- subject.input! :play => ssml_play
190
- end
157
+ it "exits the function if MenuLimitReached" do
158
+ menu_instance.should_receive(:should_continue?).and_return(true)
159
+ menu_instance.should_receive(:continue).and_return(result_limit_reached)
160
+ result = subject.menu sound_files
161
+ result.menu.should be menu_instance
162
+ result.response.should be response
163
+ end
191
164
 
192
- it "plays a Hash argument" do
193
- subject.should_receive(:interruptible_play!).with([hash_value, hash_options])
194
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
195
- subject.input! :play => hash_play
196
- end
165
+ it "executes failure hook and returns :failure if menu fails" do
166
+ menu_instance.should_receive(:should_continue?).and_return(false)
167
+ menu_instance.should_receive(:execute_failure_hook)
168
+ result = subject.menu sound_files
169
+ result.menu.should be menu_instance
170
+ result.response.should be response
171
+ end
197
172
 
198
- it "plays an array of mixed arguments" do
199
- subject.should_receive(:interruptible_play!).with(string_play)
200
- subject.should_receive(:interruptible_play!).with(ssml_play)
201
- subject.should_receive(:interruptible_play!).with([hash_value, hash_options])
202
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
203
- subject.input! :play => [string_play, ssml_play, hash_play]
204
- end
173
+ it "executes invalid hook if input is invalid" do
174
+ menu_instance.should_receive(:should_continue?).twice.and_return(true)
175
+ menu_instance.should_receive(:continue).and_return(result_invalid, result_done)
176
+ menu_instance.should_receive(:execute_invalid_hook)
177
+ menu_instance.should_receive(:restart!)
178
+ result = subject.menu sound_files
179
+ result.menu.should be menu_instance
180
+ result.response.should be response
181
+ end
205
182
 
206
- it "plays a string argument, takes 1 digit and returns the input" do
207
- subject.should_receive(:interruptible_play!).with(string_play).and_return('1')
208
- subject.input!(1, :play => string_play).should == '1'
209
- end
183
+ it "plays audio, then executes timeout hook if input times out" do
184
+ menu_instance.should_receive(:should_continue?).twice.and_return(true)
185
+ menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
186
+ subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return(nil)
187
+ menu_instance.should_receive(:execute_timeout_hook)
188
+ menu_instance.should_receive(:restart!)
189
+ subject.menu sound_files
190
+ end
210
191
 
211
- it "plays a string argument, takes 2 digits and returns the input" do
212
- subject.should_receive(:interruptible_play!).with(string_play).and_return('1')
213
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
214
- subject.input!(2, :play => string_play).should == '11'
215
- end
192
+ it "plays audio, then adds digit to digit buffer if input is received" do
193
+ menu_instance.should_receive(:should_continue?).twice.and_return(true)
194
+ menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
195
+ subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return("1")
196
+ menu_instance.should_receive(:<<).with("1")
197
+ subject.menu sound_files
198
+ end
216
199
 
217
- it "plays a string argument, allows for any number of digit and an accept key" do
218
- subject.should_receive(:interruptible_play!).with(string_play).and_return('1').ordered
219
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('2').ordered
220
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#').ordered
221
- subject.input!(:play => string_play).should == '12'
222
- end
200
+ it "plays audio, then jumps to payload when input is finished" do
201
+ menu_instance.should_receive(:should_continue?).and_return(true)
202
+ menu_instance.should_receive(:continue).and_return(result_get_another_or_finish)
203
+ subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return(nil)
204
+ subject.should_receive(:jump_to).with(:match_object, :extension => :new_extension)
205
+ subject.menu sound_files
206
+ end
223
207
 
224
- it "plays an array of mixed arguments, stops playing when a key is pressed, and returns the input" do
225
- subject.should_receive(:interruptible_play!).and_return(nil, '1', StandardError.new("should not be called"))
226
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
227
- subject.input!(:play => [string_play, ssml_play, hash_play]).should == '1'
228
- end
229
- end # describe with play arguments
208
+ it "jumps to payload when result is found" do
209
+ menu_instance.should_receive(:should_continue?).and_return(true)
210
+ menu_instance.should_receive(:continue).and_return(result_found)
211
+ subject.should_receive(:jump_to).with(:match_object, :extension => :new_extension)
212
+ result = subject.menu sound_files
213
+ result.menu.should be menu_instance
214
+ result.response.should be response
215
+ end
230
216
 
231
- describe "non interruptible play" do
232
- let(:string_play) { "Thanks for calling" }
217
+ context "if a digit limit is specified" do
218
+ it "should raise an ArgumentError"
219
+ end
233
220
 
234
- it "calls play! when passed :interruptible => false" do
235
- subject.should_receive(:play!).with(string_play)
236
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
237
- subject.input! :play => string_play, :interruptible => false
238
- end
221
+ context "if a terminator digit is specified" do
222
+ it "should raise an ArgumentError"
223
+ end
224
+
225
+ end#describe
226
+
227
+ describe "#ask" do
228
+ let(:sound_files) { ["press", "button"] }
229
+
230
+ context "mocking out the menu" do
231
+ let(:menu_instance) { MenuDSL::Menu.new :limit => 2 }
232
+
233
+ let(:result_done) { MenuDSL::Menu::MenuResultDone.new }
234
+ let(:result_terminated) { MenuDSL::Menu::MenuTerminated.new }
235
+ let(:result_limit_reached) { MenuDSL::Menu::MenuLimitReached.new }
236
+ let(:result_invalid) { MenuDSL::Menu::MenuResultInvalid.new }
237
+ let(:result_get_another_or_timeout) { MenuDSL::Menu::MenuGetAnotherDigitOrTimeout.new }
238
+ let(:result_get_another_or_finish) { MenuDSL::Menu::MenuGetAnotherDigitOrFinish.new(:match_object, :new_extension) }
239
+ let(:result_found) { MenuDSL::Menu::MenuResultFound.new(:match_object, :new_extension) }
239
240
 
240
- it "still collects digits when passed :interruptible => false" do
241
- subject.should_receive(:play!).with(string_play)
242
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('1')
243
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
244
- subject.input!(:play => string_play, :interruptible => false).should == '1'
241
+ let(:status) { :foo }
242
+ let(:response) { '1234' }
243
+
244
+ before do
245
+ flexmock menu_instance, :status => status, :result => response
246
+ flexmock(MenuDSL::Menu).should_receive(:new).and_return(menu_instance)
245
247
  end
246
- end # describe non interruptible play
247
248
 
248
- describe "speak functionality" do
249
- let(:string_speak) { "Thanks for calling" }
249
+ it "exits the function if MenuResultDone" do
250
+ menu_instance.should_receive(:continue).and_return(result_done)
251
+ result = subject.ask sound_files
252
+ result.menu.should be menu_instance
253
+ result.response.should be response
254
+ end
250
255
 
251
- it "speaks passed text" do
252
- subject.should_receive(:interruptible_play!).with(string_speak, {})
253
- subject.input! :speak => {:text => string_speak }
256
+ it "exits the function if MenuTerminated" do
257
+ menu_instance.should_receive(:continue).and_return(result_terminated)
258
+ result = subject.ask sound_files
259
+ result.menu.should be menu_instance
260
+ result.response.should be response
254
261
  end
255
262
 
256
- it "speaks passed text and collect digits" do
257
- subject.should_receive(:interruptible_play!).with(string_speak, {}).and_return('1')
258
- subject.should_receive(:wait_for_digit).once.with(nil).and_return('#')
259
- subject.input!(:speak => {:text => string_speak }).should == '1'
263
+ it "exits the function if MenuLimitReached" do
264
+ menu_instance.should_receive(:continue).and_return(result_limit_reached)
265
+ result = subject.ask sound_files
266
+ result.menu.should be menu_instance
267
+ result.response.should be response
260
268
  end
261
- end
262
269
 
263
- it 'throws an exception when playback fails'
264
- end # describe input!
270
+ it "plays audio, then executes timeout hook if input times out" do
271
+ menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
272
+ subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return(nil)
273
+ menu_instance.should_receive(:execute_timeout_hook)
274
+ menu_instance.should_receive(:restart!)
275
+ subject.ask sound_files
276
+ end
265
277
 
266
- describe "#input" do
267
- let(:string_play) { "Thanks for calling" }
278
+ it "plays audio, then adds digit to digit buffer if input is received" do
279
+ menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
280
+ subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return("1")
281
+ menu_instance.should_receive(:<<).with("1")
282
+ subject.ask sound_files
283
+ end
284
+ end
268
285
 
269
- it "just calls #input!" do
270
- subject.should_receive(:input!).with(:play => string_play).and_return(nil)
271
- subject.input! :play => string_play
286
+ context "with a block passed" do
287
+ it "should set that block as the buffer validator" do
288
+ foo = nil
289
+ subject.should_receive(:play_sound_files_for_menu).and_return("1")
290
+ subject.ask sound_files, :limit => 0 do |buffer|
291
+ foo = :bar
292
+ end.menu.execute_validator_hook
293
+ foo.should be == :bar
294
+ end
272
295
  end
273
296
 
274
- it 'does not throw exceptions when playback fails'
275
- end # describe input
276
- end
297
+ end#describe
298
+
299
+ end#shared
277
300
  end
278
301
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Adhearsion
@@ -267,17 +269,23 @@ module Adhearsion
267
269
 
268
270
  it "raises an exception if play fails" do
269
271
  subject.should_receive(:play).once.and_return false
270
- expect { subject.play!(non_existing) }.to raise_error(Adhearsion::PlaybackError)
272
+ expect { subject.play!(non_existing) }.to raise_error(Output::PlaybackError)
271
273
  end
272
274
  end
273
275
 
274
276
  describe "#speak" do
277
+ it "should be an alias for #say" do
278
+ subject.method(:speak).should be == subject.method(:say)
279
+ end
280
+ end
281
+
282
+ describe "#say" do
275
283
  describe "with a RubySpeech document" do
276
284
  it 'plays the correct SSML' do
277
285
  doc = RubySpeech::SSML.draw { string "Hello world" }
278
286
  subject.should_receive(:play_ssml).once.with(doc, {}).and_return true
279
287
  subject.should_receive(:output).never
280
- subject.speak(doc).should be true
288
+ subject.say(doc).should be true
281
289
  end
282
290
  end
283
291
 
@@ -286,7 +294,7 @@ module Adhearsion
286
294
  string = "Hello world"
287
295
  subject.should_receive(:play_ssml).once.with(string, {})
288
296
  subject.should_receive(:output).once.with(:text, string, {}).and_return true
289
- subject.speak(string).should be true
297
+ subject.say(string).should be true
290
298
  end
291
299
  end
292
300
 
@@ -296,7 +304,7 @@ module Adhearsion
296
304
  argument = 123
297
305
  subject.should_receive(:play_ssml).once.with(argument, {})
298
306
  subject.should_receive(:output).once.with(:text, expected_string, {}).and_return true
299
- subject.speak(argument)
307
+ subject.say(argument)
300
308
  end
301
309
  end
302
310
  end
@@ -311,7 +319,7 @@ module Adhearsion
311
319
  end
312
320
 
313
321
  it 'returns SSML for a text argument' do
314
- subject.ssml_for(prompt).should == ssml
322
+ subject.ssml_for(prompt).should be == ssml
315
323
  end
316
324
 
317
325
  it 'returns the same SSML passed in if it is SSML' do
@@ -326,8 +334,14 @@ module Adhearsion
326
334
  end
327
335
 
328
336
  it "detects a file path" do
329
- http_path = "/usr/shared/sounds/hello.mp3"
330
- subject.detect_type(http_path).should be :audio
337
+ file_path = "file:///usr/shared/sounds/hello.mp3"
338
+ subject.detect_type(file_path).should be :audio
339
+
340
+ absolute_path = "/usr/shared/sounds/hello.mp3"
341
+ subject.detect_type(absolute_path).should be :audio
342
+
343
+ relative_path = "foo/bar"
344
+ subject.detect_type(relative_path).should_not be :audio
331
345
  end
332
346
 
333
347
  it "detects a Date object" do
@@ -424,7 +438,7 @@ module Adhearsion
424
438
  expect_component_complete_event
425
439
  flexmock(Punchblock::Component::Output).new_instances.should_receive(:stop!)
426
440
  subject.should_receive(:execute_component_and_await_completion).once.with(output_component)
427
- subject.stream_file(prompt, allowed_digits).should == '5'
441
+ subject.stream_file(prompt, allowed_digits).should be == '5'
428
442
  end
429
443
  end # describe #stream_file
430
444
 
@@ -445,8 +459,8 @@ module Adhearsion
445
459
  end
446
460
 
447
461
  it 'raises an exception when output is unsuccessful' do
448
- subject.should_receive(:stream_file).once.and_raise PlaybackError, "Output failed"
449
- expect { subject.interruptible_play!(non_existing) }.to raise_error(Adhearsion::PlaybackError)
462
+ subject.should_receive(:stream_file).once.and_raise Output::PlaybackError, "Output failed"
463
+ expect { subject.interruptible_play!(non_existing) }.to raise_error(Output::PlaybackError)
450
464
  end
451
465
  end # describe interruptible_play!
452
466
 
@@ -466,8 +480,8 @@ module Adhearsion
466
480
  end
467
481
 
468
482
  it "should not raise an exception when output is unsuccessful" do
469
- subject.should_receive(:stream_file).once.and_raise PlaybackError, "Output failed"
470
- lambda { subject.interruptible_play non_existing }.should_not raise_error(Adhearsion::PlaybackError)
483
+ subject.should_receive(:stream_file).once.and_raise Output::PlaybackError, "Output failed"
484
+ lambda { subject.interruptible_play non_existing }.should_not raise_error(Output::PlaybackError)
471
485
  end
472
486
  end # describe interruptible_play
473
487