larynx 0.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/MIT-LICENSE +20 -0
- data/README.rdoc +191 -0
- data/Rakefile +55 -0
- data/bin/larynx +7 -0
- data/examples/guess.rb +39 -0
- data/examples/guess_form.rb +34 -0
- data/examples/multiple_apps.rb +63 -0
- data/lib/larynx/application.rb +24 -0
- data/lib/larynx/call_handler.rb +174 -0
- data/lib/larynx/callbacks.rb +32 -0
- data/lib/larynx/command.rb +73 -0
- data/lib/larynx/commands.rb +88 -0
- data/lib/larynx/fields.rb +143 -0
- data/lib/larynx/form.rb +19 -0
- data/lib/larynx/logger.rb +8 -0
- data/lib/larynx/observable.rb +35 -0
- data/lib/larynx/prompt.rb +88 -0
- data/lib/larynx/response.rb +57 -0
- data/lib/larynx/restartable_timer.rb +26 -0
- data/lib/larynx/session.rb +20 -0
- data/lib/larynx/version.rb +3 -0
- data/lib/larynx.rb +109 -0
- data/spec/fixtures/answer.rb +125 -0
- data/spec/fixtures/channel_data.rb +147 -0
- data/spec/fixtures/dtmf.rb +52 -0
- data/spec/fixtures/execute.rb +52 -0
- data/spec/fixtures/execute_complete.rb +133 -0
- data/spec/fixtures/reply_ok.rb +6 -0
- data/spec/larynx/call_handler_spec.rb +290 -0
- data/spec/larynx/command_spec.rb +76 -0
- data/spec/larynx/eventmachince_spec.rb +14 -0
- data/spec/larynx/fields_spec.rb +194 -0
- data/spec/larynx/prompt_spec.rb +222 -0
- data/spec/larynx_spec.rb +4 -0
- data/spec/spec_helper.rb +47 -0
- metadata +96 -0
@@ -0,0 +1,222 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Larynx::Prompt do
|
4
|
+
attr_accessor :call
|
5
|
+
|
6
|
+
before do
|
7
|
+
@call = TestCallHandler.new(1)
|
8
|
+
@call.queue = []
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error if no command value supplied" do
|
12
|
+
lambda { Larynx::Prompt.new(call, {}) }.should raise_exception(Larynx::NoPromptCommandValue)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return correct command name from options" do
|
16
|
+
new_prompt(:speak => 'Hello1').command_name.should == 'speak'
|
17
|
+
new_prompt(:play => 'Hello2').command_name.should == 'play'
|
18
|
+
new_prompt(:phrase => 'Hello3').command_name.should == 'phrase'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return correct message from options" do
|
22
|
+
new_prompt(:speak => 'Hello1').message.should == 'Hello1'
|
23
|
+
new_prompt(:play => 'Hello2').message.should == 'Hello2'
|
24
|
+
new_prompt(:phrase => 'Hello3').message.should == 'Hello3'
|
25
|
+
end
|
26
|
+
|
27
|
+
context "input" do
|
28
|
+
before do
|
29
|
+
@prompt = new_prompt
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return call input as string" do
|
33
|
+
call.input << '1'
|
34
|
+
@prompt.input.should == '1'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return call input without termchar" do
|
38
|
+
call.input += ['1', '#']
|
39
|
+
@prompt.input.should == '1'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "prompt_finished?" do
|
44
|
+
it "should return true if input length reached" do
|
45
|
+
prompt = new_prompt(:speak => 'hello', :length => 1)
|
46
|
+
call.input << '1'
|
47
|
+
prompt.prompt_finished?.should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return false if input length not reached" do
|
51
|
+
prompt = new_prompt(:speak => 'hello', :length => 2)
|
52
|
+
call.input << '1'
|
53
|
+
prompt.prompt_finished?.should be_false
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return true if input has termchar regardless of length" do
|
57
|
+
prompt = new_prompt(:speak => 'hello', :length => 2)
|
58
|
+
call.input << '#'
|
59
|
+
prompt.prompt_finished?.should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return true if input has reached max length" do
|
63
|
+
prompt = new_prompt(:speak => 'hello', :max_length => 2)
|
64
|
+
call.input += ['1', '2']
|
65
|
+
prompt.prompt_finished?.should be_true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "command" do
|
70
|
+
it "should return command object for command name" do
|
71
|
+
cmd = new_prompt.command
|
72
|
+
cmd.should be_kind_of(Larynx::AppCommand)
|
73
|
+
cmd.command.should == 'speak'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "before callback" do
|
78
|
+
it "should clear input on execution" do
|
79
|
+
call.input << '1'
|
80
|
+
before_callback new_prompt
|
81
|
+
call.input.should be_empty
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "after callback" do
|
86
|
+
context "input completed" do
|
87
|
+
it "should not add timers if reached length" do
|
88
|
+
call.input << '1'
|
89
|
+
call.should_not_receive(:timer).with(:digit, anything())
|
90
|
+
call.should_not_receive(:timer).with(:input, anything())
|
91
|
+
after_callback new_prompt
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not add timers if termchar input" do
|
95
|
+
prompt = new_prompt(:speak => 'hello', :length => 2, :termchar => '#')
|
96
|
+
call.input << '#'
|
97
|
+
call.should_not_receive(:timer).with(:digit, anything())
|
98
|
+
call.should_not_receive(:timer).with(:input, anything())
|
99
|
+
after_callback prompt
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should finalise prompt" do
|
103
|
+
call.input << '#'
|
104
|
+
prompt = new_prompt
|
105
|
+
prompt.should_receive(:finalise)
|
106
|
+
after_callback prompt
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "input not completed" do
|
111
|
+
it "should add timers" do
|
112
|
+
call.should_receive(:timer).with(:digit, anything())
|
113
|
+
call.should_receive(:timer).with(:input, anything())
|
114
|
+
after_callback new_prompt
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should add itself as call observer" do
|
118
|
+
prompt = new_prompt
|
119
|
+
call.stub!(:timer)
|
120
|
+
after_callback prompt
|
121
|
+
call.observers.should include(prompt)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should finalise prompt" do
|
125
|
+
prompt = new_prompt(:speak => 'hello', :interdigit_timeout => 0.01) {|input| done }
|
126
|
+
em do
|
127
|
+
after_callback prompt
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "finalize" do
|
134
|
+
it "should run user callback" do
|
135
|
+
prompt = new_prompt {|input| @callback = true }
|
136
|
+
prompt.finalise
|
137
|
+
@callback.should be_true
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should remove prompt as call observer" do
|
141
|
+
prompt = new_prompt
|
142
|
+
call.should_receive(:remove_observer).with(prompt)
|
143
|
+
prompt.finalise
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "user callback" do
|
148
|
+
it "should be passed input argument equal to call input" do
|
149
|
+
prompt = new_prompt {|input| @callback = '1'}
|
150
|
+
call.input << '1'
|
151
|
+
after_callback prompt
|
152
|
+
@callback.should == '1'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "interdigit timeout" do
|
157
|
+
it "should finalize prompt after specified number of seconds" do
|
158
|
+
prompt = new_prompt(:speak => 'hello', :interdigit_timeout => 0.5) {|input| done }
|
159
|
+
start = Time.now
|
160
|
+
em do
|
161
|
+
after_callback prompt
|
162
|
+
end
|
163
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should restart when DTMF received" do
|
167
|
+
prompt = new_prompt(:speak => 'hello', :interdigit_timeout => 1) {|input| done }
|
168
|
+
start = Time.now
|
169
|
+
em do
|
170
|
+
EM.add_timer(0.5) { prompt.dtmf_received('1') }
|
171
|
+
after_callback prompt
|
172
|
+
end
|
173
|
+
(Time.now-start).should be_close(1.5, 0.2)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "timeout" do
|
178
|
+
it "should finalize after number of seconds" do
|
179
|
+
prompt = new_prompt(:speak => 'hello', :length => 5, :interdigit_timeout => 2, :timeout => 0.5) {|input| done }
|
180
|
+
start = Time.now
|
181
|
+
em do
|
182
|
+
after_callback prompt
|
183
|
+
end
|
184
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should finalize after number of seconds even if digits being input" do
|
188
|
+
prompt = new_prompt(:speak => 'hello', :length => 5, :interdigit_timeout => 1, :timeout => 1.5) {|input| done }
|
189
|
+
start = Time.now
|
190
|
+
em do
|
191
|
+
EM.add_periodic_timer(0.5) { prompt.dtmf_received('1') }
|
192
|
+
after_callback prompt
|
193
|
+
end
|
194
|
+
(Time.now-start).should be_close(1.5, 0.2)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "completion during timer" do
|
199
|
+
it "should finalize before time out" do
|
200
|
+
prompt = new_prompt(:speak => 'hello', :length => 1, :interdigit_timeout => 2) {|input| done }
|
201
|
+
start = Time.now
|
202
|
+
em do
|
203
|
+
after_callback prompt
|
204
|
+
EM.add_timer(0.5) { call.input << '1'; prompt.dtmf_received('1') }
|
205
|
+
end
|
206
|
+
(Time.now-start).should be_close(0.5, 0.2)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def new_prompt(options=nil, &block)
|
211
|
+
block = lambda { @callback = true } unless block_given?
|
212
|
+
Larynx::Prompt.new(call, options || {:speak => 'Hello world', :length => 1}, &block)
|
213
|
+
end
|
214
|
+
|
215
|
+
def before_callback(prompt)
|
216
|
+
prompt.command.fire_callback :before
|
217
|
+
end
|
218
|
+
|
219
|
+
def after_callback(prompt)
|
220
|
+
prompt.command.fire_callback :after
|
221
|
+
end
|
222
|
+
end
|
data/spec/larynx_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/lib')
|
2
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/spec')
|
3
|
+
|
4
|
+
TEST = true
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'em-spec/rspec'
|
8
|
+
require 'larynx'
|
9
|
+
|
10
|
+
LARYNX_LOGGER = Logger.new(STDOUT)
|
11
|
+
RESPONSES = {}
|
12
|
+
Dir['spec/fixtures/*.rb'].each {|file| require file }
|
13
|
+
|
14
|
+
class TestCallHandler < Larynx::CallHandler
|
15
|
+
attr_accessor :sent_data, :session, :state, :queue, :input, :timers
|
16
|
+
|
17
|
+
def send_data(msg)
|
18
|
+
@sent_data = msg
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_response(response)
|
22
|
+
request = ::RESPONSES[response]
|
23
|
+
receive_request(request[:header], request[:content])
|
24
|
+
end
|
25
|
+
|
26
|
+
def log(msg)
|
27
|
+
(@log ||= '') << msg
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module SpecHelper
|
32
|
+
def should_be_called(times=1, &block)
|
33
|
+
proc = mock('Proc should be called')
|
34
|
+
proc.should_receive(:call).exactly(times).times.instance_eval(&(block || lambda {}))
|
35
|
+
lambda { |*args| proc.call(*args) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_not_be_called(&block)
|
39
|
+
proc = mock('Proc should not be called')
|
40
|
+
proc.should_not_receive(:call).instance_eval(&(block || lambda {}))
|
41
|
+
lambda { |*args| proc.call(*args) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Spec::Runner.configure do |config|
|
46
|
+
config.include SpecHelper, EM::SpecHelper
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: larynx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Adam Meehan
|
13
|
+
autorequire: larynx
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-25 00:00:00 +11:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: ""
|
22
|
+
email: adam.meehan@gmail.com
|
23
|
+
executables:
|
24
|
+
- larynx
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README.rdoc
|
29
|
+
files:
|
30
|
+
- MIT-LICENSE
|
31
|
+
- README.rdoc
|
32
|
+
- Rakefile
|
33
|
+
- lib/larynx/application.rb
|
34
|
+
- lib/larynx/call_handler.rb
|
35
|
+
- lib/larynx/callbacks.rb
|
36
|
+
- lib/larynx/command.rb
|
37
|
+
- lib/larynx/commands.rb
|
38
|
+
- lib/larynx/fields.rb
|
39
|
+
- lib/larynx/form.rb
|
40
|
+
- lib/larynx/logger.rb
|
41
|
+
- lib/larynx/observable.rb
|
42
|
+
- lib/larynx/prompt.rb
|
43
|
+
- lib/larynx/response.rb
|
44
|
+
- lib/larynx/restartable_timer.rb
|
45
|
+
- lib/larynx/session.rb
|
46
|
+
- lib/larynx/version.rb
|
47
|
+
- lib/larynx.rb
|
48
|
+
- spec/fixtures/answer.rb
|
49
|
+
- spec/fixtures/channel_data.rb
|
50
|
+
- spec/fixtures/dtmf.rb
|
51
|
+
- spec/fixtures/execute.rb
|
52
|
+
- spec/fixtures/execute_complete.rb
|
53
|
+
- spec/fixtures/reply_ok.rb
|
54
|
+
- spec/larynx/call_handler_spec.rb
|
55
|
+
- spec/larynx/command_spec.rb
|
56
|
+
- spec/larynx/eventmachince_spec.rb
|
57
|
+
- spec/larynx/fields_spec.rb
|
58
|
+
- spec/larynx/prompt_spec.rb
|
59
|
+
- spec/larynx_spec.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- examples/guess.rb
|
62
|
+
- examples/guess_form.rb
|
63
|
+
- examples/multiple_apps.rb
|
64
|
+
- bin/larynx
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/adzap/larynx
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: larynx
|
91
|
+
rubygems_version: 1.3.6
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: ""
|
95
|
+
test_files: []
|
96
|
+
|