punchblock 1.8.2 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|