punchblock 1.8.2 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/lib/punchblock/component/asterisk/agi/command.rb +0 -11
- data/lib/punchblock/connection/asterisk.rb +3 -3
- data/lib/punchblock/translator/asterisk/agi_command.rb +40 -0
- data/lib/punchblock/translator/asterisk/call.rb +56 -47
- data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +13 -37
- data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +24 -41
- data/lib/punchblock/translator/asterisk/component/input.rb +2 -1
- data/lib/punchblock/translator/asterisk/component/output.rb +16 -21
- data/lib/punchblock/translator/asterisk/component/record.rb +11 -19
- data/lib/punchblock/translator/asterisk/component.rb +12 -9
- data/lib/punchblock/translator/asterisk.rb +16 -22
- data/lib/punchblock/translator/dtmf_recognizer.rb +4 -4
- data/lib/punchblock/translator/freeswitch/component/input.rb +2 -1
- data/lib/punchblock/translator/input_component.rb +2 -2
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +1 -1
- data/spec/punchblock/connection/asterisk_spec.rb +8 -7
- data/spec/punchblock/translator/asterisk/call_spec.rb +262 -229
- data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +57 -29
- data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +40 -46
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +7 -7
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +84 -53
- data/spec/punchblock/translator/asterisk/component/record_spec.rb +55 -83
- data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +5 -1
- data/spec/punchblock/translator/asterisk/component_spec.rb +2 -10
- data/spec/punchblock/translator/asterisk_spec.rb +73 -100
- metadata +5 -10
|
@@ -7,7 +7,9 @@ module Punchblock
|
|
|
7
7
|
class Asterisk
|
|
8
8
|
describe Call do
|
|
9
9
|
let(:channel) { 'SIP/foo' }
|
|
10
|
-
let(:
|
|
10
|
+
let(:ami_client) { stub('AMI Client').as_null_object }
|
|
11
|
+
let(:connection) { stub('connection').as_null_object }
|
|
12
|
+
let(:translator) { Asterisk.new ami_client, connection }
|
|
11
13
|
let(:agi_env) do
|
|
12
14
|
{
|
|
13
15
|
:agi_request => 'async',
|
|
@@ -58,7 +60,7 @@ module Punchblock
|
|
|
58
60
|
}
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
subject { Call.new channel, translator, agi_env }
|
|
63
|
+
subject { Call.new channel, translator, ami_client, connection, agi_env }
|
|
62
64
|
|
|
63
65
|
its(:id) { should be_a String }
|
|
64
66
|
its(:channel) { should be == channel }
|
|
@@ -84,6 +86,22 @@ module Punchblock
|
|
|
84
86
|
end
|
|
85
87
|
end
|
|
86
88
|
|
|
89
|
+
describe "getting channel vars" do
|
|
90
|
+
it "should do a GetVar when we don't have a cached value" do
|
|
91
|
+
response = RubyAMI::Response.new 'Value' => 'thevalue'
|
|
92
|
+
ami_client.should_receive(:send_action).once.with('GetVar', 'Channel' => channel, 'Variable' => 'somevariable').and_return response
|
|
93
|
+
subject.channel_var('somevariable').should == 'thevalue'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "when the value comes back from GetVar as '(null)'" do
|
|
97
|
+
it "should return nil" do
|
|
98
|
+
response = RubyAMI::Response.new 'Value' => '(null)'
|
|
99
|
+
ami_client.should_receive(:send_action).once.with('GetVar', 'Channel' => channel, 'Variable' => 'somevariable').and_return response
|
|
100
|
+
subject.channel_var('somevariable').should be_nil
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
87
105
|
describe '#send_offer' do
|
|
88
106
|
it 'sends an offer to the translator' do
|
|
89
107
|
expected_offer = Punchblock::Event::Offer.new :target_call_id => subject.id,
|
|
@@ -103,11 +121,10 @@ module Punchblock
|
|
|
103
121
|
end
|
|
104
122
|
|
|
105
123
|
describe '#send_progress' do
|
|
106
|
-
|
|
107
124
|
context "with a call that is already answered" do
|
|
108
125
|
it 'should not send the EXEC Progress command' do
|
|
109
126
|
subject.wrapped_object.should_receive(:'answered?').and_return true
|
|
110
|
-
subject.wrapped_object.should_receive(:
|
|
127
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").never
|
|
111
128
|
subject.send_progress
|
|
112
129
|
end
|
|
113
130
|
end
|
|
@@ -126,7 +143,7 @@ module Punchblock
|
|
|
126
143
|
end
|
|
127
144
|
|
|
128
145
|
it 'should not send the EXEC Progress command' do
|
|
129
|
-
subject.wrapped_object.should_receive(:
|
|
146
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").never
|
|
130
147
|
subject.send_progress
|
|
131
148
|
end
|
|
132
149
|
end
|
|
@@ -137,12 +154,12 @@ module Punchblock
|
|
|
137
154
|
end
|
|
138
155
|
|
|
139
156
|
it 'should send the EXEC Progress command to a call that is inbound and not answered' do
|
|
140
|
-
subject.wrapped_object.should_receive(:
|
|
157
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").and_return code: 200, result: 0
|
|
141
158
|
subject.send_progress
|
|
142
159
|
end
|
|
143
160
|
|
|
144
161
|
it 'should send the EXEC Progress command only once if called twice' do
|
|
145
|
-
subject.wrapped_object.should_receive(:
|
|
162
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").once.and_return code: 200, result: 0
|
|
146
163
|
subject.send_progress
|
|
147
164
|
subject.send_progress
|
|
148
165
|
end
|
|
@@ -255,7 +272,7 @@ module Punchblock
|
|
|
255
272
|
subject.dial dial_command
|
|
256
273
|
accept_command = Command::Accept.new
|
|
257
274
|
accept_command.request!
|
|
258
|
-
subject.wrapped_object.should_receive(:
|
|
275
|
+
subject.wrapped_object.should_receive(:execute_agi_command).never
|
|
259
276
|
subject.execute_command accept_command
|
|
260
277
|
accept_command.response(0.5).should be true
|
|
261
278
|
end
|
|
@@ -264,14 +281,13 @@ module Punchblock
|
|
|
264
281
|
describe '#process_ami_event' do
|
|
265
282
|
context 'with a Hangup event' do
|
|
266
283
|
let :ami_event do
|
|
267
|
-
RubyAMI::Event.new
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
end
|
|
284
|
+
RubyAMI::Event.new 'Hangup',
|
|
285
|
+
'Uniqueid' => "1320842458.8",
|
|
286
|
+
'Calleridnum' => "5678",
|
|
287
|
+
'Calleridname' => "Jane Smith",
|
|
288
|
+
'Cause' => cause,
|
|
289
|
+
'Cause-txt' => cause_txt,
|
|
290
|
+
'Channel' => "SIP/1234-00000000"
|
|
275
291
|
end
|
|
276
292
|
|
|
277
293
|
let(:cause) { '16' }
|
|
@@ -291,6 +307,7 @@ module Punchblock
|
|
|
291
307
|
end
|
|
292
308
|
|
|
293
309
|
it "should cause all components to send complete events before sending end event" do
|
|
310
|
+
subject.stub :send_progress
|
|
294
311
|
comp_command = Punchblock::Component::Input.new :grammar => {:value => '<grammar/>'}, :mode => :dtmf
|
|
295
312
|
comp_command.request!
|
|
296
313
|
component = subject.execute_command comp_command
|
|
@@ -305,6 +322,7 @@ module Punchblock
|
|
|
305
322
|
end
|
|
306
323
|
|
|
307
324
|
it "should not allow commands to be executed while components are shutting down" do
|
|
325
|
+
subject.stub :send_progress
|
|
308
326
|
comp_command = Punchblock::Component::Input.new :grammar => {:value => '<grammar/>'}, :mode => :dtmf
|
|
309
327
|
comp_command.request!
|
|
310
328
|
component = subject.execute_command comp_command
|
|
@@ -449,13 +467,12 @@ module Punchblock
|
|
|
449
467
|
end
|
|
450
468
|
|
|
451
469
|
let(:ami_event) do
|
|
452
|
-
RubyAMI::Event.new
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
end
|
|
470
|
+
RubyAMI::Event.new "AsyncAGI",
|
|
471
|
+
"SubEvent" => "End",
|
|
472
|
+
"Channel" => "SIP/1234-00000000",
|
|
473
|
+
"CommandID" => component.id,
|
|
474
|
+
"Command" => "EXEC ANSWER",
|
|
475
|
+
"Result" => "200%20result=123%20(timeout)%0A"
|
|
459
476
|
end
|
|
460
477
|
|
|
461
478
|
before do
|
|
@@ -470,17 +487,16 @@ module Punchblock
|
|
|
470
487
|
|
|
471
488
|
context 'with a Newstate event' do
|
|
472
489
|
let :ami_event do
|
|
473
|
-
RubyAMI::Event.new
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
end
|
|
490
|
+
RubyAMI::Event.new 'Newstate',
|
|
491
|
+
'Privilege' => 'call,all',
|
|
492
|
+
'Channel' => 'SIP/1234-00000000',
|
|
493
|
+
'ChannelState' => channel_state,
|
|
494
|
+
'ChannelStateDesc' => channel_state_desc,
|
|
495
|
+
'CallerIDNum' => '',
|
|
496
|
+
'CallerIDName' => '',
|
|
497
|
+
'ConnectedLineNum' => '',
|
|
498
|
+
'ConnectedLineName' => '',
|
|
499
|
+
'Uniqueid' => '1326194671.0'
|
|
484
500
|
end
|
|
485
501
|
|
|
486
502
|
context 'ringing' do
|
|
@@ -520,18 +536,17 @@ module Punchblock
|
|
|
520
536
|
|
|
521
537
|
context 'with an OriginateResponse event' do
|
|
522
538
|
let :ami_event do
|
|
523
|
-
RubyAMI::Event.new
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
end
|
|
539
|
+
RubyAMI::Event.new 'OriginateResponse',
|
|
540
|
+
'Privilege' => 'call,all',
|
|
541
|
+
'ActionID' => '9d0c1aa4-5e3b-4cae-8aef-76a6119e2909',
|
|
542
|
+
'Response' => response,
|
|
543
|
+
'Channel' => 'SIP/15557654321',
|
|
544
|
+
'Context' => '',
|
|
545
|
+
'Exten' => '',
|
|
546
|
+
'Reason' => '0',
|
|
547
|
+
'Uniqueid' => uniqueid,
|
|
548
|
+
'CallerIDNum' => 'sip:5551234567',
|
|
549
|
+
'CallerIDName' => 'Bryan 100'
|
|
535
550
|
end
|
|
536
551
|
|
|
537
552
|
context 'sucessful' do
|
|
@@ -569,13 +584,12 @@ module Punchblock
|
|
|
569
584
|
|
|
570
585
|
context 'with a handler registered for a matching event' do
|
|
571
586
|
let :ami_event do
|
|
572
|
-
RubyAMI::Event.new
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
end
|
|
587
|
+
RubyAMI::Event.new 'DTMF',
|
|
588
|
+
'Digit' => '4',
|
|
589
|
+
'Start' => 'Yes',
|
|
590
|
+
'End' => 'No',
|
|
591
|
+
'Uniqueid' => "1320842458.8",
|
|
592
|
+
'Channel' => "SIP/1234-00000000"
|
|
579
593
|
end
|
|
580
594
|
|
|
581
595
|
let(:response) { mock 'Response' }
|
|
@@ -591,19 +605,18 @@ module Punchblock
|
|
|
591
605
|
|
|
592
606
|
context 'with a BridgeExec event' do
|
|
593
607
|
let :ami_event do
|
|
594
|
-
RubyAMI::Event.new
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
end
|
|
608
|
+
RubyAMI::Event.new 'BridgeExec',
|
|
609
|
+
'Privilege' => "call,all",
|
|
610
|
+
'Response' => "Success",
|
|
611
|
+
'Channel1' => "SIP/foo",
|
|
612
|
+
'Channel2' => other_channel
|
|
600
613
|
end
|
|
601
614
|
|
|
602
615
|
let(:other_channel) { 'SIP/5678-00000000' }
|
|
603
616
|
|
|
604
617
|
context "when a join has been executed against another call" do
|
|
605
618
|
let :other_call do
|
|
606
|
-
Call.new other_channel, translator
|
|
619
|
+
Call.new other_channel, translator, ami_client, connection
|
|
607
620
|
end
|
|
608
621
|
|
|
609
622
|
let(:other_call_id) { other_call.id }
|
|
@@ -614,6 +627,7 @@ module Punchblock
|
|
|
614
627
|
before do
|
|
615
628
|
translator.register_call other_call
|
|
616
629
|
command.request!
|
|
630
|
+
subject.wrapped_object.should_receive(:execute_agi_command).and_return code: 200
|
|
617
631
|
subject.execute_command command
|
|
618
632
|
end
|
|
619
633
|
|
|
@@ -624,12 +638,11 @@ module Punchblock
|
|
|
624
638
|
|
|
625
639
|
context "with the channel names reversed" do
|
|
626
640
|
let :ami_event do
|
|
627
|
-
RubyAMI::Event.new
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
end
|
|
641
|
+
RubyAMI::Event.new 'BridgeExec',
|
|
642
|
+
'Privilege' => "call,all",
|
|
643
|
+
'Response' => "Success",
|
|
644
|
+
'Channel1' => other_channel,
|
|
645
|
+
'Channel2' => "SIP/foo"
|
|
633
646
|
end
|
|
634
647
|
|
|
635
648
|
it 'retrieves and sets success on the correct Join' do
|
|
@@ -650,35 +663,33 @@ module Punchblock
|
|
|
650
663
|
let(:other_channel) { 'SIP/5678-00000000' }
|
|
651
664
|
let(:other_call_id) { 'def567' }
|
|
652
665
|
let :other_call do
|
|
653
|
-
Call.new other_channel, translator
|
|
666
|
+
Call.new other_channel, translator, ami_client, connection
|
|
654
667
|
end
|
|
655
668
|
|
|
656
669
|
let :ami_event do
|
|
657
|
-
RubyAMI::Event.new
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
end
|
|
670
|
+
RubyAMI::Event.new 'Bridge',
|
|
671
|
+
'Privilege' => "call,all",
|
|
672
|
+
'Bridgestate' => state,
|
|
673
|
+
'Bridgetype' => "core",
|
|
674
|
+
'Channel1' => channel,
|
|
675
|
+
'Channel2' => other_channel,
|
|
676
|
+
'Uniqueid1' => "1319717537.11",
|
|
677
|
+
'Uniqueid2' => "1319717537.10",
|
|
678
|
+
'CallerID1' => "1234",
|
|
679
|
+
'CallerID2' => "5678"
|
|
668
680
|
end
|
|
669
681
|
|
|
670
682
|
let :switched_ami_event do
|
|
671
|
-
RubyAMI::Event.new
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
end
|
|
683
|
+
RubyAMI::Event.new 'Bridge',
|
|
684
|
+
'Privilege' => "call,all",
|
|
685
|
+
'Bridgestate' => state,
|
|
686
|
+
'Bridgetype' => "core",
|
|
687
|
+
'Channel1' => other_channel,
|
|
688
|
+
'Channel2' => channel,
|
|
689
|
+
'Uniqueid1' => "1319717537.11",
|
|
690
|
+
'Uniqueid2' => "1319717537.10",
|
|
691
|
+
'CallerID1' => "1234",
|
|
692
|
+
'CallerID2' => "5678"
|
|
682
693
|
end
|
|
683
694
|
|
|
684
695
|
before do
|
|
@@ -734,31 +745,29 @@ module Punchblock
|
|
|
734
745
|
let(:other_channel) { 'SIP/5678-00000000' }
|
|
735
746
|
let(:other_call_id) { 'def567' }
|
|
736
747
|
let :other_call do
|
|
737
|
-
Call.new other_channel, translator
|
|
748
|
+
Call.new other_channel, translator, ami_client, connection
|
|
738
749
|
end
|
|
739
750
|
|
|
740
751
|
let :ami_event do
|
|
741
|
-
RubyAMI::Event.new
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
end
|
|
752
|
+
RubyAMI::Event.new 'Unlink',
|
|
753
|
+
'Privilege' => "call,all",
|
|
754
|
+
'Channel1' => channel,
|
|
755
|
+
'Channel2' => other_channel,
|
|
756
|
+
'Uniqueid1' => "1319717537.11",
|
|
757
|
+
'Uniqueid2' => "1319717537.10",
|
|
758
|
+
'CallerID1' => "1234",
|
|
759
|
+
'CallerID2' => "5678"
|
|
750
760
|
end
|
|
751
761
|
|
|
752
762
|
let :switched_ami_event do
|
|
753
|
-
RubyAMI::Event.new
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
end
|
|
763
|
+
RubyAMI::Event.new 'Unlink',
|
|
764
|
+
'Privilege' => "call,all",
|
|
765
|
+
'Channel1' => other_channel,
|
|
766
|
+
'Channel2' => channel,
|
|
767
|
+
'Uniqueid1' => "1319717537.11",
|
|
768
|
+
'Uniqueid2' => "1319717537.10",
|
|
769
|
+
'CallerID1' => "1234",
|
|
770
|
+
'CallerID2' => "5678"
|
|
762
771
|
end
|
|
763
772
|
|
|
764
773
|
before do
|
|
@@ -785,17 +794,32 @@ module Punchblock
|
|
|
785
794
|
end
|
|
786
795
|
end
|
|
787
796
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
797
|
+
context 'with a VarSet event' do
|
|
798
|
+
let :ami_event do
|
|
799
|
+
RubyAMI::Event.new 'VarSet',
|
|
800
|
+
"Privilege" => "dialplan,all",
|
|
801
|
+
"Channel" => "SIP/1234-00000000",
|
|
802
|
+
"Variable" => "foobar",
|
|
803
|
+
"Value" => 'abc123',
|
|
804
|
+
"Uniqueid" => "1326210224.0"
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
it 'makes the variable accessible on the call' do
|
|
808
|
+
subject.process_ami_event ami_event
|
|
809
|
+
subject.channel_var('foobar').should == 'abc123'
|
|
796
810
|
end
|
|
797
811
|
end
|
|
798
812
|
|
|
813
|
+
let :ami_event do
|
|
814
|
+
RubyAMI::Event.new 'Foo',
|
|
815
|
+
'Uniqueid' => "1320842458.8",
|
|
816
|
+
'Calleridnum' => "5678",
|
|
817
|
+
'Calleridname' => "Jane Smith",
|
|
818
|
+
'Cause' => "0",
|
|
819
|
+
'Cause-txt' => "Unknown",
|
|
820
|
+
'Channel' => channel
|
|
821
|
+
end
|
|
822
|
+
|
|
799
823
|
let :expected_pb_event do
|
|
800
824
|
Event::Asterisk::AMI::Event.new :name => 'Foo',
|
|
801
825
|
:attributes => { :channel => channel,
|
|
@@ -815,14 +839,6 @@ module Punchblock
|
|
|
815
839
|
end
|
|
816
840
|
|
|
817
841
|
describe '#execute_command' do
|
|
818
|
-
let :expected_agi_complete_event do
|
|
819
|
-
Punchblock::Event::Complete.new.tap do |c|
|
|
820
|
-
c.reason = Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new :code => 200,
|
|
821
|
-
:result => 'Success',
|
|
822
|
-
:data => 'FOO'
|
|
823
|
-
end
|
|
824
|
-
end
|
|
825
|
-
|
|
826
842
|
before do
|
|
827
843
|
command.request!
|
|
828
844
|
end
|
|
@@ -831,11 +847,8 @@ module Punchblock
|
|
|
831
847
|
let(:command) { Command::Accept.new }
|
|
832
848
|
|
|
833
849
|
it "should send an EXEC RINGING AGI command and set the command's response" do
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
837
|
-
agi_command.name.should be == "EXEC RINGING"
|
|
838
|
-
agi_command.add_event expected_agi_complete_event
|
|
850
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC RINGING').and_return code: 200
|
|
851
|
+
subject.execute_command command
|
|
839
852
|
command.response(0.5).should be true
|
|
840
853
|
end
|
|
841
854
|
end
|
|
@@ -845,31 +858,22 @@ module Punchblock
|
|
|
845
858
|
|
|
846
859
|
it "with a :busy reason should send an EXEC Busy AGI command and set the command's response" do
|
|
847
860
|
command.reason = :busy
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
851
|
-
agi_command.name.should be == "EXEC Busy"
|
|
852
|
-
agi_command.add_event expected_agi_complete_event
|
|
861
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Busy').and_return code: 200
|
|
862
|
+
subject.execute_command command
|
|
853
863
|
command.response(0.5).should be true
|
|
854
864
|
end
|
|
855
865
|
|
|
856
866
|
it "with a :decline reason should send an EXEC Busy AGI command and set the command's response" do
|
|
857
867
|
command.reason = :decline
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
861
|
-
agi_command.name.should be == "EXEC Busy"
|
|
862
|
-
agi_command.add_event expected_agi_complete_event
|
|
868
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Busy').and_return code: 200
|
|
869
|
+
subject.execute_command command
|
|
863
870
|
command.response(0.5).should be true
|
|
864
871
|
end
|
|
865
872
|
|
|
866
873
|
it "with an :error reason should send an EXEC Congestion AGI command and set the command's response" do
|
|
867
874
|
command.reason = :error
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
871
|
-
agi_command.name.should be == "EXEC Congestion"
|
|
872
|
-
agi_command.add_event expected_agi_complete_event
|
|
875
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Congestion').and_return code: 200
|
|
876
|
+
subject.execute_command command
|
|
873
877
|
command.response(0.5).should be true
|
|
874
878
|
end
|
|
875
879
|
end
|
|
@@ -878,11 +882,8 @@ module Punchblock
|
|
|
878
882
|
let(:command) { Command::Answer.new }
|
|
879
883
|
|
|
880
884
|
it "should send an ANSWER AGI command and set the command's response" do
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
884
|
-
agi_command.name.should be == "ANSWER"
|
|
885
|
-
agi_command.add_event expected_agi_complete_event
|
|
885
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('ANSWER').and_return code: 200
|
|
886
|
+
subject.execute_command command
|
|
886
887
|
command.response(0.5).should be true
|
|
887
888
|
end
|
|
888
889
|
end
|
|
@@ -891,11 +892,8 @@ module Punchblock
|
|
|
891
892
|
let(:command) { Command::Hangup.new }
|
|
892
893
|
|
|
893
894
|
it "should send a Hangup AMI command and set the command's response" do
|
|
895
|
+
ami_client.should_receive(:send_action).once.with('Hangup', 'Channel' => channel, 'Cause' => 16).and_return RubyAMI::Response.new
|
|
894
896
|
subject.execute_command command
|
|
895
|
-
ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
|
|
896
|
-
ami_action.name.should be == "hangup"
|
|
897
|
-
ami_action.headers['Cause'].should be == 16
|
|
898
|
-
ami_action << RubyAMI::Response.new
|
|
899
897
|
command.response(0.5).should be true
|
|
900
898
|
end
|
|
901
899
|
end
|
|
@@ -908,7 +906,6 @@ module Punchblock
|
|
|
908
906
|
let(:mock_action) { Translator::Asterisk::Component::Asterisk::AGICommand.new(command, subject) }
|
|
909
907
|
|
|
910
908
|
it 'should create an AGI command component actor and execute it asynchronously' do
|
|
911
|
-
mock_action.should_receive(:internal=).never
|
|
912
909
|
Component::Asterisk::AGICommand.should_receive(:new_link).once.with(command, subject).and_return mock_action
|
|
913
910
|
mock_action.async.should_receive(:execute).once
|
|
914
911
|
subject.execute_command command
|
|
@@ -924,7 +921,6 @@ module Punchblock
|
|
|
924
921
|
|
|
925
922
|
it 'should create an Output component and execute it asynchronously' do
|
|
926
923
|
Component::Output.should_receive(:new_link).once.with(command, subject).and_return mock_action
|
|
927
|
-
mock_action.should_receive(:internal=).never
|
|
928
924
|
mock_action.async.should_receive(:execute).once
|
|
929
925
|
subject.execute_command command
|
|
930
926
|
end
|
|
@@ -939,7 +935,6 @@ module Punchblock
|
|
|
939
935
|
|
|
940
936
|
it 'should create an Input component and execute it asynchronously' do
|
|
941
937
|
Component::Input.should_receive(:new_link).once.with(command, subject).and_return mock_action
|
|
942
|
-
mock_action.should_receive(:internal=).never
|
|
943
938
|
mock_action.async.should_receive(:execute).once
|
|
944
939
|
subject.execute_command command
|
|
945
940
|
end
|
|
@@ -954,7 +949,6 @@ module Punchblock
|
|
|
954
949
|
|
|
955
950
|
it 'should create a Record component and execute it asynchronously' do
|
|
956
951
|
Component::Record.should_receive(:new_link).once.with(command, subject).and_return mock_action
|
|
957
|
-
mock_action.should_receive(:internal=).never
|
|
958
952
|
mock_action.async.should_receive(:execute).once
|
|
959
953
|
subject.execute_command command
|
|
960
954
|
end
|
|
@@ -1059,7 +1053,7 @@ module Punchblock
|
|
|
1059
1053
|
let(:other_translator) { stub('Translator::Asterisk').as_null_object }
|
|
1060
1054
|
|
|
1061
1055
|
let :other_call do
|
|
1062
|
-
Call.new other_channel, other_translator
|
|
1056
|
+
Call.new other_channel, other_translator, ami_client, connection
|
|
1063
1057
|
end
|
|
1064
1058
|
|
|
1065
1059
|
let :command do
|
|
@@ -1067,11 +1061,9 @@ module Punchblock
|
|
|
1067
1061
|
end
|
|
1068
1062
|
|
|
1069
1063
|
it "executes the proper dialplan Bridge application" do
|
|
1064
|
+
subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Bridge', other_channel).and_return code: 200
|
|
1070
1065
|
translator.should_receive(:call_with_id).with(other_call_id).and_return(other_call)
|
|
1071
1066
|
subject.execute_command command
|
|
1072
|
-
agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
|
|
1073
|
-
agi_command.name.should be == "EXEC Bridge"
|
|
1074
|
-
agi_command.params_array.should be == [other_channel]
|
|
1075
1067
|
end
|
|
1076
1068
|
end
|
|
1077
1069
|
|
|
@@ -1080,7 +1072,7 @@ module Punchblock
|
|
|
1080
1072
|
let(:other_channel) { 'SIP/bar' }
|
|
1081
1073
|
|
|
1082
1074
|
let :other_call do
|
|
1083
|
-
Call.new other_channel, translator
|
|
1075
|
+
Call.new other_channel, translator, ami_client, connection
|
|
1084
1076
|
end
|
|
1085
1077
|
|
|
1086
1078
|
let :command do
|
|
@@ -1089,45 +1081,49 @@ module Punchblock
|
|
|
1089
1081
|
|
|
1090
1082
|
it "executes the unjoin through redirection" do
|
|
1091
1083
|
translator.should_receive(:call_with_id).with(other_call_id).and_return(nil)
|
|
1084
|
+
|
|
1085
|
+
ami_client.should_receive(:send_action).once.with("Redirect",
|
|
1086
|
+
'Channel' => channel,
|
|
1087
|
+
'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1088
|
+
'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1089
|
+
'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
|
|
1090
|
+
).and_return RubyAMI::Response.new
|
|
1091
|
+
|
|
1092
1092
|
subject.execute_command command
|
|
1093
|
-
|
|
1094
|
-
ami_action.name.should be == "redirect"
|
|
1095
|
-
ami_action.headers['Channel'].should be == channel
|
|
1096
|
-
ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
|
|
1097
|
-
ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
|
|
1098
|
-
ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
|
|
1099
|
-
|
|
1100
|
-
ami_action << RubyAMI::Response.new
|
|
1093
|
+
|
|
1101
1094
|
command.response(1).should be_true
|
|
1102
1095
|
end
|
|
1103
1096
|
|
|
1104
1097
|
it "executes the unjoin through redirection, on the subject call and the other call" do
|
|
1105
1098
|
translator.should_receive(:call_with_id).with(other_call_id).and_return(other_call)
|
|
1106
|
-
subject.execute_command command
|
|
1107
|
-
ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
|
|
1108
|
-
ami_action.name.should be == "redirect"
|
|
1109
|
-
ami_action.headers['Channel'].should be == channel
|
|
1110
|
-
ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
|
|
1111
|
-
ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
|
|
1112
|
-
ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
|
|
1113
1099
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1100
|
+
ami_client.should_receive(:send_action).once.with("Redirect",
|
|
1101
|
+
'Channel' => channel,
|
|
1102
|
+
'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1103
|
+
'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1104
|
+
'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
|
|
1105
|
+
'ExtraChannel' => other_channel,
|
|
1106
|
+
'ExtraExten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1107
|
+
'ExtraPriority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1108
|
+
'ExtraContext' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
|
|
1109
|
+
).and_return RubyAMI::Response.new
|
|
1110
|
+
|
|
1111
|
+
subject.execute_command command
|
|
1118
1112
|
end
|
|
1119
1113
|
|
|
1120
1114
|
it "handles redirect errors" do
|
|
1121
1115
|
translator.should_receive(:call_with_id).with(other_call_id).and_return(nil)
|
|
1116
|
+
|
|
1117
|
+
error = RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
|
|
1118
|
+
|
|
1119
|
+
ami_client.should_receive(:send_action).once.with("Redirect",
|
|
1120
|
+
'Channel' => channel,
|
|
1121
|
+
'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1122
|
+
'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1123
|
+
'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
|
|
1124
|
+
).and_raise error
|
|
1125
|
+
|
|
1122
1126
|
subject.execute_command command
|
|
1123
|
-
ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
|
|
1124
|
-
ami_action.name.should be == "redirect"
|
|
1125
|
-
ami_action.headers['Channel'].should be == channel
|
|
1126
|
-
ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
|
|
1127
|
-
ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
|
|
1128
|
-
ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
|
|
1129
|
-
|
|
1130
|
-
ami_action << RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
|
|
1131
1127
|
response = command.response(1)
|
|
1132
1128
|
response.should be_a ProtocolError
|
|
1133
1129
|
response.text.should == 'FooBar'
|
|
@@ -1135,54 +1131,91 @@ module Punchblock
|
|
|
1135
1131
|
end
|
|
1136
1132
|
end#execute_command
|
|
1137
1133
|
|
|
1138
|
-
describe '#
|
|
1134
|
+
describe '#execute_agi_command' do
|
|
1135
|
+
before { stub_uuids Punchblock.new_uuid }
|
|
1136
|
+
|
|
1137
|
+
let :response do
|
|
1138
|
+
RubyAMI::Response.new 'ActionID' => "552a9d9f-46d7-45d8-a257-06fe95f48d99",
|
|
1139
|
+
'Message' => 'Added AGI original_command to queue'
|
|
1140
|
+
end
|
|
1141
|
+
|
|
1139
1142
|
it 'should send an appropriate AsyncAGI AMI action' do
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
subject.
|
|
1143
|
+
Celluloid::Condition.any_instance.should_receive(:wait).and_return nil
|
|
1144
|
+
ami_client.should_receive(:send_action).once.with('AGI', 'Channel' => channel, 'Command' => 'EXEC ANSWER', 'CommandID' => Punchblock.new_uuid).and_return(response)
|
|
1145
|
+
subject.execute_agi_command 'EXEC ANSWER'
|
|
1143
1146
|
end
|
|
1144
|
-
end
|
|
1145
1147
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1148
|
+
context 'with some parameters' do
|
|
1149
|
+
let(:params) { [1000, 'foo'] }
|
|
1150
|
+
|
|
1151
|
+
it 'should send the appropriate action' do
|
|
1152
|
+
Celluloid::Condition.any_instance.should_receive(:wait).and_return nil
|
|
1153
|
+
ami_client.should_receive(:send_action).once.with('AGI', 'Channel' => channel, 'Command' => 'WAIT FOR DIGIT "1000" "foo"', 'CommandID' => Punchblock.new_uuid).and_return(response)
|
|
1154
|
+
subject.execute_agi_command 'WAIT FOR DIGIT', *params
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
|
|
1158
|
+
context 'with an error' do
|
|
1159
|
+
let :error do
|
|
1160
|
+
RubyAMI::Error.new.tap { |e| e.message = 'Action failed' }
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
it 'should raise the error' do
|
|
1164
|
+
ami_client.should_receive(:send_action).once.and_raise error
|
|
1165
|
+
expect { subject.execute_agi_command 'EXEC ANSWER' }.to raise_error(RubyAMI::Error, 'Action failed')
|
|
1166
|
+
end
|
|
1167
|
+
end
|
|
1168
|
+
|
|
1169
|
+
describe 'when receiving an AsyncAGI event' do
|
|
1170
|
+
context 'of type Exec' do
|
|
1171
|
+
let(:ami_event) do
|
|
1172
|
+
RubyAMI::Event.new 'AsyncAGI',
|
|
1173
|
+
"SubEvent" => "Exec",
|
|
1174
|
+
"Channel" => channel,
|
|
1175
|
+
"CommandID" => Punchblock.new_uuid,
|
|
1176
|
+
"Command" => "EXEC ANSWER",
|
|
1177
|
+
"Result" => "200%20result=123%20(timeout)%0A"
|
|
1178
|
+
end
|
|
1179
|
+
|
|
1180
|
+
it 'should return the result' do
|
|
1181
|
+
fut = subject.future.execute_agi_command 'EXEC ANSWER'
|
|
1149
1182
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1183
|
+
subject.process_ami_event ami_event
|
|
1184
|
+
|
|
1185
|
+
fut.value.should == {code: 200, result: 123, data: 'timeout'}
|
|
1186
|
+
end
|
|
1187
|
+
end
|
|
1154
1188
|
end
|
|
1155
1189
|
end
|
|
1156
1190
|
|
|
1157
1191
|
describe '#redirect_back' do
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
end
|
|
1192
|
+
let(:other_channel) { 'SIP/bar' }
|
|
1193
|
+
|
|
1194
|
+
let :other_call do
|
|
1195
|
+
Call.new other_channel, translator, ami_client, connection
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
it "executes the proper AMI action with only the subject call" do
|
|
1199
|
+
ami_client.should_receive(:send_action).once.with 'Redirect',
|
|
1200
|
+
'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1201
|
+
'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1202
|
+
'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
|
|
1203
|
+
'Channel' => channel
|
|
1204
|
+
subject.redirect_back
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
it "executes the proper AMI action with another call specified" do
|
|
1208
|
+
ami_client.should_receive(:send_action).once.with 'Redirect',
|
|
1209
|
+
'Channel' => channel,
|
|
1210
|
+
'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1211
|
+
'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1212
|
+
'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
|
|
1213
|
+
'ExtraChannel' => other_channel,
|
|
1214
|
+
'ExtraExten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
|
|
1215
|
+
'ExtraPriority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
|
|
1216
|
+
'ExtraContext' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
|
|
1217
|
+
subject.redirect_back other_call
|
|
1218
|
+
end
|
|
1186
1219
|
end
|
|
1187
1220
|
end
|
|
1188
1221
|
end
|