spec/punchblock/translator/asterisk/call_spec.rb in punchblock-0.6.1 vs spec/punchblock/translator/asterisk/call_spec.rb in punchblock-0.6.2
- old
+ new
@@ -2,15 +2,221 @@
module Punchblock
module Translator
class Asterisk
describe Call do
+ let(:channel) { 'SIP/foo' }
+ let(:translator) { stub_everything 'Translator::Asterisk' }
+ let(:env) { "agi_request%3A%20async%0Aagi_channel%3A%20SIP%2F1234-00000000%0Aagi_language%3A%20en%0Aagi_type%3A%20SIP%0Aagi_uniqueid%3A%201320835995.0%0Aagi_version%3A%201.8.4.1%0Aagi_callerid%3A%205678%0Aagi_calleridname%3A%20Jane%20Smith%0Aagi_callingpres%3A%200%0Aagi_callingani2%3A%200%0Aagi_callington%3A%200%0Aagi_callingtns%3A%200%0Aagi_dnid%3A%201000%0Aagi_rdnis%3A%20unknown%0Aagi_context%3A%20default%0Aagi_extension%3A%201000%0Aagi_priority%3A%201%0Aagi_enhanced%3A%200.0%0Aagi_accountcode%3A%20%0Aagi_threadid%3A%204366221312%0A%0A" }
+ let(:agi_env) do
+ {
+ :agi_request => 'async',
+ :agi_channel => 'SIP/1234-00000000',
+ :agi_language => 'en',
+ :agi_type => 'SIP',
+ :agi_uniqueid => '1320835995.0',
+ :agi_version => '1.8.4.1',
+ :agi_callerid => '5678',
+ :agi_calleridname => 'Jane Smith',
+ :agi_callingpres => '0',
+ :agi_callingani2 => '0',
+ :agi_callington => '0',
+ :agi_callingtns => '0',
+ :agi_dnid => '1000',
+ :agi_rdnis => 'unknown',
+ :agi_context => 'default',
+ :agi_extension => '1000',
+ :agi_priority => '1',
+ :agi_enhanced => '0.0',
+ :agi_accountcode => '',
+ :agi_threadid => '4366221312'
+ }
+ end
+
+ let :sip_headers do
+ {
+ :x_agi_request => 'async',
+ :x_agi_channel => 'SIP/1234-00000000',
+ :x_agi_language => 'en',
+ :x_agi_type => 'SIP',
+ :x_agi_uniqueid => '1320835995.0',
+ :x_agi_version => '1.8.4.1',
+ :x_agi_callerid => '5678',
+ :x_agi_calleridname => 'Jane Smith',
+ :x_agi_callingpres => '0',
+ :x_agi_callingani2 => '0',
+ :x_agi_callington => '0',
+ :x_agi_callingtns => '0',
+ :x_agi_dnid => '1000',
+ :x_agi_rdnis => 'unknown',
+ :x_agi_context => 'default',
+ :x_agi_extension => '1000',
+ :x_agi_priority => '1',
+ :x_agi_enhanced => '0.0',
+ :x_agi_accountcode => '',
+ :x_agi_threadid => '4366221312'
+ }
+ end
+
+ subject { Call.new channel, translator, env }
+
+ its(:id) { should be_a String }
+ its(:channel) { should == channel }
+ its(:translator) { should be translator }
+ its(:agi_env) { should == agi_env }
+
describe '#register_component' do
it 'should make the component accessible by ID' do
component_id = 'abc123'
component = mock 'Translator::Asterisk::Component', :id => component_id
subject.register_component component
subject.component_with_id(component_id).should be component
+ end
+ end
+
+ describe '#send_offer' do
+ it 'sends an offer to the translator' do
+ expected_offer = Punchblock::Event::Offer.new :call_id => subject.id,
+ :to => '1000',
+ :from => 'sip:5678',
+ :headers => sip_headers
+ translator.expects(:handle_pb_event!).with expected_offer
+ subject.send_offer
+ 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'] = "0"
+ e['Cause-txt'] = "Unknown"
+ e['Channel'] = "SIP/1234-00000000"
+ end
+ end
+
+ it 'should send an end event to the translator' do
+ expected_end_event = Punchblock::Event::End.new :reason => :hangup,
+ :call_id => subject.id
+ translator.expects(:handle_pb_event!).with expected_end_event
+ subject.process_ami_event ami_event
+ end
+ end
+
+ context 'with an event for a known AGI command component' do
+ let(:mock_component_node) { mock 'Punchblock::Component::Asterisk::AGI::Command', :name => 'EXEC ANSWER' }
+ let :component do
+ Component::Asterisk::AGICommand.new mock_component_node, subject.translator
+ end
+
+ let(:ami_event) do
+ RubyAMI::Event.new("AGIExec").tap do |e|
+ e["SubEvent"] = "End"
+ e["Channel"] = "SIP/1234-00000000"
+ e["CommandId"] = component.id
+ e["Command"] = "EXEC ANSWER"
+ e["ResultCode"] = "200"
+ e["Result"] = "Success"
+ e["Data"] = "FOO"
+ end
+ end
+
+ before do
+ subject.register_component component
+ end
+
+ it 'should send the event to the component' do
+ component.expects(:handle_ami_event!).once.with ami_event
+ subject.process_ami_event ami_event
+ end
+ 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
+ subject.execute_command command
+ agi_command = subject.actor_subject.instance_variable_get(:'@current_agi_command')
+ agi_command.name.should == "EXEC RINGING"
+ agi_command.execute!
+ agi_command.add_event expected_agi_complete_event
+ command.response(0.5).should be true
+ end
+ end
+
+ context 'with an answer command' do
+ let(:command) { Command::Answer.new }
+
+ it "should send an EXEC ANSWER AGI command and set the command's response" do
+ subject.execute_command command
+ agi_command = subject.actor_subject.instance_variable_get(:'@current_agi_command')
+ agi_command.name.should == "EXEC ANSWER"
+ agi_command.execute!
+ agi_command.add_event expected_agi_complete_event
+ 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
+ subject.execute_command command
+ ami_action = subject.actor_subject.instance_variable_get(:'@current_ami_action')
+ ami_action.name.should == "hangup"
+ ami_action << RubyAMI::Response.new
+ command.response(0.5).should be true
+ end
+ end
+
+ context 'with a component' do
+ let :command do
+ Punchblock::Component::Asterisk::AGI::Command.new :name => 'Answer'
+ end
+
+ let(:mock_action) { mock 'Component::Asterisk::AGI::Command', :id => 'foo' }
+
+ it 'should create a component actor and execute it asynchronously' do
+ Component::Asterisk::AGICommand.expects(:new).once.with(command, subject).returns mock_action
+ mock_action.expects(:execute!).once
+ subject.execute_command command
+ end
+ end
+ end
+
+ describe '#send_agi_action' do
+ it 'should send an appropriate AsyncAGI AMI action' do
+ pending
+ subject.actor_subject.expects(:send_ami_action).once.with('AGI', 'Command' => 'FOO', 'Channel' => subject.channel)
+ subject.send_agi_action 'FOO'
+ end
+ end
+
+ describe '#send_ami_action' do
+ let(:component_id) { UUIDTools::UUID.random_create }
+ before { UUIDTools::UUID.stubs :random_create => component_id }
+
+ it 'should send the action to the AMI client' do
+ action = RubyAMI::Action.new 'foo', :foo => :bar
+ translator.expects(:send_ami_action!).once.with action
+ subject.send_ami_action 'foo', :foo => :bar
end
end
end
end
end