adhearsion 2.0.1 → 2.1.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 +4 -3
- data/CHANGELOG.md +30 -0
- data/README.markdown +1 -0
- data/adhearsion.gemspec +3 -4
- data/bin/ahn +0 -20
- data/features/cli_create.feature +1 -1
- data/features/cli_restart.feature +25 -1
- data/features/cli_start.feature +0 -2
- data/features/plugin_generator.feature +66 -15
- data/features/support/env.rb +0 -13
- data/lib/adhearsion.rb +26 -6
- data/lib/adhearsion/call.rb +42 -7
- data/lib/adhearsion/call_controller.rb +5 -2
- data/lib/adhearsion/call_controller/dial.rb +92 -50
- data/lib/adhearsion/call_controller/input.rb +19 -6
- data/lib/adhearsion/call_controller/menu_dsl/menu.rb +4 -0
- data/lib/adhearsion/call_controller/output.rb +143 -161
- data/lib/adhearsion/call_controller/output/abstract_player.rb +30 -0
- data/lib/adhearsion/call_controller/output/async_player.rb +26 -0
- data/lib/adhearsion/call_controller/output/formatter.rb +81 -0
- data/lib/adhearsion/call_controller/output/player.rb +25 -0
- data/lib/adhearsion/call_controller/record.rb +19 -2
- data/lib/adhearsion/events.rb +3 -0
- data/lib/adhearsion/foundation.rb +12 -6
- data/lib/adhearsion/foundation/exception_handler.rb +8 -6
- data/lib/adhearsion/generators/app/templates/README.md +13 -0
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +7 -1
- data/lib/adhearsion/generators/plugin/plugin_generator.rb +1 -0
- data/lib/adhearsion/generators/plugin/templates/plugin-template.gemspec.tt +3 -7
- data/lib/adhearsion/generators/plugin/templates/spec/spec_helper.rb.tt +0 -1
- data/lib/adhearsion/outbound_call.rb +15 -5
- data/lib/adhearsion/punchblock_plugin.rb +13 -2
- data/lib/adhearsion/punchblock_plugin/initializer.rb +13 -12
- data/lib/adhearsion/router.rb +43 -2
- data/lib/adhearsion/router/evented_route.rb +15 -0
- data/lib/adhearsion/router/openended_route.rb +16 -0
- data/lib/adhearsion/router/route.rb +31 -13
- data/lib/adhearsion/router/unaccepting_route.rb +11 -0
- data/lib/adhearsion/version.rb +1 -1
- data/pre-commit +14 -1
- data/spec/adhearsion/call_controller/dial_spec.rb +105 -10
- data/spec/adhearsion/call_controller/input_spec.rb +19 -21
- data/spec/adhearsion/call_controller/output/async_player_spec.rb +67 -0
- data/spec/adhearsion/call_controller/output/formatter_spec.rb +90 -0
- data/spec/adhearsion/call_controller/output/player_spec.rb +65 -0
- data/spec/adhearsion/call_controller/output_spec.rb +436 -190
- data/spec/adhearsion/call_controller/record_spec.rb +49 -6
- data/spec/adhearsion/call_controller_spec.rb +10 -2
- data/spec/adhearsion/call_spec.rb +138 -0
- data/spec/adhearsion/calls_spec.rb +1 -1
- data/spec/adhearsion/outbound_call_spec.rb +48 -8
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +34 -23
- data/spec/adhearsion/router/evented_route_spec.rb +34 -0
- data/spec/adhearsion/router/openended_route_spec.rb +61 -0
- data/spec/adhearsion/router/route_spec.rb +26 -4
- data/spec/adhearsion/router/unaccepting_route_spec.rb +72 -0
- data/spec/adhearsion/router_spec.rb +107 -2
- data/spec/adhearsion_spec.rb +19 -0
- data/spec/capture_warnings.rb +28 -21
- data/spec/spec_helper.rb +2 -3
- data/spec/support/call_controller_test_helpers.rb +31 -30
- metadata +32 -29
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module Output
|
8
|
+
describe Formatter do
|
9
|
+
subject { Formatter }
|
10
|
+
|
11
|
+
describe ".ssml_for" do
|
12
|
+
let(:prompt) { "Please stand by" }
|
13
|
+
|
14
|
+
let(:ssml) do
|
15
|
+
RubySpeech::SSML.draw { string 'Please stand by' }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns SSML for a text argument' do
|
19
|
+
subject.ssml_for(prompt).should be == ssml
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns the same SSML passed in if it is SSML' do
|
23
|
+
subject.ssml_for(ssml).should be == ssml
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".ssml_for_collection" do
|
28
|
+
let(:collection) { ["/foo/bar.wav", 1, Time.now] }
|
29
|
+
let :ssml do
|
30
|
+
file = collection[0]
|
31
|
+
n = collection[1].to_s
|
32
|
+
t = collection[2].to_s
|
33
|
+
RubySpeech::SSML.draw do
|
34
|
+
audio :src => file
|
35
|
+
say_as(:interpret_as => 'cardinal') { n }
|
36
|
+
say_as(:interpret_as => 'time') { t }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should create a composite SSML document" do
|
41
|
+
subject.ssml_for_collection(collection).should be == ssml
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe ".detect_type" do
|
46
|
+
it "detects an HTTP path" do
|
47
|
+
http_path = "http://adhearsion.com/sounds/hello.mp3"
|
48
|
+
subject.detect_type(http_path).should be :audio
|
49
|
+
end
|
50
|
+
|
51
|
+
it "detects a file path" do
|
52
|
+
file_path = "file:///usr/shared/sounds/hello.mp3"
|
53
|
+
subject.detect_type(file_path).should be :audio
|
54
|
+
|
55
|
+
absolute_path = "/usr/shared/sounds/hello.mp3"
|
56
|
+
subject.detect_type(absolute_path).should be :audio
|
57
|
+
|
58
|
+
relative_path = "foo/bar"
|
59
|
+
subject.detect_type(relative_path).should_not be :audio
|
60
|
+
end
|
61
|
+
|
62
|
+
it "detects a Date object" do
|
63
|
+
today = Date.today
|
64
|
+
subject.detect_type(today).should be :time
|
65
|
+
end
|
66
|
+
|
67
|
+
it "detects a Time object" do
|
68
|
+
now = Time.now
|
69
|
+
subject.detect_type(now).should be :time
|
70
|
+
end
|
71
|
+
|
72
|
+
it "detects a DateTime object" do
|
73
|
+
today = DateTime.now
|
74
|
+
subject.detect_type(today).should be :time
|
75
|
+
end
|
76
|
+
|
77
|
+
it "detects a Numeric object" do
|
78
|
+
number = 123
|
79
|
+
subject.detect_type(number).should be :numeric
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns text as a fallback" do
|
83
|
+
output = "Hello"
|
84
|
+
subject.detect_type(output).should be :text
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module Output
|
8
|
+
describe Player do
|
9
|
+
include CallControllerTestHelpers
|
10
|
+
|
11
|
+
let(:controller) { flexmock new_controller }
|
12
|
+
|
13
|
+
subject { Player.new controller }
|
14
|
+
|
15
|
+
describe "#output" do
|
16
|
+
let(:content) { RubySpeech::SSML.draw { string "BOO" } }
|
17
|
+
|
18
|
+
it "should execute an output component with the provided SSML content" do
|
19
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => content)
|
20
|
+
subject.output content
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should allow extra options to be passed to the output component" do
|
24
|
+
component = Punchblock::Component::Output.new :ssml => content, :start_paused => true
|
25
|
+
expect_component_execution component
|
26
|
+
subject.output content, :start_paused => true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "yields the component to the block before executing it" do
|
30
|
+
component = Punchblock::Component::Output.new :ssml => content, :start_paused => true
|
31
|
+
expect_component_execution component
|
32
|
+
subject.output content do |comp|
|
33
|
+
comp.start_paused = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises a PlaybackError if the component fails to start" do
|
38
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => content), Punchblock::ProtocolError
|
39
|
+
lambda { subject.output content }.should raise_error(PlaybackError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises a Playback Error if the component ends due to an error" do
|
43
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => content), Adhearsion::Error
|
44
|
+
lambda { subject.output content }.should raise_error(PlaybackError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "raises a Playback Error if the component ends due to an error" do
|
48
|
+
e = Call::Hangup.new
|
49
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => content), e
|
50
|
+
lambda { subject.output content }.should raise_error(e)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#play_ssml" do
|
55
|
+
let(:ssml) { RubySpeech::SSML.draw { string "BOO" } }
|
56
|
+
|
57
|
+
it 'executes an Output with the correct ssml' do
|
58
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => ssml.to_s)
|
59
|
+
subject.play_ssml ssml
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -7,57 +7,102 @@ module Adhearsion
|
|
7
7
|
describe Output do
|
8
8
|
include CallControllerTestHelpers
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
def expect_ssml_output(ssml)
|
11
|
+
expect_component_execution Punchblock::Component::Output.new(:ssml => ssml)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def expect_async_ssml_output(ssml)
|
15
|
+
expect_message_waiting_for_response Punchblock::Component::Output.new(:ssml => ssml)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#player" do
|
19
|
+
it "should return a Player component targetted at the current controller" do
|
20
|
+
player = controller.player
|
21
|
+
player.should be_a Output::Player
|
22
|
+
player.controller.should be controller
|
16
23
|
end
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
25
|
+
it "should return the same player every time" do
|
26
|
+
controller.player.should be controller.player
|
27
|
+
end
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
30
|
+
describe "#async_player" do
|
31
|
+
it "should return an AsyncPlayer component targetted at the current controller" do
|
32
|
+
player = controller.async_player
|
33
|
+
player.should be_a Output::AsyncPlayer
|
34
|
+
player.controller.should be controller
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return the same player every time" do
|
38
|
+
controller.async_player.should be controller.async_player
|
28
39
|
end
|
29
40
|
end
|
30
41
|
|
31
42
|
describe "#play_audio" do
|
32
|
-
let(:audio_file)
|
33
|
-
let(:fallback) { "text for tts" }
|
43
|
+
let(:audio_file) { "/sounds/boo.wav" }
|
34
44
|
|
35
|
-
let
|
45
|
+
let :ssml do
|
36
46
|
file = audio_file
|
37
47
|
RubySpeech::SSML.draw { audio :src => file }
|
38
48
|
end
|
39
49
|
|
40
|
-
|
50
|
+
it 'plays the correct ssml' do
|
51
|
+
expect_ssml_output ssml
|
52
|
+
subject.play_audio(audio_file).should be true
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with a fallback" do
|
56
|
+
let(:fallback) { "text for tts" }
|
57
|
+
|
58
|
+
let :ssml do
|
59
|
+
file = audio_file
|
60
|
+
fallback_text = fallback
|
61
|
+
RubySpeech::SSML.draw do
|
62
|
+
audio(:src => file) { fallback_text }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'places the fallback in the SSML doc' do
|
67
|
+
expect_ssml_output ssml
|
68
|
+
subject.play_audio(audio_file, :fallback => fallback).should be true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#play_audio!" do
|
74
|
+
let(:audio_file) { "/sounds/boo.wav" }
|
75
|
+
|
76
|
+
let :ssml do
|
41
77
|
file = audio_file
|
42
|
-
|
43
|
-
RubySpeech::SSML.draw {
|
44
|
-
audio(:src => file) { fallback_text }
|
45
|
-
}
|
78
|
+
RubySpeech::SSML.draw { audio :src => file }
|
46
79
|
end
|
47
80
|
|
48
81
|
it 'plays the correct ssml' do
|
49
|
-
|
50
|
-
subject.play_audio(audio_file).should
|
82
|
+
expect_async_ssml_output ssml
|
83
|
+
subject.play_audio!(audio_file).should be_a Punchblock::Component::Output
|
51
84
|
end
|
52
85
|
|
53
|
-
|
54
|
-
|
55
|
-
|
86
|
+
context "with a fallback" do
|
87
|
+
let(:fallback) { "text for tts" }
|
88
|
+
|
89
|
+
let :ssml do
|
90
|
+
file = audio_file
|
91
|
+
fallback_text = fallback
|
92
|
+
RubySpeech::SSML.draw do
|
93
|
+
audio(:src => file) { fallback_text }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'places the fallback in the SSML doc' do
|
98
|
+
expect_async_ssml_output ssml
|
99
|
+
subject.play_audio!(audio_file, :fallback => fallback).should be_a Punchblock::Component::Output
|
100
|
+
end
|
56
101
|
end
|
57
102
|
end
|
58
103
|
|
59
104
|
describe "#play_numeric" do
|
60
|
-
let :
|
105
|
+
let :ssml do
|
61
106
|
RubySpeech::SSML.draw do
|
62
107
|
say_as(:interpret_as => 'cardinal') { "123" }
|
63
108
|
end
|
@@ -67,7 +112,7 @@ module Adhearsion
|
|
67
112
|
let(:input) { 123 }
|
68
113
|
|
69
114
|
it 'plays the correct ssml' do
|
70
|
-
|
115
|
+
expect_ssml_output ssml
|
71
116
|
subject.play_numeric(input).should be true
|
72
117
|
end
|
73
118
|
end
|
@@ -76,7 +121,7 @@ module Adhearsion
|
|
76
121
|
let(:input) { "123" }
|
77
122
|
|
78
123
|
it 'plays the correct ssml' do
|
79
|
-
|
124
|
+
expect_ssml_output ssml
|
80
125
|
subject.play_numeric(input).should be true
|
81
126
|
end
|
82
127
|
end
|
@@ -84,14 +129,48 @@ module Adhearsion
|
|
84
129
|
describe "with something that's not a number" do
|
85
130
|
let(:input) { 'foo' }
|
86
131
|
|
87
|
-
it '
|
88
|
-
subject.play_numeric
|
132
|
+
it 'raises ArgumentError' do
|
133
|
+
lambda { subject.play_numeric input }.should raise_error(ArgumentError)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#play_numeric!" do
|
139
|
+
let :ssml do
|
140
|
+
RubySpeech::SSML.draw do
|
141
|
+
say_as(:interpret_as => 'cardinal') { "123" }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "with a number" do
|
146
|
+
let(:input) { 123 }
|
147
|
+
|
148
|
+
it 'plays the correct ssml' do
|
149
|
+
expect_async_ssml_output ssml
|
150
|
+
subject.play_numeric!(input).should be_a Punchblock::Component::Output
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "with a string representation of a number" do
|
155
|
+
let(:input) { "123" }
|
156
|
+
|
157
|
+
it 'plays the correct ssml' do
|
158
|
+
expect_async_ssml_output ssml
|
159
|
+
subject.play_numeric!(input).should be_a Punchblock::Component::Output
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "with something that's not a number" do
|
164
|
+
let(:input) { 'foo' }
|
165
|
+
|
166
|
+
it 'raises ArgumentError' do
|
167
|
+
lambda { subject.play_numeric! input }.should raise_error(ArgumentError)
|
89
168
|
end
|
90
169
|
end
|
91
170
|
end
|
92
171
|
|
93
172
|
describe "#play_time" do
|
94
|
-
let :
|
173
|
+
let :ssml do
|
95
174
|
content = input.to_s
|
96
175
|
opts = expected_say_as_options
|
97
176
|
RubySpeech::SSML.draw do
|
@@ -104,7 +183,7 @@ module Adhearsion
|
|
104
183
|
let(:expected_say_as_options) { {:interpret_as => 'time'} }
|
105
184
|
|
106
185
|
it 'plays the correct SSML' do
|
107
|
-
|
186
|
+
expect_ssml_output ssml
|
108
187
|
subject.play_time(input).should be true
|
109
188
|
end
|
110
189
|
end
|
@@ -114,7 +193,7 @@ module Adhearsion
|
|
114
193
|
let(:expected_say_as_options) { {:interpret_as => 'date'} }
|
115
194
|
|
116
195
|
it 'plays the correct SSML' do
|
117
|
-
|
196
|
+
expect_ssml_output ssml
|
118
197
|
subject.play_time(input).should be true
|
119
198
|
end
|
120
199
|
end
|
@@ -125,7 +204,7 @@ module Adhearsion
|
|
125
204
|
let(:expected_say_as_options) { {:interpret_as => 'date', :format => format} }
|
126
205
|
|
127
206
|
it 'plays the correct SSML' do
|
128
|
-
|
207
|
+
expect_ssml_output ssml
|
129
208
|
subject.play_time(input, :format => format).should be true
|
130
209
|
end
|
131
210
|
end
|
@@ -137,7 +216,7 @@ module Adhearsion
|
|
137
216
|
let(:expected_say_as_options) { {:interpret_as => 'date'} }
|
138
217
|
|
139
218
|
it 'plays the correct SSML' do
|
140
|
-
|
219
|
+
expect_ssml_output ssml
|
141
220
|
subject.play_time(base_input, :strftime => strftime).should be true
|
142
221
|
end
|
143
222
|
end
|
@@ -150,7 +229,7 @@ module Adhearsion
|
|
150
229
|
let(:expected_say_as_options) { {:interpret_as => 'date', :format => format} }
|
151
230
|
|
152
231
|
it 'plays the correct SSML' do
|
153
|
-
|
232
|
+
expect_ssml_output ssml
|
154
233
|
subject.play_time(base_input, :format => format, :strftime => strftime).should be true
|
155
234
|
end
|
156
235
|
end
|
@@ -158,87 +237,198 @@ module Adhearsion
|
|
158
237
|
describe "with an object other than Time, DateTime, or Date" do
|
159
238
|
let(:input) { "foo" }
|
160
239
|
|
161
|
-
it '
|
162
|
-
subject.play_time
|
240
|
+
it 'raises ArgumentError' do
|
241
|
+
lambda { subject.play_time input }.should raise_error(ArgumentError)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "#play_time!" do
|
247
|
+
let :ssml do
|
248
|
+
content = input.to_s
|
249
|
+
opts = expected_say_as_options
|
250
|
+
RubySpeech::SSML.draw do
|
251
|
+
say_as(opts) { content }
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "with a time" do
|
256
|
+
let(:input) { Time.parse("12/5/2000") }
|
257
|
+
let(:expected_say_as_options) { {:interpret_as => 'time'} }
|
258
|
+
|
259
|
+
it 'plays the correct SSML' do
|
260
|
+
expect_async_ssml_output ssml
|
261
|
+
subject.play_time!(input).should be_a Punchblock::Component::Output
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "with a date" do
|
266
|
+
let(:input) { Date.parse('2011-01-23') }
|
267
|
+
let(:expected_say_as_options) { {:interpret_as => 'date'} }
|
268
|
+
|
269
|
+
it 'plays the correct SSML' do
|
270
|
+
expect_async_ssml_output ssml
|
271
|
+
subject.play_time!(input).should be_a Punchblock::Component::Output
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "with a date and a say_as format" do
|
276
|
+
let(:input) { Date.parse('2011-01-23') }
|
277
|
+
let(:format) { "d-m-y" }
|
278
|
+
let(:expected_say_as_options) { {:interpret_as => 'date', :format => format} }
|
279
|
+
|
280
|
+
it 'plays the correct SSML' do
|
281
|
+
expect_async_ssml_output ssml
|
282
|
+
subject.play_time!(input, :format => format).should be_a Punchblock::Component::Output
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe "with a date and a strftime option" do
|
287
|
+
let(:strftime) { "%d-%m-%Y" }
|
288
|
+
let(:base_input) { Date.parse('2011-01-23') }
|
289
|
+
let(:input) { base_input.strftime(strftime) }
|
290
|
+
let(:expected_say_as_options) { {:interpret_as => 'date'} }
|
291
|
+
|
292
|
+
it 'plays the correct SSML' do
|
293
|
+
expect_async_ssml_output ssml
|
294
|
+
subject.play_time!(base_input, :strftime => strftime).should be_a Punchblock::Component::Output
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "with a date, a format option and a strftime option" do
|
299
|
+
let(:strftime) { "%d-%m-%Y" }
|
300
|
+
let(:format) { "d-m-y" }
|
301
|
+
let(:base_input) { Date.parse('2011-01-23') }
|
302
|
+
let(:input) { base_input.strftime(strftime) }
|
303
|
+
let(:expected_say_as_options) { {:interpret_as => 'date', :format => format} }
|
304
|
+
|
305
|
+
it 'plays the correct SSML' do
|
306
|
+
expect_async_ssml_output ssml
|
307
|
+
subject.play_time!(base_input, :format => format, :strftime => strftime).should be_a Punchblock::Component::Output
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "with an object other than Time, DateTime, or Date" do
|
312
|
+
let(:input) { "foo" }
|
313
|
+
|
314
|
+
it 'raises ArgumentError' do
|
315
|
+
lambda { subject.play_time! input }.should raise_error(ArgumentError)
|
163
316
|
end
|
164
317
|
end
|
165
318
|
end
|
166
319
|
|
167
320
|
describe '#play' do
|
168
321
|
describe "with a single string" do
|
169
|
-
let(:
|
322
|
+
let(:audio_file) { "/foo/bar.wav" }
|
323
|
+
let :ssml do
|
324
|
+
file = audio_file
|
325
|
+
RubySpeech::SSML.draw { audio :src => file }
|
326
|
+
end
|
170
327
|
|
171
328
|
it 'plays the audio file' do
|
172
|
-
|
173
|
-
subject.play(
|
329
|
+
expect_ssml_output ssml
|
330
|
+
subject.play(audio_file).should be true
|
174
331
|
end
|
175
332
|
end
|
176
333
|
|
177
|
-
describe "with multiple
|
178
|
-
let(:args) { [
|
179
|
-
|
180
|
-
|
181
|
-
args.
|
182
|
-
|
334
|
+
describe "with multiple arguments" do
|
335
|
+
let(:args) { ["/foo/bar.wav", 1, Time.now] }
|
336
|
+
let :ssml do
|
337
|
+
file = args[0]
|
338
|
+
n = args[1].to_s
|
339
|
+
t = args[2].to_s
|
340
|
+
RubySpeech::SSML.draw do
|
341
|
+
audio :src => file
|
342
|
+
say_as(:interpret_as => 'cardinal') { n }
|
343
|
+
say_as(:interpret_as => 'time') { t }
|
183
344
|
end
|
345
|
+
end
|
184
346
|
|
347
|
+
it 'plays all arguments in one document' do
|
348
|
+
expect_ssml_output ssml
|
185
349
|
subject.play(*args).should be true
|
186
350
|
end
|
351
|
+
end
|
187
352
|
|
188
|
-
|
189
|
-
|
190
|
-
pending
|
191
|
-
subject.should_receive(:play_audio).with(args[0]).and_return(true).ordered
|
192
|
-
subject.should_receive(:play_audio).with(args[1]).and_return(false).ordered
|
193
|
-
subject.should_receive(:play_audio).with(args[2]).and_return(true).ordered
|
194
|
-
end
|
353
|
+
describe "with a number" do
|
354
|
+
let(:argument) { 123 }
|
195
355
|
|
196
|
-
|
197
|
-
|
356
|
+
let(:ssml) do
|
357
|
+
number = argument.to_s
|
358
|
+
RubySpeech::SSML.draw do
|
359
|
+
say_as(:interpret_as => 'cardinal') { number }
|
198
360
|
end
|
199
361
|
end
|
200
|
-
end
|
201
362
|
|
202
|
-
describe "with a number" do
|
203
363
|
it 'plays the number' do
|
204
|
-
|
205
|
-
subject.play(
|
364
|
+
expect_ssml_output ssml
|
365
|
+
subject.play(argument).should be true
|
206
366
|
end
|
207
367
|
end
|
208
368
|
|
209
369
|
describe "with a string representation of a number" do
|
370
|
+
let(:argument) { '123' }
|
371
|
+
|
372
|
+
let(:ssml) do
|
373
|
+
number = argument
|
374
|
+
RubySpeech::SSML.draw do
|
375
|
+
say_as(:interpret_as => 'cardinal') { number }
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
210
379
|
it 'plays the number' do
|
211
|
-
|
212
|
-
subject.play(
|
380
|
+
expect_ssml_output ssml
|
381
|
+
subject.play(argument).should be true
|
213
382
|
end
|
214
383
|
end
|
215
384
|
|
216
385
|
describe "with a time" do
|
217
|
-
let(:time) { Time.parse
|
386
|
+
let(:time) { Time.parse "12/5/2000" }
|
387
|
+
|
388
|
+
let(:ssml) do
|
389
|
+
t = time.to_s
|
390
|
+
RubySpeech::SSML.draw do
|
391
|
+
say_as(:interpret_as => 'time') { t }
|
392
|
+
end
|
393
|
+
end
|
218
394
|
|
219
395
|
it 'plays the time' do
|
220
|
-
|
396
|
+
expect_ssml_output ssml
|
221
397
|
subject.play(time).should be true
|
222
398
|
end
|
223
399
|
end
|
224
400
|
|
225
401
|
describe "with a date" do
|
226
|
-
let(:date) { Date.parse
|
402
|
+
let(:date) { Date.parse '2011-01-23' }
|
403
|
+
let(:ssml) do
|
404
|
+
d = date.to_s
|
405
|
+
RubySpeech::SSML.draw do
|
406
|
+
say_as(:interpret_as => 'date') { d }
|
407
|
+
end
|
408
|
+
end
|
227
409
|
|
228
410
|
it 'plays the time' do
|
229
|
-
|
411
|
+
expect_ssml_output ssml
|
230
412
|
subject.play(date).should be true
|
231
413
|
end
|
232
414
|
end
|
233
415
|
|
234
416
|
describe "with an array containing a Date/DateTime/Time object and a hash" do
|
235
|
-
let(:date) { Date.parse
|
417
|
+
let(:date) { Date.parse '2011-01-23' }
|
236
418
|
let(:format) { "d-m-y" }
|
237
419
|
let(:strftime) { "%d-%m%Y" }
|
238
420
|
|
421
|
+
let :ssml do
|
422
|
+
d = date.strftime strftime
|
423
|
+
f = format
|
424
|
+
RubySpeech::SSML.draw do
|
425
|
+
say_as(:interpret_as => 'date', :format => f) { d }
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
239
429
|
it 'plays the time with the specified format and strftime' do
|
240
|
-
|
241
|
-
subject.play(
|
430
|
+
expect_ssml_output ssml
|
431
|
+
subject.play(:value => date, :format => format, :strftime => strftime).should be true
|
242
432
|
end
|
243
433
|
end
|
244
434
|
|
@@ -246,125 +436,157 @@ module Adhearsion
|
|
246
436
|
let(:ssml) { RubySpeech::SSML.draw { string "Hello world" } }
|
247
437
|
|
248
438
|
it "plays the SSML without generating" do
|
249
|
-
|
439
|
+
expect_ssml_output ssml
|
250
440
|
subject.play(ssml).should be true
|
251
441
|
end
|
252
442
|
end
|
253
443
|
end
|
254
444
|
|
255
|
-
describe
|
256
|
-
|
257
|
-
|
258
|
-
|
445
|
+
describe '#play!' do
|
446
|
+
describe "with a single string" do
|
447
|
+
let(:audio_file) { "/foo/bar.wav" }
|
448
|
+
let :ssml do
|
449
|
+
file = audio_file
|
450
|
+
RubySpeech::SSML.draw { audio :src => file }
|
451
|
+
end
|
259
452
|
|
260
|
-
|
261
|
-
|
262
|
-
|
453
|
+
it 'plays the audio file' do
|
454
|
+
expect_async_ssml_output ssml
|
455
|
+
subject.play!(audio_file).should be_a Punchblock::Component::Output
|
456
|
+
end
|
263
457
|
end
|
264
458
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
459
|
+
describe "with multiple arguments" do
|
460
|
+
let(:args) { ["/foo/bar.wav", 1, Time.now] }
|
461
|
+
let :ssml do
|
462
|
+
file = args[0]
|
463
|
+
n = args[1].to_s
|
464
|
+
t = args[2].to_s
|
465
|
+
RubySpeech::SSML.draw do
|
466
|
+
audio :src => file
|
467
|
+
say_as(:interpret_as => 'cardinal') { n }
|
468
|
+
say_as(:interpret_as => 'time') { t }
|
469
|
+
end
|
470
|
+
end
|
269
471
|
|
270
|
-
|
271
|
-
|
272
|
-
|
472
|
+
it 'plays all arguments in one document' do
|
473
|
+
expect_async_ssml_output ssml
|
474
|
+
subject.play!(*args).should be_a Punchblock::Component::Output
|
475
|
+
end
|
273
476
|
end
|
274
|
-
end
|
275
477
|
|
276
|
-
|
277
|
-
|
278
|
-
subject.method(:speak).should be == subject.method(:say)
|
279
|
-
end
|
280
|
-
end
|
478
|
+
describe "with a number" do
|
479
|
+
let(:argument) { 123 }
|
281
480
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
subject.say(ssml).should be_a Punchblock::Component::Output
|
481
|
+
let(:ssml) do
|
482
|
+
number = argument.to_s
|
483
|
+
RubySpeech::SSML.draw do
|
484
|
+
say_as(:interpret_as => 'cardinal') { number }
|
485
|
+
end
|
288
486
|
end
|
289
|
-
end
|
290
487
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
ssml = RubySpeech::SSML.draw { string str }
|
295
|
-
expect_component_execution Punchblock::Component::Output.new(:ssml => ssml)
|
296
|
-
subject.say(str).should be_a Punchblock::Component::Output
|
488
|
+
it 'plays the number' do
|
489
|
+
expect_async_ssml_output ssml
|
490
|
+
subject.play!(argument).should be_a Punchblock::Component::Output
|
297
491
|
end
|
298
492
|
end
|
299
493
|
|
300
|
-
describe "
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
494
|
+
describe "with a string representation of a number" do
|
495
|
+
let(:argument) { '123' }
|
496
|
+
|
497
|
+
let(:ssml) do
|
498
|
+
number = argument
|
499
|
+
RubySpeech::SSML.draw do
|
500
|
+
say_as(:interpret_as => 'cardinal') { number }
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
it 'plays the number' do
|
505
|
+
expect_async_ssml_output ssml
|
506
|
+
subject.play!(argument).should be_a Punchblock::Component::Output
|
306
507
|
end
|
307
508
|
end
|
308
|
-
end
|
309
509
|
|
310
|
-
|
311
|
-
|
510
|
+
describe "with a time" do
|
511
|
+
let(:time) { Time.parse "12/5/2000" }
|
312
512
|
|
313
|
-
|
314
|
-
|
315
|
-
|
513
|
+
let(:ssml) do
|
514
|
+
t = time.to_s
|
515
|
+
RubySpeech::SSML.draw do
|
516
|
+
say_as(:interpret_as => 'time') { t }
|
517
|
+
end
|
316
518
|
end
|
317
|
-
end
|
318
519
|
|
319
|
-
|
320
|
-
|
520
|
+
it 'plays the time' do
|
521
|
+
expect_async_ssml_output ssml
|
522
|
+
subject.play!(time).should be_a Punchblock::Component::Output
|
523
|
+
end
|
321
524
|
end
|
322
525
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
526
|
+
describe "with a date" do
|
527
|
+
let(:date) { Date.parse '2011-01-23' }
|
528
|
+
let(:ssml) do
|
529
|
+
d = date.to_s
|
530
|
+
RubySpeech::SSML.draw do
|
531
|
+
say_as(:interpret_as => 'date') { d }
|
532
|
+
end
|
533
|
+
end
|
327
534
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
535
|
+
it 'plays the time' do
|
536
|
+
expect_async_ssml_output ssml
|
537
|
+
subject.play!(date).should be_a Punchblock::Component::Output
|
538
|
+
end
|
332
539
|
end
|
333
540
|
|
334
|
-
|
335
|
-
|
336
|
-
|
541
|
+
describe "with an array containing a Date/DateTime/Time object and a hash" do
|
542
|
+
let(:date) { Date.parse '2011-01-23' }
|
543
|
+
let(:format) { "d-m-y" }
|
544
|
+
let(:strftime) { "%d-%m%Y" }
|
337
545
|
|
338
|
-
|
339
|
-
|
546
|
+
let :ssml do
|
547
|
+
d = date.strftime strftime
|
548
|
+
f = format
|
549
|
+
RubySpeech::SSML.draw do
|
550
|
+
say_as(:interpret_as => 'date', :format => f) { d }
|
551
|
+
end
|
552
|
+
end
|
340
553
|
|
341
|
-
|
342
|
-
|
554
|
+
it 'plays the time with the specified format and strftime' do
|
555
|
+
expect_async_ssml_output ssml
|
556
|
+
subject.play!(:value => date, :format => format, :strftime => strftime).should be_a Punchblock::Component::Output
|
557
|
+
end
|
343
558
|
end
|
344
559
|
|
345
|
-
|
346
|
-
|
347
|
-
subject.detect_type(today).should be :time
|
348
|
-
end
|
560
|
+
describe "with an SSML document" do
|
561
|
+
let(:ssml) { RubySpeech::SSML.draw { string "Hello world" } }
|
349
562
|
|
350
|
-
|
351
|
-
|
352
|
-
|
563
|
+
it "plays the SSML without generating" do
|
564
|
+
expect_async_ssml_output ssml
|
565
|
+
subject.play!(ssml).should be_a Punchblock::Component::Output
|
566
|
+
end
|
353
567
|
end
|
568
|
+
end
|
569
|
+
|
570
|
+
describe "#interruptible_play" do
|
571
|
+
let(:output1) { "one two" }
|
572
|
+
let(:output2) { "three four" }
|
573
|
+
let(:non_existing) { "http://adhearsion.com/nonexistingfile.mp3" }
|
354
574
|
|
355
|
-
it "
|
356
|
-
|
357
|
-
subject.
|
575
|
+
it "plays two outputs in succession" do
|
576
|
+
subject.should_receive(:stream_file).twice
|
577
|
+
digit = subject.interruptible_play output1, output2
|
578
|
+
digit.should be_nil
|
358
579
|
end
|
359
580
|
|
360
|
-
it "
|
361
|
-
|
362
|
-
subject.
|
581
|
+
it "stops at the first play when input is received" do
|
582
|
+
subject.should_receive(:stream_file).once.and_return(2)
|
583
|
+
digit = subject.interruptible_play output1, output2
|
584
|
+
digit.should be == 2
|
363
585
|
end
|
364
586
|
|
365
|
-
it
|
366
|
-
|
367
|
-
subject.
|
587
|
+
it 'raises an exception when output is unsuccessful' do
|
588
|
+
subject.should_receive(:stream_file).once.and_raise Output::PlaybackError, "Output failed"
|
589
|
+
expect { subject.interruptible_play non_existing }.to raise_error(Output::PlaybackError)
|
368
590
|
end
|
369
591
|
end
|
370
592
|
|
@@ -372,21 +594,21 @@ module Adhearsion
|
|
372
594
|
let(:allowed_digits) { '35' }
|
373
595
|
let(:prompt) { "Press 3 or 5 to make something happen." }
|
374
596
|
|
375
|
-
let(:ssml)
|
597
|
+
let(:ssml) do
|
376
598
|
RubySpeech::SSML.draw do
|
377
599
|
string "Press 3 or 5 to make something happen."
|
378
600
|
end
|
379
|
-
|
601
|
+
end
|
380
602
|
|
381
|
-
let(:grammar)
|
382
|
-
|
603
|
+
let(:grammar) do
|
604
|
+
RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'acceptdigits' do
|
383
605
|
rule id: 'acceptdigits' do
|
384
606
|
one_of do
|
385
607
|
allowed_digits.each { |d| item { d.to_s } }
|
386
608
|
end
|
387
609
|
end
|
388
610
|
end
|
389
|
-
|
611
|
+
end
|
390
612
|
|
391
613
|
let(:output_component) {
|
392
614
|
Punchblock::Component::Output.new :ssml => ssml.to_s
|
@@ -399,7 +621,7 @@ module Adhearsion
|
|
399
621
|
|
400
622
|
#test does pass and method works, but not sure if the empty method is a good idea
|
401
623
|
it "plays the correct output" do
|
402
|
-
def
|
624
|
+
def controller.write_and_await_response(input_component)
|
403
625
|
# it is actually a no-op here
|
404
626
|
end
|
405
627
|
|
@@ -420,7 +642,7 @@ module Adhearsion
|
|
420
642
|
it "returns a single digit amongst the allowed when pressed" do
|
421
643
|
flexmock(Punchblock::Event::Complete).new_instances.should_receive(:reason => flexmock(:interpretation => 'dtmf-5', :name => :input))
|
422
644
|
|
423
|
-
def
|
645
|
+
def controller.write_and_await_response(input_component)
|
424
646
|
input_component.trigger_event_handler Punchblock::Event::Complete.new
|
425
647
|
end
|
426
648
|
|
@@ -435,54 +657,78 @@ module Adhearsion
|
|
435
657
|
|
436
658
|
expect_component_complete_event
|
437
659
|
flexmock(Punchblock::Component::Output).new_instances.should_receive(:stop!)
|
438
|
-
|
660
|
+
expect_component_execution output_component
|
439
661
|
subject.stream_file(prompt, allowed_digits).should be == '5'
|
440
662
|
end
|
441
|
-
end
|
442
|
-
|
443
|
-
|
444
|
-
describe "#interruptible_play!" do
|
445
|
-
let(:output1) { "one two" }
|
446
|
-
let(:output2) { "three four" }
|
447
|
-
let(:non_existing) { "http://adhearsion.com/nonexistingfile.mp3" }
|
663
|
+
end
|
448
664
|
|
449
|
-
|
450
|
-
|
451
|
-
|
665
|
+
describe "#say" do
|
666
|
+
describe "with a RubySpeech document" do
|
667
|
+
it 'plays the correct SSML' do
|
668
|
+
ssml = RubySpeech::SSML.draw { string "Hello world" }
|
669
|
+
expect_ssml_output ssml
|
670
|
+
subject.say(ssml).should be_a Punchblock::Component::Output
|
671
|
+
end
|
452
672
|
end
|
453
673
|
|
454
|
-
|
455
|
-
|
456
|
-
|
674
|
+
describe "with a string" do
|
675
|
+
it 'outputs the correct text' do
|
676
|
+
str = "Hello world"
|
677
|
+
ssml = RubySpeech::SSML.draw { string str }
|
678
|
+
expect_ssml_output ssml
|
679
|
+
subject.say(str).should be_a Punchblock::Component::Output
|
680
|
+
end
|
457
681
|
end
|
458
682
|
|
459
|
-
|
460
|
-
|
461
|
-
|
683
|
+
describe "converts the argument to a string" do
|
684
|
+
it 'calls output with a string' do
|
685
|
+
argument = 123
|
686
|
+
ssml = RubySpeech::SSML.draw { string '123' }
|
687
|
+
expect_ssml_output ssml
|
688
|
+
subject.say(argument).should be_a Punchblock::Component::Output
|
689
|
+
end
|
462
690
|
end
|
463
|
-
end
|
691
|
+
end
|
464
692
|
|
465
|
-
describe "#
|
466
|
-
|
467
|
-
|
468
|
-
|
693
|
+
describe "#speak" do
|
694
|
+
it "should be an alias for #say" do
|
695
|
+
subject.method(:speak).should be == subject.method(:say)
|
696
|
+
end
|
697
|
+
end
|
469
698
|
|
470
|
-
|
471
|
-
|
472
|
-
|
699
|
+
describe "#say!" do
|
700
|
+
describe "with a RubySpeech document" do
|
701
|
+
it 'plays the correct SSML' do
|
702
|
+
ssml = RubySpeech::SSML.draw { string "Hello world" }
|
703
|
+
expect_async_ssml_output ssml
|
704
|
+
subject.say!(ssml).should be_a Punchblock::Component::Output
|
705
|
+
end
|
473
706
|
end
|
474
707
|
|
475
|
-
|
476
|
-
|
477
|
-
|
708
|
+
describe "with a string" do
|
709
|
+
it 'outputs the correct text' do
|
710
|
+
str = "Hello world"
|
711
|
+
ssml = RubySpeech::SSML.draw { string str }
|
712
|
+
expect_async_ssml_output ssml
|
713
|
+
subject.say!(str).should be_a Punchblock::Component::Output
|
714
|
+
end
|
478
715
|
end
|
479
716
|
|
480
|
-
|
481
|
-
|
482
|
-
|
717
|
+
describe "converts the argument to a string" do
|
718
|
+
it 'calls output with a string' do
|
719
|
+
argument = 123
|
720
|
+
ssml = RubySpeech::SSML.draw { string '123' }
|
721
|
+
expect_async_ssml_output ssml
|
722
|
+
subject.say!(argument).should be_a Punchblock::Component::Output
|
723
|
+
end
|
483
724
|
end
|
484
|
-
end
|
725
|
+
end
|
485
726
|
|
727
|
+
describe "#speak!" do
|
728
|
+
it "should be an alias for #say!" do
|
729
|
+
subject.method(:speak!).should be == subject.method(:say!)
|
730
|
+
end
|
731
|
+
end
|
486
732
|
end
|
487
733
|
end
|
488
734
|
end
|