punchblock 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.document +5 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +31 -0
  7. data/Rakefile +23 -0
  8. data/assets/ozone/ask-1.0.xsd +56 -0
  9. data/assets/ozone/conference-1.0.xsd +17 -0
  10. data/assets/ozone/ozone-1.0.xsd +127 -0
  11. data/assets/ozone/say-1.0.xsd +24 -0
  12. data/assets/ozone/transfer-1.0.xsd +32 -0
  13. data/bin/punchblock-console +125 -0
  14. data/lib/punchblock/command/accept.rb +30 -0
  15. data/lib/punchblock/command/answer.rb +30 -0
  16. data/lib/punchblock/command/dial.rb +88 -0
  17. data/lib/punchblock/command/hangup.rb +25 -0
  18. data/lib/punchblock/command/join.rb +81 -0
  19. data/lib/punchblock/command/mute.rb +7 -0
  20. data/lib/punchblock/command/redirect.rb +49 -0
  21. data/lib/punchblock/command/reject.rb +61 -0
  22. data/lib/punchblock/command/unjoin.rb +50 -0
  23. data/lib/punchblock/command/unmute.rb +7 -0
  24. data/lib/punchblock/command.rb +16 -0
  25. data/lib/punchblock/command_node.rb +46 -0
  26. data/lib/punchblock/component/input.rb +320 -0
  27. data/lib/punchblock/component/output.rb +449 -0
  28. data/lib/punchblock/component/record.rb +216 -0
  29. data/lib/punchblock/component/tropo/ask.rb +197 -0
  30. data/lib/punchblock/component/tropo/conference.rb +328 -0
  31. data/lib/punchblock/component/tropo/say.rb +113 -0
  32. data/lib/punchblock/component/tropo/transfer.rb +178 -0
  33. data/lib/punchblock/component/tropo.rb +12 -0
  34. data/lib/punchblock/component.rb +73 -0
  35. data/lib/punchblock/connection.rb +209 -0
  36. data/lib/punchblock/core_ext/blather/stanza/presence.rb +11 -0
  37. data/lib/punchblock/core_ext/blather/stanza.rb +26 -0
  38. data/lib/punchblock/dsl.rb +46 -0
  39. data/lib/punchblock/event/answered.rb +7 -0
  40. data/lib/punchblock/event/complete.rb +65 -0
  41. data/lib/punchblock/event/dtmf.rb +19 -0
  42. data/lib/punchblock/event/end.rb +15 -0
  43. data/lib/punchblock/event/info.rb +15 -0
  44. data/lib/punchblock/event/joined.rb +50 -0
  45. data/lib/punchblock/event/offer.rb +29 -0
  46. data/lib/punchblock/event/ringing.rb +7 -0
  47. data/lib/punchblock/event/unjoined.rb +50 -0
  48. data/lib/punchblock/event.rb +16 -0
  49. data/lib/punchblock/generic_connection.rb +18 -0
  50. data/lib/punchblock/has_headers.rb +34 -0
  51. data/lib/punchblock/header.rb +47 -0
  52. data/lib/punchblock/media_container.rb +39 -0
  53. data/lib/punchblock/media_node.rb +17 -0
  54. data/lib/punchblock/protocol_error.rb +16 -0
  55. data/lib/punchblock/rayo_node.rb +88 -0
  56. data/lib/punchblock/ref.rb +26 -0
  57. data/lib/punchblock/version.rb +3 -0
  58. data/lib/punchblock.rb +42 -0
  59. data/log/.gitkeep +0 -0
  60. data/punchblock.gemspec +42 -0
  61. data/spec/punchblock/command/accept_spec.rb +13 -0
  62. data/spec/punchblock/command/answer_spec.rb +13 -0
  63. data/spec/punchblock/command/dial_spec.rb +54 -0
  64. data/spec/punchblock/command/hangup_spec.rb +13 -0
  65. data/spec/punchblock/command/join_spec.rb +21 -0
  66. data/spec/punchblock/command/mute_spec.rb +11 -0
  67. data/spec/punchblock/command/redirect_spec.rb +19 -0
  68. data/spec/punchblock/command/reject_spec.rb +43 -0
  69. data/spec/punchblock/command/unjoin_spec.rb +19 -0
  70. data/spec/punchblock/command/unmute_spec.rb +11 -0
  71. data/spec/punchblock/command_node_spec.rb +80 -0
  72. data/spec/punchblock/component/input_spec.rb +188 -0
  73. data/spec/punchblock/component/output_spec.rb +531 -0
  74. data/spec/punchblock/component/record_spec.rb +235 -0
  75. data/spec/punchblock/component/tropo/ask_spec.rb +183 -0
  76. data/spec/punchblock/component/tropo/conference_spec.rb +360 -0
  77. data/spec/punchblock/component/tropo/say_spec.rb +171 -0
  78. data/spec/punchblock/component/tropo/transfer_spec.rb +153 -0
  79. data/spec/punchblock/component_spec.rb +126 -0
  80. data/spec/punchblock/connection_spec.rb +194 -0
  81. data/spec/punchblock/event/answered_spec.rb +23 -0
  82. data/spec/punchblock/event/complete_spec.rb +80 -0
  83. data/spec/punchblock/event/dtmf_spec.rb +24 -0
  84. data/spec/punchblock/event/end_spec.rb +30 -0
  85. data/spec/punchblock/event/info_spec.rb +30 -0
  86. data/spec/punchblock/event/joined_spec.rb +32 -0
  87. data/spec/punchblock/event/offer_spec.rb +35 -0
  88. data/spec/punchblock/event/ringing_spec.rb +23 -0
  89. data/spec/punchblock/event/unjoined_spec.rb +32 -0
  90. data/spec/punchblock/header_spec.rb +44 -0
  91. data/spec/punchblock/protocol_error_spec.rb +9 -0
  92. data/spec/punchblock/ref_spec.rb +21 -0
  93. data/spec/spec_helper.rb +43 -0
  94. metadata +353 -0
@@ -0,0 +1,531 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Component
5
+ describe Output do
6
+ it 'registers itself' do
7
+ RayoNode.class_from_registration(:output, 'urn:xmpp:rayo:output:1').should == Output
8
+ end
9
+
10
+ describe "when setting options in initializer" do
11
+ subject do
12
+ Output.new :interrupt_on => :speech,
13
+ :start_offset => 2000,
14
+ :start_paused => false,
15
+ :repeat_interval => 2000,
16
+ :repeat_times => 10,
17
+ :max_time => 30000,
18
+ :voice => 'allison'
19
+ end
20
+
21
+ its(:interrupt_on) { should == :speech }
22
+ its(:start_offset) { should == 2000 }
23
+ its(:start_paused) { should == false }
24
+ its(:repeat_interval) { should == 2000 }
25
+ its(:repeat_times) { should == 10 }
26
+ its(:max_time) { should == 30000 }
27
+ its(:voice) { should == 'allison' }
28
+ end
29
+
30
+ describe "for text" do
31
+ subject { Output.new :text => 'Once upon a time there was a message...', :voice => 'kate' }
32
+
33
+ its(:voice) { should == 'kate' }
34
+ its(:text) { should == 'Once upon a time there was a message...' }
35
+ end
36
+
37
+ describe "for SSML" do
38
+ subject { Output.new :ssml => '<output-as interpret-as="ordinal">100</output-as>', :voice => 'kate' }
39
+
40
+ its(:voice) { should == 'kate' }
41
+
42
+ its(:ssml) { should == '<output-as interpret-as="ordinal">100</output-as>' }
43
+
44
+ describe "comparison" do
45
+ let(:output2) { Output.new :ssml => '<output-as interpret-as="ordinal">100</output-as>', :voice => 'kate' }
46
+ let(:output3) { Output.new :ssml => '<output-as interpret-as="number">100</output-as>', :voice => 'kate' }
47
+
48
+ it { should == output2 }
49
+ it { should_not == output3 }
50
+ end
51
+ end
52
+
53
+ describe "actions" do
54
+ let(:command) { Output.new :text => 'Once upon a time there was a message...', :voice => 'kate' }
55
+
56
+ before do
57
+ command.component_id = 'abc123'
58
+ command.call_id = '123abc'
59
+ command.connection = Connection.new :username => '123', :password => '123'
60
+ end
61
+
62
+ describe '#pause_action' do
63
+ subject { command.pause_action }
64
+
65
+ its(:to_xml) { should == '<pause xmlns="urn:xmpp:rayo:output:1"/>' }
66
+ its(:component_id) { should == 'abc123' }
67
+ its(:call_id) { should == '123abc' }
68
+ end
69
+
70
+ describe '#pause!' do
71
+ describe "when the command is executing" do
72
+ before do
73
+ command.request!
74
+ command.execute!
75
+ end
76
+
77
+ it "should send its command properly" do
78
+ Connection.any_instance.expects(:write).with('123abc', command.pause_action, 'abc123').returns true
79
+ command.expects :paused!
80
+ command.pause!
81
+ end
82
+ end
83
+
84
+ describe "when the command is not executing" do
85
+ it "should raise an error" do
86
+ lambda { command.pause! }.should raise_error(InvalidActionError, "Cannot pause a Output that is not executing")
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "#paused!" do
92
+ before do
93
+ subject.request!
94
+ subject.execute!
95
+ subject.paused!
96
+ end
97
+
98
+ its(:state_name) { should == :paused }
99
+
100
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
101
+ lambda { subject.paused! }.should raise_error(StateMachine::InvalidTransition)
102
+ end
103
+ end
104
+
105
+ describe '#resume_action' do
106
+ subject { command.resume_action }
107
+
108
+ its(:to_xml) { should == '<resume xmlns="urn:xmpp:rayo:output:1"/>' }
109
+ its(:component_id) { should == 'abc123' }
110
+ its(:call_id) { should == '123abc' }
111
+ end
112
+
113
+ describe '#resume!' do
114
+ describe "when the command is paused" do
115
+ before do
116
+ command.request!
117
+ command.execute!
118
+ command.paused!
119
+ end
120
+
121
+ it "should send its command properly" do
122
+ Connection.any_instance.expects(:write).with('123abc', command.resume_action, 'abc123').returns true
123
+ command.expects :resumed!
124
+ command.resume!
125
+ end
126
+ end
127
+
128
+ describe "when the command is not paused" do
129
+ it "should raise an error" do
130
+ lambda { command.resume! }.should raise_error(InvalidActionError, "Cannot resume a Output that is not paused.")
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#resumed!" do
136
+ before do
137
+ subject.request!
138
+ subject.execute!
139
+ subject.paused!
140
+ subject.resumed!
141
+ end
142
+
143
+ its(:state_name) { should == :executing }
144
+
145
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
146
+ lambda { subject.resumed! }.should raise_error(StateMachine::InvalidTransition)
147
+ end
148
+ end
149
+
150
+ describe '#stop_action' do
151
+ subject { command.stop_action }
152
+
153
+ its(:to_xml) { should == '<stop xmlns="urn:xmpp:rayo:1"/>' }
154
+ its(:component_id) { should == 'abc123' }
155
+ its(:call_id) { should == '123abc' }
156
+ end
157
+
158
+ describe '#stop!' do
159
+ describe "when the command is executing" do
160
+ before do
161
+ command.request!
162
+ command.execute!
163
+ end
164
+
165
+ it "should send its command properly" do
166
+ Connection.any_instance.expects(:write).with('123abc', command.stop_action, 'abc123')
167
+ command.stop!
168
+ end
169
+ end
170
+
171
+ describe "when the command is not executing" do
172
+ it "should raise an error" do
173
+ lambda { command.stop! }.should raise_error(InvalidActionError, "Cannot stop a Output that is not executing")
174
+ end
175
+ end
176
+ end # #stop!
177
+
178
+ describe "seeking" do
179
+ let(:seek_options) { {:direction => :forward, :amount => 1500} }
180
+
181
+ describe '#seek_action' do
182
+ subject { command.seek_action seek_options }
183
+
184
+ its(:to_xml) { should == '<seek xmlns="urn:xmpp:rayo:output:1" direction="forward" amount="1500"/>' }
185
+ its(:component_id) { should == 'abc123' }
186
+ its(:call_id) { should == '123abc' }
187
+ end
188
+
189
+ describe '#seek!' do
190
+ describe "when not seeking" do
191
+ before do
192
+ command.request!
193
+ command.execute!
194
+ end
195
+
196
+ it "should send its command properly" do
197
+ seek_action = command.seek_action seek_options
198
+ command.stubs(:seek_action).returns seek_action
199
+ Connection.any_instance.expects(:write).with('123abc', seek_action, 'abc123').returns true
200
+ command.expects :seeking!
201
+ command.expects :stopped_seeking!
202
+ command.seek! seek_options
203
+ seek_action.request!
204
+ seek_action.execute!
205
+ end
206
+ end
207
+
208
+ describe "when seeking" do
209
+ before { command.seeking! }
210
+
211
+ it "should raise an error" do
212
+ lambda { command.seek! }.should raise_error(InvalidActionError, "Cannot seek an Output that is already seeking.")
213
+ end
214
+ end
215
+ end
216
+
217
+ describe "#seeking!" do
218
+ before do
219
+ subject.request!
220
+ subject.execute!
221
+ subject.seeking!
222
+ end
223
+
224
+ its(:seek_status_name) { should == :seeking }
225
+
226
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
227
+ lambda { subject.seeking! }.should raise_error(StateMachine::InvalidTransition)
228
+ end
229
+ end
230
+
231
+ describe "#stopped_seeking!" do
232
+ before do
233
+ subject.request!
234
+ subject.execute!
235
+ subject.seeking!
236
+ subject.stopped_seeking!
237
+ end
238
+
239
+ its(:seek_status_name) { should == :not_seeking }
240
+
241
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
242
+ lambda { subject.stopped_seeking! }.should raise_error(StateMachine::InvalidTransition)
243
+ end
244
+ end
245
+ end
246
+
247
+ describe "adjusting speed" do
248
+ describe '#speed_up_action' do
249
+ subject { command.speed_up_action }
250
+
251
+ its(:to_xml) { should == '<speed-up xmlns="urn:xmpp:rayo:output:1"/>' }
252
+ its(:component_id) { should == 'abc123' }
253
+ its(:call_id) { should == '123abc' }
254
+ end
255
+
256
+ describe '#speed_up!' do
257
+ describe "when not altering speed" do
258
+ before do
259
+ command.request!
260
+ command.execute!
261
+ end
262
+
263
+ it "should send its command properly" do
264
+ speed_up_action = command.speed_up_action
265
+ command.stubs(:speed_up_action).returns speed_up_action
266
+ Connection.any_instance.expects(:write).with('123abc', speed_up_action, 'abc123').returns true
267
+ command.expects :speeding_up!
268
+ command.expects :stopped_speeding!
269
+ command.speed_up!
270
+ speed_up_action.request!
271
+ speed_up_action.execute!
272
+ end
273
+ end
274
+
275
+ describe "when speeding up" do
276
+ before { command.speeding_up! }
277
+
278
+ it "should raise an error" do
279
+ lambda { command.speed_up! }.should raise_error(InvalidActionError, "Cannot speed up an Output that is already speeding.")
280
+ end
281
+ end
282
+
283
+ describe "when slowing down" do
284
+ before { command.slowing_down! }
285
+
286
+ it "should raise an error" do
287
+ lambda { command.speed_up! }.should raise_error(InvalidActionError, "Cannot speed up an Output that is already speeding.")
288
+ end
289
+ end
290
+ end
291
+
292
+ describe "#speeding_up!" do
293
+ before do
294
+ subject.request!
295
+ subject.execute!
296
+ subject.speeding_up!
297
+ end
298
+
299
+ its(:speed_status_name) { should == :speeding_up }
300
+
301
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
302
+ lambda { subject.speeding_up! }.should raise_error(StateMachine::InvalidTransition)
303
+ end
304
+ end
305
+
306
+ describe '#slow_down_action' do
307
+ subject { command.slow_down_action }
308
+
309
+ its(:to_xml) { should == '<speed-down xmlns="urn:xmpp:rayo:output:1"/>' }
310
+ its(:component_id) { should == 'abc123' }
311
+ its(:call_id) { should == '123abc' }
312
+ end
313
+
314
+ describe '#slow_down!' do
315
+ describe "when not altering speed" do
316
+ before do
317
+ command.request!
318
+ command.execute!
319
+ end
320
+
321
+ it "should send its command properly" do
322
+ slow_down_action = command.slow_down_action
323
+ command.stubs(:slow_down_action).returns slow_down_action
324
+ Connection.any_instance.expects(:write).with('123abc', slow_down_action, 'abc123').returns true
325
+ command.expects :slowing_down!
326
+ command.expects :stopped_speeding!
327
+ command.slow_down!
328
+ slow_down_action.request!
329
+ slow_down_action.execute!
330
+ end
331
+ end
332
+
333
+ describe "when speeding up" do
334
+ before { command.speeding_up! }
335
+
336
+ it "should raise an error" do
337
+ lambda { command.slow_down! }.should raise_error(InvalidActionError, "Cannot slow down an Output that is already speeding.")
338
+ end
339
+ end
340
+
341
+ describe "when slowing down" do
342
+ before { command.slowing_down! }
343
+
344
+ it "should raise an error" do
345
+ lambda { command.slow_down! }.should raise_error(InvalidActionError, "Cannot slow down an Output that is already speeding.")
346
+ end
347
+ end
348
+ end
349
+
350
+ describe "#slowing_down!" do
351
+ before do
352
+ subject.request!
353
+ subject.execute!
354
+ subject.slowing_down!
355
+ end
356
+
357
+ its(:speed_status_name) { should == :slowing_down }
358
+
359
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
360
+ lambda { subject.slowing_down! }.should raise_error(StateMachine::InvalidTransition)
361
+ end
362
+ end
363
+
364
+ describe "#stopped_speeding!" do
365
+ before do
366
+ subject.request!
367
+ subject.execute!
368
+ subject.speeding_up!
369
+ subject.stopped_speeding!
370
+ end
371
+
372
+ its(:speed_status_name) { should == :not_speeding }
373
+
374
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
375
+ lambda { subject.stopped_speeding! }.should raise_error(StateMachine::InvalidTransition)
376
+ end
377
+ end
378
+ end
379
+
380
+ describe "adjusting volume" do
381
+ describe '#volume_up_action' do
382
+ subject { command.volume_up_action }
383
+
384
+ its(:to_xml) { should == '<volume-up xmlns="urn:xmpp:rayo:output:1"/>' }
385
+ its(:component_id) { should == 'abc123' }
386
+ its(:call_id) { should == '123abc' }
387
+ end
388
+
389
+ describe '#volume_up!' do
390
+ describe "when not altering volume" do
391
+ before do
392
+ command.request!
393
+ command.execute!
394
+ end
395
+
396
+ it "should send its command properly" do
397
+ volume_up_action = command.volume_up_action
398
+ command.stubs(:volume_up_action).returns volume_up_action
399
+ Connection.any_instance.expects(:write).with('123abc', volume_up_action, 'abc123').returns true
400
+ command.expects :voluming_up!
401
+ command.expects :stopped_voluming!
402
+ command.volume_up!
403
+ volume_up_action.request!
404
+ volume_up_action.execute!
405
+ end
406
+ end
407
+
408
+ describe "when voluming up" do
409
+ before { command.voluming_up! }
410
+
411
+ it "should raise an error" do
412
+ lambda { command.volume_up! }.should raise_error(InvalidActionError, "Cannot volume up an Output that is already voluming.")
413
+ end
414
+ end
415
+
416
+ describe "when voluming down" do
417
+ before { command.voluming_down! }
418
+
419
+ it "should raise an error" do
420
+ lambda { command.volume_up! }.should raise_error(InvalidActionError, "Cannot volume up an Output that is already voluming.")
421
+ end
422
+ end
423
+ end
424
+
425
+ describe "#voluming_up!" do
426
+ before do
427
+ subject.request!
428
+ subject.execute!
429
+ subject.voluming_up!
430
+ end
431
+
432
+ its(:volume_status_name) { should == :voluming_up }
433
+
434
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
435
+ lambda { subject.voluming_up! }.should raise_error(StateMachine::InvalidTransition)
436
+ end
437
+ end
438
+
439
+ describe '#volume_down_action' do
440
+ subject { command.volume_down_action }
441
+
442
+ its(:to_xml) { should == '<volume-down xmlns="urn:xmpp:rayo:output:1"/>' }
443
+ its(:component_id) { should == 'abc123' }
444
+ its(:call_id) { should == '123abc' }
445
+ end
446
+
447
+ describe '#volume_down!' do
448
+ describe "when not altering volume" do
449
+ before do
450
+ command.request!
451
+ command.execute!
452
+ end
453
+
454
+ it "should send its command properly" do
455
+ volume_down_action = command.volume_down_action
456
+ command.stubs(:volume_down_action).returns volume_down_action
457
+ Connection.any_instance.expects(:write).with('123abc', volume_down_action, 'abc123').returns true
458
+ command.expects :voluming_down!
459
+ command.expects :stopped_voluming!
460
+ command.volume_down!
461
+ volume_down_action.request!
462
+ volume_down_action.execute!
463
+ end
464
+ end
465
+
466
+ describe "when voluming up" do
467
+ before { command.voluming_up! }
468
+
469
+ it "should raise an error" do
470
+ lambda { command.volume_down! }.should raise_error(InvalidActionError, "Cannot volume down an Output that is already voluming.")
471
+ end
472
+ end
473
+
474
+ describe "when voluming down" do
475
+ before { command.voluming_down! }
476
+
477
+ it "should raise an error" do
478
+ lambda { command.volume_down! }.should raise_error(InvalidActionError, "Cannot volume down an Output that is already voluming.")
479
+ end
480
+ end
481
+ end
482
+
483
+ describe "#voluming_down!" do
484
+ before do
485
+ subject.request!
486
+ subject.execute!
487
+ subject.voluming_down!
488
+ end
489
+
490
+ its(:volume_status_name) { should == :voluming_down }
491
+
492
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
493
+ lambda { subject.voluming_down! }.should raise_error(StateMachine::InvalidTransition)
494
+ end
495
+ end
496
+
497
+ describe "#stopped_voluming!" do
498
+ before do
499
+ subject.request!
500
+ subject.execute!
501
+ subject.voluming_up!
502
+ subject.stopped_voluming!
503
+ end
504
+
505
+ its(:volume_status_name) { should == :not_voluming }
506
+
507
+ it "should raise a StateMachine::InvalidTransition when received a second time" do
508
+ lambda { subject.stopped_voluming! }.should raise_error(StateMachine::InvalidTransition)
509
+ end
510
+ end
511
+ end
512
+ end
513
+ end
514
+
515
+ describe Output::Complete::Success do
516
+ let :stanza do
517
+ <<-MESSAGE
518
+ <complete xmlns='urn:xmpp:rayo:ext:1'>
519
+ <success xmlns='urn:xmpp:rayo:output:complete:1' />
520
+ </complete>
521
+ MESSAGE
522
+ end
523
+
524
+ subject { RayoNode.import(parse_stanza(stanza).root).reason }
525
+
526
+ it { should be_instance_of Output::Complete::Success }
527
+
528
+ its(:name) { should == :success }
529
+ end
530
+ end
531
+ end # Punchblock