spec/punchblock/translator/asterisk/call_spec.rb in punchblock-1.8.2 vs spec/punchblock/translator/asterisk/call_spec.rb in punchblock-1.9.0
- old
+ new
@@ -5,11 +5,13 @@
module Punchblock
module Translator
class Asterisk
describe Call do
let(:channel) { 'SIP/foo' }
- let(:translator) { Asterisk.new stub('AMI Client').as_null_object, stub('connection').as_null_object }
+ let(:ami_client) { stub('AMI Client').as_null_object }
+ let(:connection) { stub('connection').as_null_object }
+ let(:translator) { Asterisk.new ami_client, connection }
let(:agi_env) do
{
:agi_request => 'async',
:agi_channel => 'SIP/1234-00000000',
:agi_language => 'en',
@@ -56,11 +58,11 @@
:x_agi_accountcode => '',
:x_agi_threadid => '4366221312'
}
end
- subject { Call.new channel, translator, agi_env }
+ subject { Call.new channel, translator, ami_client, connection, agi_env }
its(:id) { should be_a String }
its(:channel) { should be == channel }
its(:translator) { should be translator }
its(:agi_env) { should be == agi_env }
@@ -82,10 +84,26 @@
subject.register_component component
subject.component_with_id(component_id).should be component
end
end
+ describe "getting channel vars" do
+ it "should do a GetVar when we don't have a cached value" do
+ response = RubyAMI::Response.new 'Value' => 'thevalue'
+ ami_client.should_receive(:send_action).once.with('GetVar', 'Channel' => channel, 'Variable' => 'somevariable').and_return response
+ subject.channel_var('somevariable').should == 'thevalue'
+ end
+
+ context "when the value comes back from GetVar as '(null)'" do
+ it "should return nil" do
+ response = RubyAMI::Response.new 'Value' => '(null)'
+ ami_client.should_receive(:send_action).once.with('GetVar', 'Channel' => channel, 'Variable' => 'somevariable').and_return response
+ subject.channel_var('somevariable').should be_nil
+ end
+ end
+ end
+
describe '#send_offer' do
it 'sends an offer to the translator' do
expected_offer = Punchblock::Event::Offer.new :target_call_id => subject.id,
:to => '1000',
:from => 'Jane Smith <SIP/5678>',
@@ -101,15 +119,14 @@
subject.outbound?.should be false
end
end
describe '#send_progress' do
-
context "with a call that is already answered" do
it 'should not send the EXEC Progress command' do
subject.wrapped_object.should_receive(:'answered?').and_return true
- subject.wrapped_object.should_receive(:send_agi_action).with("EXEC Progress").never
+ subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").never
subject.send_progress
end
end
context "with an unanswered call" do
@@ -124,27 +141,27 @@
dial_command.request!
subject.dial dial_command
end
it 'should not send the EXEC Progress command' do
- subject.wrapped_object.should_receive(:send_agi_action).with("EXEC Progress").never
+ subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").never
subject.send_progress
end
end
context "with a call that is inbound" do
before do
subject.send_offer
end
it 'should send the EXEC Progress command to a call that is inbound and not answered' do
- subject.wrapped_object.should_receive(:send_agi_action).with("EXEC Progress")
+ subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").and_return code: 200, result: 0
subject.send_progress
end
it 'should send the EXEC Progress command only once if called twice' do
- subject.wrapped_object.should_receive(:send_agi_action).with("EXEC Progress").once
+ subject.wrapped_object.should_receive(:execute_agi_command).with("EXEC Progress").once.and_return code: 200, result: 0
subject.send_progress
subject.send_progress
end
end
end
@@ -253,27 +270,26 @@
it 'causes accepting the call to be a null operation' do
subject.dial dial_command
accept_command = Command::Accept.new
accept_command.request!
- subject.wrapped_object.should_receive(:send_agi_action).never
+ subject.wrapped_object.should_receive(:execute_agi_command).never
subject.execute_command accept_command
accept_command.response(0.5).should be true
end
end
describe '#process_ami_event' do
context 'with a Hangup event' do
let :ami_event do
- RubyAMI::Event.new('Hangup').tap do |e|
- e['Uniqueid'] = "1320842458.8"
- e['Calleridnum'] = "5678"
- e['Calleridname'] = "Jane Smith"
- e['Cause'] = cause
- e['Cause-txt'] = cause_txt
- e['Channel'] = "SIP/1234-00000000"
- end
+ RubyAMI::Event.new 'Hangup',
+ 'Uniqueid' => "1320842458.8",
+ 'Calleridnum' => "5678",
+ 'Calleridname' => "Jane Smith",
+ 'Cause' => cause,
+ 'Cause-txt' => cause_txt,
+ 'Channel' => "SIP/1234-00000000"
end
let(:cause) { '16' }
let(:cause_txt) { 'Normal Clearing' }
@@ -289,10 +305,11 @@
translator.should_receive(:deregister_call).once.with(subject)
subject.process_ami_event ami_event
end
it "should cause all components to send complete events before sending end event" do
+ subject.stub :send_progress
comp_command = Punchblock::Component::Input.new :grammar => {:value => '<grammar/>'}, :mode => :dtmf
comp_command.request!
component = subject.execute_command comp_command
comp_command.response(0.1).should be_a Ref
expected_complete_event = Punchblock::Event::Complete.new :target_call_id => subject.id, :component_id => component.id
@@ -303,10 +320,11 @@
translator.should_receive(:handle_pb_event).with(expected_end_event).once.ordered
subject.process_ami_event ami_event
end
it "should not allow commands to be executed while components are shutting down" do
+ subject.stub :send_progress
comp_command = Punchblock::Component::Input.new :grammar => {:value => '<grammar/>'}, :mode => :dtmf
comp_command.request!
component = subject.execute_command comp_command
comp_command.response(0.1).should be_a Ref
@@ -447,17 +465,16 @@
let :component do
Component::Asterisk::AGICommand.new mock_component_node, subject
end
let(:ami_event) do
- RubyAMI::Event.new("AsyncAGI").tap do |e|
- e["SubEvent"] = "End"
- e["Channel"] = "SIP/1234-00000000"
- e["CommandID"] = component.id
- e["Command"] = "EXEC ANSWER"
- e["Result"] = "200%20result=123%20(timeout)%0A"
- end
+ RubyAMI::Event.new "AsyncAGI",
+ "SubEvent" => "End",
+ "Channel" => "SIP/1234-00000000",
+ "CommandID" => component.id,
+ "Command" => "EXEC ANSWER",
+ "Result" => "200%20result=123%20(timeout)%0A"
end
before do
subject.register_component component
end
@@ -468,21 +485,20 @@
end
end
context 'with a Newstate event' do
let :ami_event do
- RubyAMI::Event.new('Newstate').tap do |e|
- e['Privilege'] = 'call,all'
- e['Channel'] = 'SIP/1234-00000000'
- e['ChannelState'] = channel_state
- e['ChannelStateDesc'] = channel_state_desc
- e['CallerIDNum'] = ''
- e['CallerIDName'] = ''
- e['ConnectedLineNum'] = ''
- e['ConnectedLineName'] = ''
- e['Uniqueid'] = '1326194671.0'
- end
+ RubyAMI::Event.new 'Newstate',
+ 'Privilege' => 'call,all',
+ 'Channel' => 'SIP/1234-00000000',
+ 'ChannelState' => channel_state,
+ 'ChannelStateDesc' => channel_state_desc,
+ 'CallerIDNum' => '',
+ 'CallerIDName' => '',
+ 'ConnectedLineNum' => '',
+ 'ConnectedLineName' => '',
+ 'Uniqueid' => '1326194671.0'
end
context 'ringing' do
let(:channel_state) { '5' }
let(:channel_state_desc) { 'Ringing' }
@@ -518,22 +534,21 @@
end
end
context 'with an OriginateResponse event' do
let :ami_event do
- RubyAMI::Event.new('OriginateResponse').tap do |e|
- e['Privilege'] = 'call,all'
- e['ActionID'] = '9d0c1aa4-5e3b-4cae-8aef-76a6119e2909'
- e['Response'] = response
- e['Channel'] = 'SIP/15557654321'
- e['Context'] = ''
- e['Exten'] = ''
- e['Reason'] = '0'
- e['Uniqueid'] = uniqueid
- e['CallerIDNum'] = 'sip:5551234567'
- e['CallerIDName'] = 'Bryan 100'
- end
+ RubyAMI::Event.new 'OriginateResponse',
+ 'Privilege' => 'call,all',
+ 'ActionID' => '9d0c1aa4-5e3b-4cae-8aef-76a6119e2909',
+ 'Response' => response,
+ 'Channel' => 'SIP/15557654321',
+ 'Context' => '',
+ 'Exten' => '',
+ 'Reason' => '0',
+ 'Uniqueid' => uniqueid,
+ 'CallerIDNum' => 'sip:5551234567',
+ 'CallerIDName' => 'Bryan 100'
end
context 'sucessful' do
let(:response) { 'Success' }
let(:uniqueid) { '<null>' }
@@ -567,17 +582,16 @@
end
end
context 'with a handler registered for a matching event' do
let :ami_event do
- RubyAMI::Event.new('DTMF').tap do |e|
- e['Digit'] = '4'
- e['Start'] = 'Yes'
- e['End'] = 'No'
- e['Uniqueid'] = "1320842458.8"
- e['Channel'] = "SIP/1234-00000000"
- end
+ RubyAMI::Event.new 'DTMF',
+ 'Digit' => '4',
+ 'Start' => 'Yes',
+ 'End' => 'No',
+ 'Uniqueid' => "1320842458.8",
+ 'Channel' => "SIP/1234-00000000"
end
let(:response) { mock 'Response' }
it 'should execute the handler' do
@@ -589,49 +603,48 @@
end
end
context 'with a BridgeExec event' do
let :ami_event do
- RubyAMI::Event.new('BridgeExec').tap do |e|
- e['Privilege'] = "call,all"
- e['Response'] = "Success"
- e['Channel1'] = "SIP/foo"
- e['Channel2'] = other_channel
- end
+ RubyAMI::Event.new 'BridgeExec',
+ 'Privilege' => "call,all",
+ 'Response' => "Success",
+ 'Channel1' => "SIP/foo",
+ 'Channel2' => other_channel
end
let(:other_channel) { 'SIP/5678-00000000' }
context "when a join has been executed against another call" do
let :other_call do
- Call.new other_channel, translator
+ Call.new other_channel, translator, ami_client, connection
end
let(:other_call_id) { other_call.id }
let :command do
Punchblock::Command::Join.new :call_id => other_call_id
end
before do
translator.register_call other_call
command.request!
+ subject.wrapped_object.should_receive(:execute_agi_command).and_return code: 200
subject.execute_command command
end
it 'retrieves and sets success on the correct Join' do
subject.process_ami_event ami_event
command.response(0.5).should be == true
end
context "with the channel names reversed" do
let :ami_event do
- RubyAMI::Event.new('BridgeExec').tap do |e|
- e['Privilege'] = "call,all"
- e['Response'] = "Success"
- e['Channel1'] = other_channel
- e['Channel2'] = "SIP/foo"
- end
+ RubyAMI::Event.new 'BridgeExec',
+ 'Privilege' => "call,all",
+ 'Response' => "Success",
+ 'Channel1' => other_channel,
+ 'Channel2' => "SIP/foo"
end
it 'retrieves and sets success on the correct Join' do
subject.process_ami_event ami_event
command.response(0.5).should be == true
@@ -648,39 +661,37 @@
context 'with a Bridge event' do
let(:other_channel) { 'SIP/5678-00000000' }
let(:other_call_id) { 'def567' }
let :other_call do
- Call.new other_channel, translator
+ Call.new other_channel, translator, ami_client, connection
end
let :ami_event do
- RubyAMI::Event.new('Bridge').tap do |e|
- e['Privilege'] = "call,all"
- e['Bridgestate'] = state
- e['Bridgetype'] = "core"
- e['Channel1'] = channel
- e['Channel2'] = other_channel
- e['Uniqueid1'] = "1319717537.11"
- e['Uniqueid2'] = "1319717537.10"
- e['CallerID1'] = "1234"
- e['CallerID2'] = "5678"
- end
+ RubyAMI::Event.new 'Bridge',
+ 'Privilege' => "call,all",
+ 'Bridgestate' => state,
+ 'Bridgetype' => "core",
+ 'Channel1' => channel,
+ 'Channel2' => other_channel,
+ 'Uniqueid1' => "1319717537.11",
+ 'Uniqueid2' => "1319717537.10",
+ 'CallerID1' => "1234",
+ 'CallerID2' => "5678"
end
let :switched_ami_event do
- RubyAMI::Event.new('Bridge').tap do |e|
- e['Privilege'] = "call,all"
- e['Bridgestate'] = state
- e['Bridgetype'] = "core"
- e['Channel1'] = other_channel
- e['Channel2'] = channel
- e['Uniqueid1'] = "1319717537.11"
- e['Uniqueid2'] = "1319717537.10"
- e['CallerID1'] = "1234"
- e['CallerID2'] = "5678"
- end
+ RubyAMI::Event.new 'Bridge',
+ 'Privilege' => "call,all",
+ 'Bridgestate' => state,
+ 'Bridgetype' => "core",
+ 'Channel1' => other_channel,
+ 'Channel2' => channel,
+ 'Uniqueid1' => "1319717537.11",
+ 'Uniqueid2' => "1319717537.10",
+ 'CallerID1' => "1234",
+ 'CallerID2' => "5678"
end
before do
translator.register_call other_call
translator.should_receive(:call_for_channel).with(other_channel).and_return(other_call)
@@ -732,35 +743,33 @@
context 'with an Unlink event' do
let(:other_channel) { 'SIP/5678-00000000' }
let(:other_call_id) { 'def567' }
let :other_call do
- Call.new other_channel, translator
+ Call.new other_channel, translator, ami_client, connection
end
let :ami_event do
- RubyAMI::Event.new('Unlink').tap do |e|
- e['Privilege'] = "call,all"
- e['Channel1'] = channel
- e['Channel2'] = other_channel
- e['Uniqueid1'] = "1319717537.11"
- e['Uniqueid2'] = "1319717537.10"
- e['CallerID1'] = "1234"
- e['CallerID2'] = "5678"
- end
+ RubyAMI::Event.new 'Unlink',
+ 'Privilege' => "call,all",
+ 'Channel1' => channel,
+ 'Channel2' => other_channel,
+ 'Uniqueid1' => "1319717537.11",
+ 'Uniqueid2' => "1319717537.10",
+ 'CallerID1' => "1234",
+ 'CallerID2' => "5678"
end
let :switched_ami_event do
- RubyAMI::Event.new('Unlink').tap do |e|
- e['Privilege'] = "call,all"
- e['Channel1'] = other_channel
- e['Channel2'] = channel
- e['Uniqueid1'] = "1319717537.11"
- e['Uniqueid2'] = "1319717537.10"
- e['CallerID1'] = "1234"
- e['CallerID2'] = "5678"
- end
+ RubyAMI::Event.new 'Unlink',
+ 'Privilege' => "call,all",
+ 'Channel1' => other_channel,
+ 'Channel2' => channel,
+ 'Uniqueid1' => "1319717537.11",
+ 'Uniqueid2' => "1319717537.10",
+ 'CallerID1' => "1234",
+ 'CallerID2' => "5678"
end
before do
translator.register_call other_call
translator.should_receive(:call_for_channel).with(other_channel).and_return(other_call)
@@ -783,21 +792,36 @@
translator.should_receive(:handle_pb_event).with expected_unjoined
subject.process_ami_event switched_ami_event
end
end
- let :ami_event do
- RubyAMI::Event.new('Foo').tap do |e|
- e['Uniqueid'] = "1320842458.8"
- e['Calleridnum'] = "5678"
- e['Calleridname'] = "Jane Smith"
- e['Cause'] = "0"
- e['Cause-txt'] = "Unknown"
- e['Channel'] = channel
+ context 'with a VarSet event' do
+ let :ami_event do
+ RubyAMI::Event.new 'VarSet',
+ "Privilege" => "dialplan,all",
+ "Channel" => "SIP/1234-00000000",
+ "Variable" => "foobar",
+ "Value" => 'abc123',
+ "Uniqueid" => "1326210224.0"
end
+
+ it 'makes the variable accessible on the call' do
+ subject.process_ami_event ami_event
+ subject.channel_var('foobar').should == 'abc123'
+ end
end
+ let :ami_event do
+ RubyAMI::Event.new 'Foo',
+ 'Uniqueid' => "1320842458.8",
+ 'Calleridnum' => "5678",
+ 'Calleridname' => "Jane Smith",
+ 'Cause' => "0",
+ 'Cause-txt' => "Unknown",
+ 'Channel' => channel
+ end
+
let :expected_pb_event do
Event::Asterisk::AMI::Event.new :name => 'Foo',
:attributes => { :channel => channel,
:uniqueid => "1320842458.8",
:calleridnum => "5678",
@@ -813,91 +837,65 @@
end
end
describe '#execute_command' do
- let :expected_agi_complete_event do
- Punchblock::Event::Complete.new.tap do |c|
- c.reason = Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new :code => 200,
- :result => 'Success',
- :data => 'FOO'
- end
- end
-
before do
command.request!
end
context 'with an accept command' do
let(:command) { Command::Accept.new }
it "should send an EXEC RINGING AGI command and set the command's response" do
- component = subject.execute_command command
- component.internal.should be_true
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "EXEC RINGING"
- agi_command.add_event expected_agi_complete_event
+ subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC RINGING').and_return code: 200
+ subject.execute_command command
command.response(0.5).should be true
end
end
context 'with a reject command' do
let(:command) { Command::Reject.new }
it "with a :busy reason should send an EXEC Busy AGI command and set the command's response" do
command.reason = :busy
- component = subject.execute_command command
- component.internal.should be_true
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "EXEC Busy"
- agi_command.add_event expected_agi_complete_event
+ subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Busy').and_return code: 200
+ subject.execute_command command
command.response(0.5).should be true
end
it "with a :decline reason should send an EXEC Busy AGI command and set the command's response" do
command.reason = :decline
- component = subject.execute_command command
- component.internal.should be_true
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "EXEC Busy"
- agi_command.add_event expected_agi_complete_event
+ subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Busy').and_return code: 200
+ subject.execute_command command
command.response(0.5).should be true
end
it "with an :error reason should send an EXEC Congestion AGI command and set the command's response" do
command.reason = :error
- component = subject.execute_command command
- component.internal.should be_true
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "EXEC Congestion"
- agi_command.add_event expected_agi_complete_event
+ subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Congestion').and_return code: 200
+ subject.execute_command command
command.response(0.5).should be true
end
end
context 'with an answer command' do
let(:command) { Command::Answer.new }
it "should send an ANSWER AGI command and set the command's response" do
- component = subject.execute_command command
- component.internal.should be_true
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "ANSWER"
- agi_command.add_event expected_agi_complete_event
+ subject.wrapped_object.should_receive(:execute_agi_command).with('ANSWER').and_return code: 200
+ subject.execute_command command
command.response(0.5).should be true
end
end
context 'with a hangup command' do
let(:command) { Command::Hangup.new }
it "should send a Hangup AMI command and set the command's response" do
+ ami_client.should_receive(:send_action).once.with('Hangup', 'Channel' => channel, 'Cause' => 16).and_return RubyAMI::Response.new
subject.execute_command command
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "hangup"
- ami_action.headers['Cause'].should be == 16
- ami_action << RubyAMI::Response.new
command.response(0.5).should be true
end
end
context 'with an AGI command component' do
@@ -906,11 +904,10 @@
end
let(:mock_action) { Translator::Asterisk::Component::Asterisk::AGICommand.new(command, subject) }
it 'should create an AGI command component actor and execute it asynchronously' do
- mock_action.should_receive(:internal=).never
Component::Asterisk::AGICommand.should_receive(:new_link).once.with(command, subject).and_return mock_action
mock_action.async.should_receive(:execute).once
subject.execute_command command
end
end
@@ -922,11 +919,10 @@
let(:mock_action) { Translator::Asterisk::Component::Output.new(command, subject) }
it 'should create an Output component and execute it asynchronously' do
Component::Output.should_receive(:new_link).once.with(command, subject).and_return mock_action
- mock_action.should_receive(:internal=).never
mock_action.async.should_receive(:execute).once
subject.execute_command command
end
end
@@ -937,11 +933,10 @@
let(:mock_action) { Translator::Asterisk::Component::Input.new(command, subject) }
it 'should create an Input component and execute it asynchronously' do
Component::Input.should_receive(:new_link).once.with(command, subject).and_return mock_action
- mock_action.should_receive(:internal=).never
mock_action.async.should_receive(:execute).once
subject.execute_command command
end
end
@@ -952,11 +947,10 @@
let(:mock_action) { Translator::Asterisk::Component::Record.new(command, subject) }
it 'should create a Record component and execute it asynchronously' do
Component::Record.should_receive(:new_link).once.with(command, subject).and_return mock_action
- mock_action.should_receive(:internal=).never
mock_action.async.should_receive(:execute).once
subject.execute_command command
end
end
@@ -1057,133 +1051,172 @@
let(:other_call_id) { "abc123" }
let(:other_channel) { 'SIP/bar' }
let(:other_translator) { stub('Translator::Asterisk').as_null_object }
let :other_call do
- Call.new other_channel, other_translator
+ Call.new other_channel, other_translator, ami_client, connection
end
let :command do
Punchblock::Command::Join.new :call_id => other_call_id
end
it "executes the proper dialplan Bridge application" do
+ subject.wrapped_object.should_receive(:execute_agi_command).with('EXEC Bridge', other_channel).and_return code: 200
translator.should_receive(:call_with_id).with(other_call_id).and_return(other_call)
subject.execute_command command
- agi_command = subject.wrapped_object.instance_variable_get(:'@current_agi_command')
- agi_command.name.should be == "EXEC Bridge"
- agi_command.params_array.should be == [other_channel]
end
end
context "with an unjoin command" do
let(:other_call_id) { "abc123" }
let(:other_channel) { 'SIP/bar' }
let :other_call do
- Call.new other_channel, translator
+ Call.new other_channel, translator, ami_client, connection
end
let :command do
Punchblock::Command::Unjoin.new :call_id => other_call_id
end
it "executes the unjoin through redirection" do
translator.should_receive(:call_with_id).with(other_call_id).and_return(nil)
+
+ ami_client.should_receive(:send_action).once.with("Redirect",
+ 'Channel' => channel,
+ 'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
+ ).and_return RubyAMI::Response.new
+
subject.execute_command command
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "redirect"
- ami_action.headers['Channel'].should be == channel
- ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
- ami_action << RubyAMI::Response.new
command.response(1).should be_true
end
it "executes the unjoin through redirection, on the subject call and the other call" do
translator.should_receive(:call_with_id).with(other_call_id).and_return(other_call)
- subject.execute_command command
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "redirect"
- ami_action.headers['Channel'].should be == channel
- ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
- ami_action.headers['ExtraChannel'].should be == other_channel
- ami_action.headers['ExtraExten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['ExtraPriority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['ExtraContext'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
+ ami_client.should_receive(:send_action).once.with("Redirect",
+ 'Channel' => channel,
+ 'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
+ 'ExtraChannel' => other_channel,
+ 'ExtraExten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'ExtraPriority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'ExtraContext' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
+ ).and_return RubyAMI::Response.new
+
+ subject.execute_command command
end
it "handles redirect errors" do
translator.should_receive(:call_with_id).with(other_call_id).and_return(nil)
- subject.execute_command command
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "redirect"
- ami_action.headers['Channel'].should be == channel
- ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
- ami_action << RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
+ error = RubyAMI::Error.new.tap { |e| e.message = 'FooBar' }
+
+ ami_client.should_receive(:send_action).once.with("Redirect",
+ 'Channel' => channel,
+ 'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
+ ).and_raise error
+
+ subject.execute_command command
response = command.response(1)
response.should be_a ProtocolError
response.text.should == 'FooBar'
end
end
end#execute_command
- describe '#send_agi_action' do
+ describe '#execute_agi_command' do
+ before { stub_uuids Punchblock.new_uuid }
+
+ let :response do
+ RubyAMI::Response.new 'ActionID' => "552a9d9f-46d7-45d8-a257-06fe95f48d99",
+ 'Message' => 'Added AGI original_command to queue'
+ end
+
it 'should send an appropriate AsyncAGI AMI action' do
- pending
- subject.wrapped_object.should_receive(:send_ami_action).once.with('AGI', 'Command' => 'FOO', 'Channel' => subject.channel)
- subject.send_agi_action 'FOO'
+ Celluloid::Condition.any_instance.should_receive(:wait).and_return nil
+ ami_client.should_receive(:send_action).once.with('AGI', 'Channel' => channel, 'Command' => 'EXEC ANSWER', 'CommandID' => Punchblock.new_uuid).and_return(response)
+ subject.execute_agi_command 'EXEC ANSWER'
end
- end
- describe '#send_ami_action' do
- let(:component_id) { Punchblock.new_uuid }
- before { stub_uuids component_id }
+ context 'with some parameters' do
+ let(:params) { [1000, 'foo'] }
- it 'should send the action to the AMI client' do
- action = RubyAMI::Action.new 'foo', :foo => :bar
- translator.should_receive(:send_ami_action).once.with action
- subject.send_ami_action 'foo', :foo => :bar
+ it 'should send the appropriate action' do
+ Celluloid::Condition.any_instance.should_receive(:wait).and_return nil
+ ami_client.should_receive(:send_action).once.with('AGI', 'Channel' => channel, 'Command' => 'WAIT FOR DIGIT "1000" "foo"', 'CommandID' => Punchblock.new_uuid).and_return(response)
+ subject.execute_agi_command 'WAIT FOR DIGIT', *params
+ end
end
- end
- describe '#redirect_back' do
- let(:other_channel) { 'SIP/bar' }
- let :other_call do
- Call.new other_channel, translator
+ context 'with an error' do
+ let :error do
+ RubyAMI::Error.new.tap { |e| e.message = 'Action failed' }
end
- it "executes the proper AMI action with only the subject call" do
- subject.redirect_back
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "redirect"
- ami_action.headers['Channel'].should be == channel
- ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
+ it 'should raise the error' do
+ ami_client.should_receive(:send_action).once.and_raise error
+ expect { subject.execute_agi_command 'EXEC ANSWER' }.to raise_error(RubyAMI::Error, 'Action failed')
end
+ end
- it "executes the proper AMI action with another call specified" do
- subject.redirect_back other_call
- ami_action = subject.wrapped_object.instance_variable_get(:'@current_ami_action')
- ami_action.name.should be == "redirect"
- ami_action.headers['Channel'].should be == channel
- ami_action.headers['Exten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['Priority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['Context'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
- ami_action.headers['ExtraChannel'].should be == other_channel
- ami_action.headers['ExtraExten'].should be == Punchblock::Translator::Asterisk::REDIRECT_EXTENSION
- ami_action.headers['ExtraPriority'].should be == Punchblock::Translator::Asterisk::REDIRECT_PRIORITY
- ami_action.headers['ExtraContext'].should be == Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
+ describe 'when receiving an AsyncAGI event' do
+ context 'of type Exec' do
+ let(:ami_event) do
+ RubyAMI::Event.new 'AsyncAGI',
+ "SubEvent" => "Exec",
+ "Channel" => channel,
+ "CommandID" => Punchblock.new_uuid,
+ "Command" => "EXEC ANSWER",
+ "Result" => "200%20result=123%20(timeout)%0A"
+ end
+
+ it 'should return the result' do
+ fut = subject.future.execute_agi_command 'EXEC ANSWER'
+
+ subject.process_ami_event ami_event
+
+ fut.value.should == {code: 200, result: 123, data: 'timeout'}
+ end
end
+ end
+ end
+
+ describe '#redirect_back' do
+ let(:other_channel) { 'SIP/bar' }
+
+ let :other_call do
+ Call.new other_channel, translator, ami_client, connection
+ end
+
+ it "executes the proper AMI action with only the subject call" do
+ ami_client.should_receive(:send_action).once.with 'Redirect',
+ 'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
+ 'Channel' => channel
+ subject.redirect_back
+ end
+
+ it "executes the proper AMI action with another call specified" do
+ ami_client.should_receive(:send_action).once.with 'Redirect',
+ 'Channel' => channel,
+ 'Exten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'Priority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'Context' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT,
+ 'ExtraChannel' => other_channel,
+ 'ExtraExten' => Punchblock::Translator::Asterisk::REDIRECT_EXTENSION,
+ 'ExtraPriority' => Punchblock::Translator::Asterisk::REDIRECT_PRIORITY,
+ 'ExtraContext' => Punchblock::Translator::Asterisk::REDIRECT_CONTEXT
+ subject.redirect_back other_call
+ end
end
end
end
end
end