punchblock 0.8.4 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/Rakefile +0 -6
- data/lib/punchblock.rb +0 -6
- data/lib/punchblock/command/dial.rb +1 -0
- data/lib/punchblock/connection/xmpp.rb +2 -1
- data/lib/punchblock/translator/asterisk/call.rb +12 -10
- data/lib/punchblock/translator/asterisk/component.rb +2 -0
- data/lib/punchblock/translator/asterisk/component/asterisk.rb +0 -2
- data/lib/punchblock/translator/asterisk/component/input.rb +114 -0
- data/lib/punchblock/translator/asterisk/component/output.rb +92 -0
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +0 -1
- data/spec/punchblock/translator/asterisk/call_spec.rb +29 -3
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +282 -0
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +491 -0
- metadata +46 -60
- data/lib/punchblock/component/tropo.rb +0 -9
- data/lib/punchblock/component/tropo/conference.rb +0 -331
- data/lib/punchblock/translator/asterisk/component/asterisk/input.rb +0 -116
- data/lib/punchblock/translator/asterisk/component/asterisk/output.rb +0 -94
- data/spec/punchblock/component/tropo/conference_spec.rb +0 -361
- data/spec/punchblock/translator/asterisk/component/asterisk/input_spec.rb +0 -284
- data/spec/punchblock/translator/asterisk/component/asterisk/output_spec.rb +0 -493
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Translator
|
|
5
|
+
class Asterisk
|
|
6
|
+
module Component
|
|
7
|
+
describe Output do
|
|
8
|
+
let(:connection) do
|
|
9
|
+
mock_connection_with_event_handler do |event|
|
|
10
|
+
command.add_event event
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
let(:media_engine) { nil }
|
|
14
|
+
let(:translator) { Punchblock::Translator::Asterisk.new mock('AMI'), connection, media_engine }
|
|
15
|
+
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator }
|
|
16
|
+
|
|
17
|
+
let :command do
|
|
18
|
+
Punchblock::Component::Output.new command_options
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
let :ssml_doc do
|
|
22
|
+
RubySpeech::SSML.draw do
|
|
23
|
+
say_as(:interpret_as => :cardinal) { 'FOO' }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
let :command_options do
|
|
28
|
+
{ :ssml => ssml_doc }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
subject { Output.new command, mock_call }
|
|
32
|
+
|
|
33
|
+
describe '#execute' do
|
|
34
|
+
before { command.request! }
|
|
35
|
+
|
|
36
|
+
context 'with a media engine of :unimrcp' do
|
|
37
|
+
let(:media_engine) { :unimrcp }
|
|
38
|
+
|
|
39
|
+
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
|
40
|
+
|
|
41
|
+
let :ssml_doc do
|
|
42
|
+
RubySpeech::SSML.draw do
|
|
43
|
+
audio :src => audio_filename
|
|
44
|
+
say_as(:interpret_as => :cardinal) { 'FOO' }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
let(:command_opts) { {} }
|
|
49
|
+
|
|
50
|
+
let :command_options do
|
|
51
|
+
{ :ssml => ssml_doc }.merge(command_opts)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def expect_mrcpsynth_with_options(options)
|
|
55
|
+
mock_call.expects(:send_agi_action!).once.with do |*args|
|
|
56
|
+
args[0].should == 'EXEC MRCPSynth'
|
|
57
|
+
args[2].should match options
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should execute MRCPSynth" do
|
|
62
|
+
mock_call.expects(:send_agi_action!).once.with 'EXEC MRCPSynth', ssml_doc.to_s.squish.gsub(/["\\]/) { |m| "\\#{m}" }, ''
|
|
63
|
+
subject.execute
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should send a complete event when MRCPSynth completes' do
|
|
67
|
+
def mock_call.send_agi_action!(*args, &block)
|
|
68
|
+
block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1)
|
|
69
|
+
end
|
|
70
|
+
subject.execute
|
|
71
|
+
command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'ssml' do
|
|
75
|
+
context 'unset' do
|
|
76
|
+
let(:command_opts) { { :ssml => nil } }
|
|
77
|
+
it "should return an error and not execute any actions" do
|
|
78
|
+
subject.execute
|
|
79
|
+
error = ProtocolError.new 'option error', 'An SSML document is required.'
|
|
80
|
+
command.response(0.1).should == error
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe 'start-offset' do
|
|
86
|
+
context 'unset' do
|
|
87
|
+
let(:command_opts) { { :start_offset => nil } }
|
|
88
|
+
it 'should not pass any options to MRCPSynth' do
|
|
89
|
+
expect_mrcpsynth_with_options(//)
|
|
90
|
+
subject.execute
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'set' do
|
|
95
|
+
let(:command_opts) { { :start_offset => 10 } }
|
|
96
|
+
it "should return an error and not execute any actions" do
|
|
97
|
+
subject.execute
|
|
98
|
+
error = ProtocolError.new 'option error', 'A start_offset value is unsupported on Asterisk.'
|
|
99
|
+
command.response(0.1).should == error
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe 'start-paused' do
|
|
105
|
+
context 'false' do
|
|
106
|
+
let(:command_opts) { { :start_paused => false } }
|
|
107
|
+
it 'should not pass any options to MRCPSynth' do
|
|
108
|
+
expect_mrcpsynth_with_options(//)
|
|
109
|
+
subject.execute
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'true' do
|
|
114
|
+
let(:command_opts) { { :start_paused => true } }
|
|
115
|
+
it "should return an error and not execute any actions" do
|
|
116
|
+
subject.execute
|
|
117
|
+
error = ProtocolError.new 'option error', 'A start_paused value is unsupported on Asterisk.'
|
|
118
|
+
command.response(0.1).should == error
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe 'repeat-interval' do
|
|
124
|
+
context 'unset' do
|
|
125
|
+
let(:command_opts) { { :repeat_interval => nil } }
|
|
126
|
+
it 'should not pass any options to MRCPSynth' do
|
|
127
|
+
expect_mrcpsynth_with_options(//)
|
|
128
|
+
subject.execute
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'set' do
|
|
133
|
+
let(:command_opts) { { :repeat_interval => 10 } }
|
|
134
|
+
it "should return an error and not execute any actions" do
|
|
135
|
+
subject.execute
|
|
136
|
+
error = ProtocolError.new 'option error', 'A repeat_interval value is unsupported on Asterisk.'
|
|
137
|
+
command.response(0.1).should == error
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
describe 'repeat-times' do
|
|
143
|
+
context 'unset' do
|
|
144
|
+
let(:command_opts) { { :repeat_times => nil } }
|
|
145
|
+
it 'should not pass any options to MRCPSynth' do
|
|
146
|
+
expect_mrcpsynth_with_options(//)
|
|
147
|
+
subject.execute
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context 'set' do
|
|
152
|
+
let(:command_opts) { { :repeat_times => 2 } }
|
|
153
|
+
it "should return an error and not execute any actions" do
|
|
154
|
+
subject.execute
|
|
155
|
+
error = ProtocolError.new 'option error', 'A repeat_times value is unsupported on Asterisk.'
|
|
156
|
+
command.response(0.1).should == error
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
describe 'max-time' do
|
|
162
|
+
context 'unset' do
|
|
163
|
+
let(:command_opts) { { :max_time => nil } }
|
|
164
|
+
it 'should not pass any options to MRCPSynth' do
|
|
165
|
+
expect_mrcpsynth_with_options(//)
|
|
166
|
+
subject.execute
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context 'set' do
|
|
171
|
+
let(:command_opts) { { :max_time => 30 } }
|
|
172
|
+
it "should return an error and not execute any actions" do
|
|
173
|
+
subject.execute
|
|
174
|
+
error = ProtocolError.new 'option error', 'A max_time value is unsupported on Asterisk.'
|
|
175
|
+
command.response(0.1).should == error
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
describe 'voice' do
|
|
181
|
+
context 'unset' do
|
|
182
|
+
let(:command_opts) { { :voice => nil } }
|
|
183
|
+
it 'should not pass the v option to MRCPSynth' do
|
|
184
|
+
expect_mrcpsynth_with_options(//)
|
|
185
|
+
subject.execute
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
context 'set' do
|
|
190
|
+
let(:command_opts) { { :voice => 'alison' } }
|
|
191
|
+
it 'should pass the v option to MRCPSynth' do
|
|
192
|
+
expect_mrcpsynth_with_options(/v=alison/)
|
|
193
|
+
subject.execute
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe 'interrupt_on' do
|
|
199
|
+
context "set to nil" do
|
|
200
|
+
let(:command_opts) { { :interrupt_on => nil } }
|
|
201
|
+
it "should not pass the i option to MRCPSynth" do
|
|
202
|
+
expect_mrcpsynth_with_options(//)
|
|
203
|
+
subject.execute
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
context "set to :any" do
|
|
208
|
+
let(:command_opts) { { :interrupt_on => :any } }
|
|
209
|
+
it "should pass the i option to MRCPSynth" do
|
|
210
|
+
expect_mrcpsynth_with_options(/i=any/)
|
|
211
|
+
subject.execute
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "set to :dtmf" do
|
|
216
|
+
let(:command_opts) { { :interrupt_on => :dtmf } }
|
|
217
|
+
it "should pass the i option to MRCPSynth" do
|
|
218
|
+
expect_mrcpsynth_with_options(/i=any/)
|
|
219
|
+
subject.execute
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context "set to :speech" do
|
|
224
|
+
let(:command_opts) { { :interrupt_on => :speech } }
|
|
225
|
+
it "should return an error and not execute any actions" do
|
|
226
|
+
subject.execute
|
|
227
|
+
error = ProtocolError.new 'option error', 'An interrupt-on value of speech is unsupported.'
|
|
228
|
+
command.response(0.1).should == error
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context 'with a media engine of :asterisk' do
|
|
235
|
+
let(:media_engine) { :asterisk }
|
|
236
|
+
|
|
237
|
+
def expect_stream_file_with_options(options = nil)
|
|
238
|
+
mock_call.expects(:send_agi_action!).once.with 'STREAM FILE', audio_filename, options do |*args|
|
|
239
|
+
args[2].should == options
|
|
240
|
+
subject.continue!
|
|
241
|
+
true
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
|
246
|
+
|
|
247
|
+
let :ssml_doc do
|
|
248
|
+
RubySpeech::SSML.draw do
|
|
249
|
+
audio :src => audio_filename
|
|
250
|
+
say_as(:interpret_as => :cardinal) { 'FOO' }
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
let(:command_opts) { {} }
|
|
255
|
+
|
|
256
|
+
let :command_options do
|
|
257
|
+
{ :ssml => ssml_doc }.merge(command_opts)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
let :command do
|
|
261
|
+
Punchblock::Component::Output.new command_options
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
describe 'ssml' do
|
|
265
|
+
context 'unset' do
|
|
266
|
+
let(:command_opts) { { :ssml => nil } }
|
|
267
|
+
it "should return an error and not execute any actions" do
|
|
268
|
+
subject.execute
|
|
269
|
+
error = ProtocolError.new 'option error', 'An SSML document is required.'
|
|
270
|
+
command.response(0.1).should == error
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context 'with a single audio SSML node' do
|
|
275
|
+
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
|
276
|
+
let :command_options do
|
|
277
|
+
{
|
|
278
|
+
:ssml => RubySpeech::SSML.draw { audio :src => audio_filename }
|
|
279
|
+
}
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it 'should playback the audio file using STREAM FILE' do
|
|
283
|
+
expect_stream_file_with_options
|
|
284
|
+
subject.execute
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'should send a complete event when the file finishes playback' do
|
|
288
|
+
def mock_call.send_agi_action!(*args, &block)
|
|
289
|
+
block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1)
|
|
290
|
+
end
|
|
291
|
+
subject.execute
|
|
292
|
+
command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
context 'with multiple audio SSML nodes' do
|
|
297
|
+
let(:audio_filename1) { 'http://foo.com/bar.mp3' }
|
|
298
|
+
let(:audio_filename2) { 'http://foo.com/baz.mp3' }
|
|
299
|
+
let :command_options do
|
|
300
|
+
{
|
|
301
|
+
:ssml => RubySpeech::SSML.draw do
|
|
302
|
+
audio :src => audio_filename1
|
|
303
|
+
audio :src => audio_filename2
|
|
304
|
+
end
|
|
305
|
+
}
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it 'should playback each audio file using STREAM FILE' do
|
|
309
|
+
latch = CountDownLatch.new 2
|
|
310
|
+
mock_call.expects(:send_agi_action!).once.with 'STREAM FILE', audio_filename1, nil do
|
|
311
|
+
subject.continue
|
|
312
|
+
true
|
|
313
|
+
latch.countdown!
|
|
314
|
+
end
|
|
315
|
+
mock_call.expects(:send_agi_action!).once.with 'STREAM FILE', audio_filename2, nil do
|
|
316
|
+
subject.continue
|
|
317
|
+
true
|
|
318
|
+
latch.countdown!
|
|
319
|
+
end
|
|
320
|
+
subject.execute
|
|
321
|
+
latch.wait 2
|
|
322
|
+
sleep 2
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
it 'should send a complete event after the final file has finished playback' do
|
|
326
|
+
def mock_call.send_agi_action!(*args, &block)
|
|
327
|
+
block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1)
|
|
328
|
+
end
|
|
329
|
+
command.expects(:add_event).once.with do |e|
|
|
330
|
+
e.reason.should be_a Punchblock::Component::Output::Complete::Success
|
|
331
|
+
end
|
|
332
|
+
subject.execute
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
describe 'start-offset' do
|
|
338
|
+
context 'unset' do
|
|
339
|
+
let(:command_opts) { { :start_offset => nil } }
|
|
340
|
+
it 'should not pass any options to STREAM FILE' do
|
|
341
|
+
expect_stream_file_with_options
|
|
342
|
+
subject.execute
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
context 'set' do
|
|
347
|
+
let(:command_opts) { { :start_offset => 10 } }
|
|
348
|
+
it "should return an error and not execute any actions" do
|
|
349
|
+
subject.execute
|
|
350
|
+
error = ProtocolError.new 'option error', 'A start_offset value is unsupported on Asterisk.'
|
|
351
|
+
command.response(0.1).should == error
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
describe 'start-paused' do
|
|
357
|
+
context 'false' do
|
|
358
|
+
let(:command_opts) { { :start_paused => false } }
|
|
359
|
+
it 'should not pass any options to STREAM FILE' do
|
|
360
|
+
expect_stream_file_with_options
|
|
361
|
+
subject.execute
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'true' do
|
|
366
|
+
let(:command_opts) { { :start_paused => true } }
|
|
367
|
+
it "should return an error and not execute any actions" do
|
|
368
|
+
subject.execute
|
|
369
|
+
error = ProtocolError.new 'option error', 'A start_paused value is unsupported on Asterisk.'
|
|
370
|
+
command.response(0.1).should == error
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
describe 'repeat-interval' do
|
|
376
|
+
context 'unset' do
|
|
377
|
+
let(:command_opts) { { :repeat_interval => nil } }
|
|
378
|
+
it 'should not pass any options to STREAM FILE' do
|
|
379
|
+
expect_stream_file_with_options
|
|
380
|
+
subject.execute
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context 'set' do
|
|
385
|
+
let(:command_opts) { { :repeat_interval => 10 } }
|
|
386
|
+
it "should return an error and not execute any actions" do
|
|
387
|
+
subject.execute
|
|
388
|
+
error = ProtocolError.new 'option error', 'A repeat_interval value is unsupported on Asterisk.'
|
|
389
|
+
command.response(0.1).should == error
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
describe 'repeat-times' do
|
|
395
|
+
context 'unset' do
|
|
396
|
+
let(:command_opts) { { :repeat_times => nil } }
|
|
397
|
+
it 'should not pass any options to STREAM FILE' do
|
|
398
|
+
expect_stream_file_with_options
|
|
399
|
+
subject.execute
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
context 'set' do
|
|
404
|
+
let(:command_opts) { { :repeat_times => 2 } }
|
|
405
|
+
it "should return an error and not execute any actions" do
|
|
406
|
+
subject.execute
|
|
407
|
+
error = ProtocolError.new 'option error', 'A repeat_times value is unsupported on Asterisk.'
|
|
408
|
+
command.response(0.1).should == error
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
describe 'max-time' do
|
|
414
|
+
context 'unset' do
|
|
415
|
+
let(:command_opts) { { :max_time => nil } }
|
|
416
|
+
it 'should not pass any options to STREAM FILE' do
|
|
417
|
+
expect_stream_file_with_options
|
|
418
|
+
subject.execute
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
context 'set' do
|
|
423
|
+
let(:command_opts) { { :max_time => 30 } }
|
|
424
|
+
it "should return an error and not execute any actions" do
|
|
425
|
+
subject.execute
|
|
426
|
+
error = ProtocolError.new 'option error', 'A max_time value is unsupported on Asterisk.'
|
|
427
|
+
command.response(0.1).should == error
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
describe 'voice' do
|
|
433
|
+
context 'unset' do
|
|
434
|
+
let(:command_opts) { { :voice => nil } }
|
|
435
|
+
it 'should not pass the v option to STREAM FILE' do
|
|
436
|
+
expect_stream_file_with_options
|
|
437
|
+
subject.execute
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
context 'set' do
|
|
442
|
+
let(:command_opts) { { :voice => 'alison' } }
|
|
443
|
+
it "should return an error and not execute any actions" do
|
|
444
|
+
subject.execute
|
|
445
|
+
error = ProtocolError.new 'option error', 'A voice value is unsupported on Asterisk.'
|
|
446
|
+
command.response(0.1).should == error
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
describe 'interrupt_on' do
|
|
452
|
+
context "set to nil" do
|
|
453
|
+
let(:command_opts) { { :interrupt_on => nil } }
|
|
454
|
+
it "should not pass any digits to STREAM FILE" do
|
|
455
|
+
expect_stream_file_with_options
|
|
456
|
+
subject.execute
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
context "set to :any" do
|
|
461
|
+
let(:command_opts) { { :interrupt_on => :any } }
|
|
462
|
+
it "should pass all digits to STREAM FILE" do
|
|
463
|
+
expect_stream_file_with_options '0123456789*#'
|
|
464
|
+
subject.execute
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
context "set to :dtmf" do
|
|
469
|
+
let(:command_opts) { { :interrupt_on => :dtmf } }
|
|
470
|
+
it "should pass all digits to STREAM FILE" do
|
|
471
|
+
expect_stream_file_with_options '0123456789*#'
|
|
472
|
+
subject.execute
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
context "set to :speech" do
|
|
477
|
+
let(:command_opts) { { :interrupt_on => :speech } }
|
|
478
|
+
it "should return an error and not execute any actions" do
|
|
479
|
+
subject.execute
|
|
480
|
+
error = ProtocolError.new 'option error', 'An interrupt-on value of speech is unsupported.'
|
|
481
|
+
command.response(0.1).should == error
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|