tropo-webapi-sdk-ruby 15.10.1

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.
@@ -0,0 +1,637 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Tropo" do
4
+
5
+
6
+ response = Tropo::Generator.wait({ :milliseconds => 10, :allowSignals => "exit"})
7
+
8
+ # Ask action tests (and alias Prompt)
9
+ it "should generate a complete 'ask' JSON document" do
10
+ response = Tropo::Generator.ask({ :name => 'foo',
11
+ :bargein => 'true',
12
+ :timeout => 30,
13
+ :require => 'true' })
14
+ JSON.parse(response).should == { "tropo" => [{ "ask" => { "name" => "foo", "bargein" => "true", "timeout" => 30, "require" => "true" } }] }
15
+ end
16
+
17
+ it "should generate an 'ask' JSON document when a block is passed" do
18
+ response = Tropo::Generator.ask({ :name => 'foo',
19
+ :bargein => 'true',
20
+ :timeout => 30,
21
+ :require => 'true' }) do
22
+ say :value => 'Please say your account number'
23
+ choices :value => '[5 DIGITS]'
24
+ end
25
+ JSON.parse(response).should == {"tropo"=>[{"ask"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "bargein"=>"true", "timeout"=>30, "require"=>"true", "choices"=>{"value"=>"[5 DIGITS]"}}}]}
26
+ end
27
+
28
+ # There is currently a feature request to support an on within an ask
29
+ #
30
+ # it "should generate an 'ask' JSON document when a block is passed with an 'on' action" do
31
+ # response = Tropo::Generator.ask({ :name => 'foo',
32
+ # :bargein => 'true',
33
+ # :timeout => 30,
34
+ # :require => 'true' }) do
35
+ # say :value => 'Please say your account number'
36
+ # choices :value => '[5 DIGITS]'
37
+ # on :event => 'success', :next => '/result.json'
38
+ # end
39
+ # JSON.parse(response).should == {"tropo"=>[{"ask"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "bargein"=>"true", "timeout"=>30, "require"=>"true", "on"=>[{"event"=>"success", "next"=>"/result.json"}], "choices"=>{"value"=>"[5 DIGITS]"}}}]}
40
+ # end
41
+
42
+ it "should generate an error if an 'ask' is passed without a 'name' parameter" do
43
+ begin
44
+ response = Tropo::Generator.ask({ :foo => 'bar' })
45
+ rescue => err
46
+ err.to_s.should == "A 'name' must be provided to a 'ask' action"
47
+ end
48
+ end
49
+
50
+ # Prompt
51
+ it "should generate a complete 'prompt' JSON document" do
52
+ response = Tropo::Generator.prompt({ :name => 'foo',
53
+ :bargein => 'true',
54
+ :timeout => 30,
55
+ :require => 'true' })
56
+ JSON.parse(response).should == { "tropo" => [{ "ask" => { "name" => "foo", "bargein" => "true", "timeout" => 30, "require" => "true" } }] }
57
+ end
58
+
59
+ it "should generate an 'prompt' JSON document when a block is passed" do
60
+ response = Tropo::Generator.prompt({ :name => 'foo',
61
+ :bargein => 'true',
62
+ :timeout => 30,
63
+ :require => 'true' }) do
64
+ say :value => 'Please say your account number'
65
+ choices :value => '[5 DIGITS]'
66
+ end
67
+ JSON.parse(response).should == {"tropo"=>[{"ask"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "bargein"=>"true", "timeout"=>30, "require"=>"true", "choices"=>{"value"=>"[5 DIGITS]"}}}]}
68
+ end
69
+
70
+ it "should generate an error if an 'prompt' is passed without a 'name' parameter" do
71
+ begin
72
+ response = Tropo::Generator.prompt({ :foo => 'bar' })
73
+ rescue => err
74
+ err.to_s.should == "A 'name' must be provided to a 'ask' action"
75
+ end
76
+ end
77
+
78
+ # Choices tests
79
+ it "should generate a standard 'choices' JSON document" do
80
+ response = Tropo::Generator.choices({ :value => '[5 DIGITS]' })
81
+ JSON.parse(response).should == { 'tropo' => [{ 'choices' => { 'value' => '[5 DIGITS]' } }] }
82
+ end
83
+
84
+ it "should raise an error if a 'choices' passes an unspported mode" do
85
+ begin
86
+ response = Tropo::Generator.choices({ :value => '[5 DIGITS]', :mode => 'frootloops' })
87
+ rescue => err
88
+ err.to_s.should == "If mode is provided, only 'dtmf', 'speech' or 'any' is supported"
89
+ end
90
+ end
91
+
92
+ it "should generate a standard 'choices' JSON document with a mode" do
93
+ response = Tropo::Generator.choices({ :value => '[5 DIGITS]', :mode => 'dtmf' })
94
+ JSON.parse(response).should == { 'tropo' => [{ 'choices' => { 'value' => '[5 DIGITS]', 'mode' => 'dtmf' } }] }
95
+ end
96
+
97
+ # Conference action tests
98
+ it "should generate a complete 'conference' JSON document" do
99
+ response = Tropo::Generator.conference({ :name => 'foo',
100
+ :id => '1234',
101
+ :mute => false,
102
+ :send_tones => false,
103
+ :exit_tone => '#' })
104
+ JSON.parse(response).should == {"tropo"=>[{"conference"=>{"name"=>"foo", "mute"=>false, "sendTones"=>false, "id"=>"1234", "exitTone"=>"#"}}]}
105
+ end
106
+
107
+ it "should generate a complete 'conference' JSON document when a block is passed" do
108
+ response = Tropo::Generator.conference({ :name => 'foo',
109
+ :id => '1234',
110
+ :mute => false,
111
+ :send_tones => false,
112
+ :exit_tone => '#' }) do
113
+ on(:event => 'join') { say :value => 'Welcome to the conference' }
114
+ on(:event => 'leave') { say :value => 'Someone has left the conference' }
115
+ end
116
+ JSON.parse(response).should == {"tropo"=>[{"conference"=>{"name"=>"foo", "mute"=>false, "id"=>"1234", "exitTone"=>"#", "sendTones"=>false, "on"=>[{"say"=>[{"value"=>"Welcome to the conference"}], "event"=>"join"}, {"say"=>[{"value"=>"Someone has left the conference"}], "event"=>"leave"}]}}]}
117
+ end
118
+
119
+ it "should generate an error if an 'conference' is passed without a 'name' parameter" do
120
+ begin
121
+ response = Tropo::Generator.conference({ :foo => 'bar' })
122
+ rescue => err
123
+ err.to_s.should == "A 'name' must be provided to a 'conference' action"
124
+ end
125
+ end
126
+
127
+ it "should generate an error if an 'conference' is passed without an 'id' parameter" do
128
+ begin
129
+ response = Tropo::Generator.conference({ :name => 'bar' })
130
+ rescue => err
131
+ err.to_s.should == "A 'id' must be provided to a 'conference' action"
132
+ end
133
+ end
134
+
135
+ # Hangup action tests and Disconnect alias
136
+ it "should generate a JSON document with a 'hangup' action" do
137
+ response = Tropo::Generator.hangup
138
+ JSON.parse(response).should == {"tropo"=>[{"hangup"=>nil}]}
139
+ end
140
+
141
+ it "should generate a JSON document with a 'disconnect' action" do
142
+ response = Tropo::Generator.disconnect
143
+ JSON.parse(response).should == {"tropo"=>[{"hangup"=>nil}]}
144
+ end
145
+
146
+ it "should generate a standard 'on' JSON document" do
147
+ response = Tropo::Generator.on({ :event => 'hangup', :next => 'myresource' })
148
+ JSON.parse(response).should == { "tropo" => [{ "on" =>{ "event" => "hangup", "next" => "myresource" } }] }
149
+ end
150
+
151
+ # On tests
152
+ it "should generate a an error of an 'on' document does not pass an event param" do
153
+ begin
154
+ response = Tropo::Generator.on({ :foo => 'bar' })
155
+ rescue => err
156
+ err.to_s.should == "A 'event' must be provided to a 'on' action"
157
+ end
158
+ end
159
+
160
+ it "should generate a an error of an 'on' document does not pass an event param" do
161
+ begin
162
+ response = Tropo::Generator.on({ :event => 'bar' })
163
+ rescue => err
164
+ err.to_s.should == "A 'next' resource must be provided"
165
+ end
166
+ end
167
+
168
+ # Record action tests
169
+ it "should generate a complete 'record' JSON document" do
170
+ response = Tropo::Generator.record({ :name => 'foo',
171
+ :url => 'http://sendme.com/tropo',
172
+ :beep => true,
173
+ :send_tones => false,
174
+ :exit_tone => '#' })
175
+ JSON.parse(response).should == {"tropo"=>[{"record"=>{"name"=>"foo", "beep"=>true, "url"=>"http://sendme.com/tropo", "exitTone"=>"#", "sendTones"=>false}}]}
176
+ end
177
+
178
+ it "should generate a complete 'record' JSON document when a block is passed" do
179
+ response = Tropo::Generator.record({ :name => 'foo',
180
+ :url => 'http://sendme.com/tropo',
181
+ :beep => true,
182
+ :send_tones => false,
183
+ :exit_tone => '#' }) do
184
+ say :value => 'Please say your account number'
185
+ choices :value => '[5 DIGITS]'
186
+ end
187
+ JSON.parse(response).should == {"tropo"=>[{"record"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "beep"=>true, "url"=>"http://sendme.com/tropo", "sendTones"=>false, "exitTone"=>"#", "choices"=>{"value"=>"[5 DIGITS]"}}}]}
188
+ end
189
+
190
+ it "should generate an error if an 'record' is passed without a 'name' parameter" do
191
+ begin
192
+ response = Tropo::Generator.record({ :foo => 'bar' })
193
+ rescue => err
194
+ err.to_s.should == "A 'name' must be provided to a 'record' action"
195
+ end
196
+ end
197
+
198
+ it "should generate an error if an 'record' is passed without an 'url' parameter" do
199
+ begin
200
+ response = Tropo::Generator.record({ :name => 'bar' })
201
+ rescue => err
202
+ err.to_s.should == "A 'url' must be provided to a 'record' action"
203
+ end
204
+ end
205
+
206
+ it "should generate an error if an 'record' is passed without an invalid 'url' parameter" do
207
+ begin
208
+ response = Tropo::Generator.record({ :name => 'bar',
209
+ :url => 'foobar' })
210
+ rescue => err
211
+ err.to_s.should == "The 'url' paramater must be a valid URL"
212
+ end
213
+ end
214
+
215
+ it "should accept a valid email address when a 'record' action is called" do
216
+ response = Tropo::Generator.record({ :name => 'bar',
217
+ :url => 'foo@bar.com' })
218
+ JSON.parse(response).should == JSON.parse("{\"tropo\":[{\"record\":{\"url\":\"foo@bar.com\",\"name\":\"bar\"}}]}")
219
+ end
220
+
221
+ # Redirect action tests
222
+ it "should generate a JSON document with a 'redirect' action" do
223
+ response = Tropo::Generator.redirect({ :to => 'sip:1234', :from => '4155551212' })
224
+ JSON.parse(response).should == {"tropo"=>[{"redirect"=>{"from"=>"4155551212", "to"=>"sip:1234"}}]}
225
+ end
226
+
227
+ it "should generate an error if a 'redirect' action is included in a block" do
228
+ begin
229
+ response = Tropo::Generator.conference(:name => 'foobar', :id => 1234) do
230
+ redirect(:to => 'sip:1234', :from => '4155551212')
231
+ end
232
+ rescue => err
233
+ err.to_s.should == 'Redirect should only be used alone and before the session is answered, use transfer instead'
234
+ end
235
+ end
236
+
237
+ it "should generate an error when no 'to' is passed to a 'redirect' action" do
238
+ begin
239
+ response = Tropo::Generator.redirect
240
+ rescue => err
241
+ err.to_s.should == "A 'to' must be provided to a 'redirect' action"
242
+ end
243
+ end
244
+
245
+ # Reject action tests
246
+ it "should generate a JSON document with a 'reject' action" do
247
+ response = Tropo::Generator.reject
248
+ JSON.parse(response).should == {"tropo"=>[{"reject"=>nil}]}
249
+ end
250
+
251
+ # Say action tests
252
+ it "should generate a standard 'say' JSON document when a stiring is passed" do
253
+ JSON.parse(Tropo::Generator.say('1234')).should == { "tropo" => [{ "say" => [{ "value" => "1234" }] }] }
254
+ end
255
+
256
+ it "should generate an error if I try to pass an integer to a 'say' action" do
257
+ begin
258
+ Tropo::Generator.say(1234)
259
+ rescue => err
260
+ err.to_s.should == "An invalid paramater type Fixnum has been passed"
261
+ end
262
+ end
263
+
264
+ it "should generate a standard 'say' JSON document" do
265
+ JSON.parse(Tropo::Generator.say({ :value => '1234' })).should == { "tropo" => [{ "say" => [{ "value" => "1234" }] }] }
266
+ end
267
+
268
+ it "should generate a 'say' JSON document when an array of values is passed" do
269
+ response = Tropo::Generator.say([{ :value => '1234' }, { :value => 'abcd', :event => 'nomatch:1' }])
270
+ JSON.parse(response).should == { "tropo" => [{ "say" => [{ "value" => "1234" }, { "value" => "abcd", "event"=>"nomatch:1" }] }] }
271
+ end
272
+
273
+ it "should generate an error if no 'value' key is passed to a 'say' request" do
274
+ begin
275
+ response = Tropo::Generator.say({ :name => 'foo' })
276
+ rescue => err
277
+ err.to_s.should == "A 'value' must be provided to a 'say' action"
278
+ end
279
+ end
280
+
281
+ it "should generate a JSON document with a 'say' and an 'on'" do
282
+ result = Tropo::Generator.new do
283
+ say :value => 'blah'
284
+ on :event => 'error', :next => 'error.json'
285
+ end
286
+ JSON.parse(result.response).should == {"tropo"=>[{"say"=>[{"value"=>"blah"}]}, {"on"=>{"event"=>"error", "next"=>"error.json"}}]}
287
+ end
288
+
289
+ # Start & Stop Recording actions tests
290
+ it "should generate a JSON document with a 'start_recording' action" do
291
+ response = Tropo::Generator.start_recording(:url => 'http://postrecording.com/tropo')
292
+ JSON.parse(response).should == {"tropo"=>[{"startRecording"=>{"url"=>"http://postrecording.com/tropo"}}]}
293
+ end
294
+
295
+ it "should generate a JSON document with a 'start_call_recording' action" do
296
+ response = Tropo::Generator.start_call_recording(:url => 'http://postrecording.com/tropo')
297
+ JSON.parse(response).should == {"tropo"=>[{"startRecording"=>{"url"=>"http://postrecording.com/tropo"}}]}
298
+ end
299
+
300
+ it "should generate a JSON document with a 'stopRecording' action" do
301
+ response = Tropo::Generator.stop_call_recording
302
+ JSON.parse(response).should == {"tropo"=>[{"stopRecording"=>nil}]}
303
+ end
304
+
305
+ it "should generate a JSON document with a 'stoprecording' action" do
306
+ response = Tropo::Generator.stop_recording
307
+ JSON.parse(response).should == {"tropo"=>[{"stopRecording"=>nil}]}
308
+ end
309
+
310
+ # Transfer action tests
311
+ it "should generate a JSON document with a 'transfer' action" do
312
+ response = Tropo::Generator.transfer(:to => 'tel:+14157044517')
313
+ JSON.parse(response).should == {"tropo"=>[{"transfer"=>{"to"=>"tel:+14157044517"}}]}
314
+ end
315
+
316
+ # Transfer action tests
317
+ it "should generate a JSON document with a 'transfer' action with an 'on' and 'choices' actions" do
318
+ response = Tropo::Generator.transfer(:to => 'tel:+14157044517') do
319
+ on :event => 'unbounded', :next => '/error.json'
320
+ choices :value => '[5 DIGITS]'
321
+ end
322
+ JSON.parse(response).should == {"tropo"=>[{"transfer"=>{"to"=>"tel:+14157044517", "choices"=>{"value"=>"[5 DIGITS]"}, "on"=>[{"event"=>"unbounded", "next"=>"/error.json"}]}}]}
323
+ end
324
+
325
+ it "should generate an error if no 'to' key is passed to a 'transfer' request" do
326
+ begin
327
+ response = Tropo::Generator.transfer
328
+ rescue => err
329
+ err.to_s.should == "A 'to' must be provided to a 'transfer' action"
330
+ end
331
+ end
332
+
333
+ # General tests
334
+ it "should generate a JSON document when a block is passed" do
335
+ result = Tropo::Generator.new do
336
+ say [{ :value => '1234' }, { :value => 'abcd', :event => "nomatch:1" }]
337
+ say [{ :value => '0987' }, { :value => 'zyxw', :event => "nomatch:2" }]
338
+ end
339
+ JSON.parse(result.response).should == {"tropo"=>[{"say"=>[{"value"=>"1234"}, {"value"=>"abcd", "event"=>"nomatch:1"}]}, {"say"=>[{"value"=>"0987"}, {"value"=>"zyxw", "event"=>"nomatch:2"}]}]}
340
+ end
341
+
342
+ it "should build a Ruby hash object when a session arrives in JSON" do
343
+ json_session = "{\"session\":{\"id\":\"dih06n\",\"accountId\":\"33932\",\"timestamp\":\"2010-01-19T23:18:48.562Z\",\"userType\":\"HUMAN\",\"to\":{\"id\":\"tropomessaging@bot.im\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"},\"from\":{\"id\":\"john_doe@gmail.com\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"}}}"
344
+ hash = Tropo::Generator.parse(json_session)
345
+ hash[:session][:timestamp] == Time.parse('2010-01-19T18:27:46.852-05:00')
346
+ end
347
+
348
+ it "should build a Ruby hash object when a result arrives in JSON" do
349
+ json_result = "{\"result\":{\"sessionId\":\"sessionId\",\"callState\":\"ANSWERED\",\"sessionDuration\":10,\"sequence\":1,\"complete\":true,\"error\":\"error\",\"properties\":[{\"key\":\"foo\",\"value\":\"bar\"},{\"key\":\"charlie\",\"value\":\"foxtrot\"}],\"actions\":{\"name\":\"pin\",\"attempts\":1,\"disposition\":\"SUCCESS\",\"confidence\":100,\"interpretation\":\"12345\",\"utterance\":\"1 2 3 4 5\"}}}"
350
+ Tropo::Generator.parse(json_result).should == Hashie::Mash.new({:result=>{:session_id=>"sessionId", :properties=>{:foo=>{:value=>"bar"}, :charlie=>{:value=>"foxtrot"}}, :complete=>true, :call_state=>"ANSWERED", :actions=>{:pin=>{:disposition=>"SUCCESS", :utterance=>"1 2 3 4 5", :attempts=>1, :interpretation=>"12345", :confidence=>100}}, :session_duration=>10, :error=>"error", :sequence=>1}})
351
+ end
352
+
353
+ it "should build a ruby hash object when a realworld JSON string arrives" do
354
+ json_result = "{\"result\":{\"sessionId\":\"CCFD9C86-1DD1-11B2-B76D-B9B253E4B7FB@161.253.55.20\",\"callState\":\"ANSWERED\",\"sessionDuration\":2,\"sequence\":1,\"complete\":true,\"error\":null,\"actions\":[{\"name\":\"zip\",\"attempts\":1,\"disposition\":\"SUCCESS\",\"confidence\":100,\"interpretation\":\"12345\",\"utterance\":\"1 2 3 4 5\"},{\"name\":\"days\",\"attempts\":1,\"disposition\":\"SUCCESS\",\"confidence\":100,\"interpretation\":\"1\",\"utterance\":\"1\"}]}}"
355
+ Tropo::Generator.parse(json_result).should == Hashie::Mash.new({:result=>{:call_state=>"ANSWERED", :complete=>true, :actions=>{:zip=>{:disposition=>"SUCCESS", :utterance=>"1 2 3 4 5", :attempts=>1, :interpretation=>"12345", :confidence=>100}, :days=>{:disposition=>"SUCCESS", :utterance=>"1", :attempts=>1, :interpretation=>"1", :confidence=>100}}, :session_duration=>2, :sequence=>1, :session_id=>"CCFD9C86-1DD1-11B2-B76D-B9B253E4B7FB@161.253.55.20", :error=>nil}})
356
+ end
357
+
358
+ it "should see an object delcared outside of a block" do
359
+ @@session = 'foobar'
360
+ result = Tropo::Generator.new do
361
+ @@new_session = @@session
362
+ say :value => 'blah'
363
+ on :event => 'error', :next => 'error.json'
364
+ end
365
+ @@new_session.should == 'foobar'
366
+ end
367
+
368
+ it "should allow you to create a Tropo::Generator object and build up a JSON request with two says" do
369
+ tropo = Tropo::Generator.new
370
+ tropo.say('foo')
371
+ tropo.say('bar')
372
+ tropo.response.should == "{\"tropo\":[{\"say\":[{\"value\":\"foo\"}]},{\"say\":[{\"value\":\"bar\"}]}]}"
373
+ end
374
+
375
+ it "should allow you to create a Tropo::Generator object and build up a JSON request with: a say, an on and a record" do
376
+ tropo = Tropo::Generator.new
377
+ tropo.say 'Welcome to the app'
378
+ tropo.on :event => 'hangup', :next => '/hangup.json'
379
+ tropo.record({ :name => 'foo',
380
+ :url => 'http://sendme.com/tropo',
381
+ :beep => true,
382
+ :send_tones => false,
383
+ :exit_tone => '#' }) do
384
+ say :value => 'Please say your account number'
385
+ choices :value => '[5 DIGITS]'
386
+ end
387
+ JSON.parse(tropo.response).should == {"tropo"=>[{"say"=>[{"value"=>"Welcome to the app"}]}, {"on"=>{"event"=>"hangup", "next"=>"/hangup.json"}}, {"record"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "beep"=>true, "url"=>"http://sendme.com/tropo", "sendTones"=>false, "exitTone"=>"#", "choices"=>{"value"=>"[5 DIGITS]"}}}]}
388
+ end
389
+
390
+ it "should allow you to reset the object to a fresh response after building a response first" do
391
+ tropo = Tropo::Generator.new
392
+ tropo.say 'Welcome to the app'
393
+ tropo.on :event => 'hangup', :next => '/hangup.json'
394
+ tropo.record({ :name => 'foo',
395
+ :url => 'http://sendme.com/tropo',
396
+ :beep => true,
397
+ :send_tones => false,
398
+ :exit_tone => '#' }) do
399
+ say :value => 'Please say your account number'
400
+ choices :value => '[5 DIGITS]'
401
+ end
402
+ JSON.parse(tropo.response).should == {"tropo"=>[{"say"=>[{"value"=>"Welcome to the app"}]}, {"on"=>{"event"=>"hangup", "next"=>"/hangup.json"}}, {"record"=>{"name"=>"foo", "say"=>[{"value"=>"Please say your account number"}], "beep"=>true, "url"=>"http://sendme.com/tropo", "sendTones"=>false, "exitTone"=>"#", "choices"=>{"value"=>"[5 DIGITS]"}}}]}
403
+ tropo.reset
404
+ tropo.response.should == "{\"tropo\":[]}"
405
+ end
406
+
407
+ it "should build a Ruby hash object when a session arrives in JSON with a proper Ruby Time object" do
408
+ json_session = "{\"session\":{\"id\":\"dih06n\",\"accountId\":\"33932\",\"timestamp\":\"2010-01-19T23:18:48.562Z\",\"userType\":\"HUMAN\",\"to\":{\"id\":\"tropomessaging@bot.im\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"},\"from\":{\"id\":\"john_doe@gmail.com\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"}}}"
409
+ hash = Tropo::Generator.parse(json_session)
410
+ hash[:session][:timestamp].should == Time.parse("2010-01-19T23:18:48.562Z")
411
+ end
412
+
413
+ it "should build a Ruby hash object when a result arrives in JSON with one action returned in an array" do
414
+ json_result = "{\"result\":{\"sessionId\":\"CCFD9C86-1DD1-11B2-B76D-B9B253E4B7FB@161.253.55.20\",\"callState\":\"ANSWERED\",\"sessionDuration\":2,\"sequence\":1,\"complete\":true,\"error\":null,\"actions\":{\"name\":\"zip\",\"attempts\":1,\"disposition\":\"SUCCESS\",\"confidence\":100,\"interpretation\":\"12345\",\"utterance\":\"1 2 3 4 5\"}}}"
415
+ hash = Tropo::Generator.parse(json_result)
416
+ hash.should == Hashie::Mash.new({:result=>{:call_state=>"ANSWERED", :complete=>true, :actions=>{:zip=>{:utterance=>"1 2 3 4 5", :attempts=>1, :interpretation=>"12345", :confidence=>100, :disposition=>"SUCCESS"}}, :session_id=>"CCFD9C86-1DD1-11B2-B76D-B9B253E4B7FB@161.253.55.20", :session_duration=>2, :error=>nil, :sequence=>1}})
417
+ end
418
+
419
+ it "should build a Hashie object when a result arrives in JSON" do
420
+ json_result = "{\"result\":{\"sessionId\":\"CCFD9C86-1DD1-11B2-B76D-B9B253E4B7FB@161.253.55.20\",\"callState\":\"ANSWERED\",\"sessionDuration\":2,\"sequence\":1,\"complete\":true,\"error\":null,\"actions\":{\"name\":\"zip\",\"attempts\":1,\"disposition\":\"SUCCESS\",\"confidence\":100,\"interpretation\":\"12345\",\"utterance\":\"1 2 3 4 5\"}}}"
421
+ hash = Tropo::Generator.parse(json_result)
422
+ hash.result.call_state.should == 'ANSWERED'
423
+ hash[:result][:call_state].should == 'ANSWERED'
424
+ hash['result']['call_state'].should == 'ANSWERED'
425
+ end
426
+
427
+ it "should generate valid JSON when a startRecording is used" do
428
+ t = Tropo::Generator.new
429
+ t.on :event => 'error', :next => '/error.json' # For fatal programming errors. Log some details so we can fix it
430
+ t.on :event => 'hangup', :next => '/hangup.json' # When a user hangs or call is done. We will want to log some details.
431
+ t.on :event => 'continue', :next => '/next.json'
432
+ t.say "Hello"
433
+ t.start_recording(:url => "http://heroku-voip.marksilver.net/post_audio_to_s3?filename=foo.wav&unique_id=bar")
434
+ # [From this point, until stop_recording(), we will record what the caller *and* the IVR say]
435
+ t.say "You are now on the record."
436
+ # Prompt the user to incriminate themselve on-the-record
437
+ t.say "Go ahead, sing-along."
438
+ t.say "http://denalidomain.com/music/keepers/HappyHappyBirthdaytoYou-Disney.mp3"
439
+ JSON.parse(t.response).should == {"tropo"=>[{"on"=>{"event"=>"error", "next"=>"/error.json"}}, {"on"=>{"event"=>"hangup", "next"=>"/hangup.json"}}, {"on"=>{"event"=>"continue", "next"=>"/next.json"}}, {"say"=>[{"value"=>"Hello"}]}, {"startRecording"=>{"url"=>"http://heroku-voip.marksilver.net/post_audio_to_s3?filename=foo.wav&unique_id=bar"}}, {"say"=>[{"value"=>"You are now on the record."}]}, {"say"=>[{"value"=>"Go ahead, sing-along."}]}, {"say"=>[{"value"=>"http://denalidomain.com/music/keepers/HappyHappyBirthdaytoYou-Disney.mp3"}]}]}
440
+ end
441
+
442
+ it "should generate a voice_session true if a JSON session is received that is a channel of 'VOICE'" do
443
+ tropo = Tropo::Generator.new
444
+ tropo.parse "{\"session\":{\"id\":\"0-13c4-4b563da3-7aecefda-46af-1d10bdd0\",\"accountId\":\"33932\",\"timestamp\":\"2010-01-19T23:18:00.854Z\",\"userType\":\"HUMAN\",\"to\":{\"id\":\"9991427589\",\"name\":\"unknown\",\"channel\":\"VOICE\",\"network\":\"PSTN\"},\"from\":{\"id\":\"jsgoecke\",\"name\":\"unknown\",\"channel\":\"VOICE\",\"network\":\"PSTN\"}}}"
445
+ tropo.voice_session.should == true
446
+ tropo.text_session.should == false
447
+ end
448
+
449
+ it "should generate a text_session true if a JSON session is received that is a channel of 'TEXT'" do
450
+ tropo = Tropo::Generator.new
451
+ tropo.parse "{\"session\":{\"id\":\"dih06n\",\"accountId\":\"33932\",\"timestamp\":\"2010-01-19T23:18:48.562Z\",\"userType\":\"HUMAN\",\"to\":{\"id\":\"tropomessaging@bot.im\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"},\"from\":{\"id\":\"john_doe@gmail.com\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"}}}"
452
+ tropo.voice_session.should == false
453
+ tropo.text_session.should == true
454
+ end
455
+
456
+ it "should generate a valid JSON string for a call method" do
457
+ json_result = "{\"tropo\":[{\"call\":{\"recording\":{\"password\":\"passwd\",\"username\":\"jose\",\"method\":\"POST\",\"url\":\"http://foobar\",\"format\":\"audio/mp3\"},\"timeout\":10,\"network\":\"SMS\",\"channel\":\"TEXT\",\"to\":\"foo\",\"from\":\"bar\",\"headers\":{\"foo\":\"foo\",\"bar\":\"bar\"},\"answerOnMedia\":false}}]}"
458
+ tropo = Tropo::Generator.call({ :to => 'foo',
459
+ :from => 'bar',
460
+ :network => 'SMS',
461
+ :channel => 'TEXT',
462
+ :timeout => 10,
463
+ :answer_on_media => false,
464
+ :headers => { :foo => 'foo', :bar => 'bar' },
465
+ :recording => { :url => 'http://foobar',
466
+ :method => 'POST',
467
+ :format => 'audio/mp3',
468
+ :username => 'jose',
469
+ :password => 'passwd' } })
470
+ JSON.parse(tropo).should == JSON.parse(json_result)
471
+ end
472
+
473
+ it "should generate a valid JSON string for a message method" do
474
+ hash_result = {"tropo"=>[{"message"=>{"say"=>[{"value"=>"Please say your account number"}], "from"=>"bar", "timeout"=>10, "to"=>"foo", "network"=>"SMS", "answerOnMedia"=>false, "channel"=>"TEXT", "recording"=>{"format"=>"audio/mp3", "method"=>"POST", "url"=>"http://foobar", "username"=>"jose", "password"=>"passwd"}, "headers"=>{"foo"=>"foo", "bar"=>"bar"}}}]}
475
+ tropo = Tropo::Generator.message({ :to => 'foo',
476
+ :from => 'bar',
477
+ :network => 'SMS',
478
+ :channel => 'TEXT',
479
+ :timeout => 10,
480
+ :answer_on_media => false,
481
+ :headers => { :foo => 'foo', :bar => 'bar' },
482
+ :recording => { :url => 'http://foobar',
483
+ :method => 'POST',
484
+ :format => 'audio/mp3',
485
+ :username => 'jose',
486
+ :password => 'passwd' } }) do
487
+ say :value => 'Please say your account number'
488
+ end
489
+ JSON.parse(tropo).should == hash_result
490
+ end
491
+
492
+ it "should generate a valid JSON string for a record method with a transcription request" do
493
+ hash_result = {"tropo"=>[{"record"=>{"name"=>"foo", "transcription"=>{"email_format"=>"encoded", "url"=>"mailto:jose@voxeo.com", "id"=>"bling"}, "say"=>[{"value"=>"Please say your account number"}], "beep"=>true, "url"=>"http://sendme.com/tropo", "exitTone"=>"#", "sendTones"=>false, "choices"=>{"value"=>"[5 DIGITS]"}}}]}
494
+ tropo = Tropo::Generator.record({ :name => 'foo',
495
+ :url => 'http://sendme.com/tropo',
496
+ :beep => true,
497
+ :send_tones => false,
498
+ :transcription => { :id => 'bling',
499
+ :url => 'mailto:jose@voxeo.com',
500
+ :email_format => 'encoded' },
501
+ :exit_tone => '#' }) do
502
+ say :value => 'Please say your account number'
503
+ choices :value => '[5 DIGITS]'
504
+ end
505
+ JSON.parse(tropo).should == hash_result
506
+ end
507
+
508
+ it "should properly generate a JSON document when calling an ask with says as hash elements rather than as methods" do
509
+ hash_result = {"tropo"=>[{"ask"=>{"name"=>"donate_to_id", "say"=>[{"event"=>"timeout", "value"=>"Sorry, I did not hear anything."}, {"event"=>"nomatch:1 nomatch:2 nomatch:3", "value"=>"Sorry, that wasn't a valid answer. You can press or say 1 for 'yes', or 2 for 'no'."}, {"value"=>"You chose organization foobar. Are you ready to donate to them? If you say no, I will tell you a little more about the organization."}, {"event"=>"nomatch:3", "value"=>"This is your last attempt."}], "bargein"=>true, "silenceTimeout"=>10, "timeout"=>10, "attempts"=>4, "choices"=>{"value"=>"true(1,yes,sure,affirmative), false(2,no,no thank you,negative), 0(0,help,i do not know, agent, operator, assistance, representative, real person, human), 9(9,quit,stop,shut up)"}}}]}
510
+ help_stop_choices = "0(0,help,i do not know, agent, operator, assistance, representative, real person, human), 9(9,quit,stop,shut up)"
511
+ yes_no_choices = "true(1,yes,sure,affirmative), false(2,no,no thank you,negative), " + help_stop_choices
512
+
513
+ t = Tropo::Generator.new
514
+ t.ask :name => 'donate_to_id',
515
+ :bargein => true,
516
+ :timeout => 10,
517
+ :silence_timeout => 10,
518
+ :attempts => 4,
519
+ :say => [{:event => "timeout", :value => "Sorry, I did not hear anything."},
520
+ {:event => "nomatch:1 nomatch:2 nomatch:3", :value => "Sorry, that wasn't a valid answer. You can press or say 1 for 'yes', or 2 for 'no'."},
521
+ {:value => "You chose organization foobar. Are you ready to donate to them? If you say no, I will tell you a little more about the organization."},
522
+ {:event => "nomatch:3", :value => "This is your last attempt."}],
523
+ :choices => { :value => yes_no_choices}
524
+ JSON.parse(t.response).should == hash_result
525
+ end
526
+
527
+ it "should set the voice variable when called" do
528
+ t = Tropo::Generator.new
529
+ t.voice.should == nil
530
+
531
+ t = Tropo::Generator.new(:voice => 'barnie')
532
+ t.voice.should == 'barnie'
533
+
534
+ t = Tropo::Generator.new
535
+ t.voice = 'barnie'
536
+ t.voice.should == 'barnie'
537
+ end
538
+
539
+ it "should handle the setting of the voice parameter based on defaults" do
540
+ t = Tropo::Generator.new
541
+ t.say 'Hi there!'
542
+ JSON.parse(t.response)['tropo'][0]['say'][0]['voice'].should == nil
543
+
544
+ t = Tropo::Generator.new
545
+ t.say 'Hi there!', :voice => 'barnie'
546
+ JSON.parse(t.response)['tropo'][0]['say'][0]['voice'].should == 'barnie'
547
+
548
+ t = Tropo::Generator.new(:voice => 'barnie')
549
+ t.say 'Hi there!'
550
+ t.say 'Wow!'
551
+ JSON.parse(t.response)['tropo'][0]['say'][0]['voice'].should == 'barnie'
552
+ JSON.parse(t.response)['tropo'][1]['say'][0]['voice'].should == 'barnie'
553
+
554
+ t = Tropo::Generator.new(:voice => 'barnie')
555
+ t.say 'Hi there!'
556
+ t.say 'Wow!', :voice => 'jack'
557
+ JSON.parse(t.response)['tropo'][0]['say'][0]['voice'].should == 'barnie'
558
+ JSON.parse(t.response)['tropo'][1]['say'][0]['voice'].should == 'jack'
559
+
560
+ t = Tropo::Generator.new
561
+ t.voice = 'barnie'
562
+ t.say 'Hi there!'
563
+ t.say 'Wow!', :voice => 'jack'
564
+ JSON.parse(t.response)['tropo'][0]['say'][0]['voice'].should == 'barnie'
565
+ JSON.parse(t.response)['tropo'][1]['say'][0]['voice'].should == 'jack'
566
+ end
567
+
568
+ it "should set the recognizer variable when called" do
569
+ t = Tropo::Generator.new
570
+ t.recognizer.should == nil
571
+
572
+ t = Tropo::Generator.new(:recognizer => 'fr-fr')
573
+ t.recognizer.should == 'fr-fr'
574
+
575
+ t = Tropo::Generator.new
576
+ t.recognizer = 'fr-fr'
577
+ t.recognizer.should == 'fr-fr'
578
+ end
579
+
580
+ it "should handle the setting of the recognizer parameter based on defaults" do
581
+ t = Tropo::Generator.new
582
+ t.ask({ :name => 'foo',
583
+ :bargein => 'true',
584
+ :timeout => 30,
585
+ :require => 'true' })
586
+ JSON.parse(t.response)['tropo'][0]['ask']['recognizer'].should == nil
587
+
588
+ t = Tropo::Generator.new(:recognizer => 'fr-fr')
589
+ t.ask({ :name => 'foo',
590
+ :bargein => 'true',
591
+ :timeout => 30,
592
+ :require => 'true' })
593
+ JSON.parse(t.response)['tropo'][0]['ask']['recognizer'].should == 'fr-fr'
594
+
595
+ t = Tropo::Generator.new
596
+ t.recognizer = 'fr-fr'
597
+ t.ask({ :name => 'foo',
598
+ :bargein => 'true',
599
+ :timeout => 30,
600
+ :require => 'true' })
601
+ JSON.parse(t.response)['tropo'][0]['ask']['recognizer'].should == 'fr-fr'
602
+
603
+ t = Tropo::Generator.new
604
+ t.recognizer = 'fr-fr'
605
+ t.ask({ :name => 'foo',
606
+ :bargein => 'true',
607
+ :timeout => 30,
608
+ :require => 'true' })
609
+ t.ask({ :name => 'foo',
610
+ :bargein => 'true',
611
+ :timeout => 30,
612
+ :require => 'true',
613
+ :recognizer => 'de-de' })
614
+ JSON.parse(t.response)['tropo'][0]['ask']['recognizer'].should == 'fr-fr'
615
+ JSON.parse(t.response)['tropo'][1]['ask']['recognizer'].should == 'de-de'
616
+ end
617
+
618
+ it "should parse a JSON string or a Ruby Hash the same" do
619
+ json_session = "{\"session\":{\"id\":\"dih06n\",\"accountId\":\"33932\",\"timestamp\":\"2010-01-19T23:18:48.562Z\",\"userType\":\"HUMAN\",\"to\":{\"id\":\"tropomessaging@bot.im\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"},\"from\":{\"id\":\"john_doe@gmail.com\",\"name\":\"unknown\",\"channel\":\"TEXT\",\"network\":\"JABBER\"}}}"
620
+ tropo = Tropo::Generator.parse json_session
621
+ tropo.session.user_type.should == 'HUMAN'
622
+
623
+ tropo = Tropo::Generator.parse(JSON.parse(json_session))
624
+ tropo.session.user_type.should == 'HUMAN'
625
+ end
626
+
627
+ it "should return a hash of the response object" do
628
+ result = Tropo::Generator.new do
629
+ say [{ :value => '1234' }, { :value => 'abcd', :event => "nomatch:1" }]
630
+ say [{ :value => '0987' }, { :value => 'zyxw', :event => "nomatch:2" }]
631
+ end
632
+ result.to_hash.should == { :tropo => [{ :say => [{ :value => "1234" },
633
+ { :event => "nomatch:1", :value => "abcd" }] },
634
+ { :say => [{ :value => "0987" },
635
+ { :event => "nomatch:2", :value => "zyxw" }] }] }
636
+ end
637
+ end