spec/punchblock/translator/asterisk/component/output_spec.rb in punchblock-0.10.0 vs spec/punchblock/translator/asterisk/component/output_spec.rb in punchblock-0.11.0

- old
+ new

@@ -7,18 +7,18 @@ class Asterisk module Component describe Output do let(:connection) do mock_connection_with_event_handler do |event| - command.add_event event + original_command.add_event event end end let(:media_engine) { nil } let(:translator) { Punchblock::Translator::Asterisk.new mock('AMI'), connection, media_engine } let(:mock_call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator } - let :command do + let :original_command do Punchblock::Component::Output.new command_options end let :ssml_doc do RubySpeech::SSML.draw do @@ -28,14 +28,14 @@ let :command_options do { :ssml => ssml_doc } end - subject { Output.new command, mock_call } + subject { Output.new original_command, mock_call } describe '#execute' do - before { command.request! } + before { original_command.request! } it "calls answer_if_not_answered on the call" do mock_call.expects :answer_if_not_answered subject.execute end @@ -73,11 +73,11 @@ it 'should send a complete event when Swift completes' do def mock_call.send_agi_action!(*args, &block) block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1) end subject.execute - command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success + original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success end describe 'interrupt_on' do context "set to nil" do let(:command_opts) { { :interrupt_on => nil } } @@ -105,12 +105,12 @@ context "set to :speech" do let(:command_opts) { { :interrupt_on => :speech } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'An interrupt-on value of speech is unsupported.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'An interrupt-on value of speech is unsupported.' + original_command.response(0.1).should be == error end end end describe 'voice' do @@ -166,20 +166,20 @@ it 'should send a complete event when MRCPSynth completes' do def mock_call.send_agi_action!(*args, &block) block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1) end subject.execute - command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success + original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success end describe 'ssml' do context 'unset' do let(:command_opts) { { :ssml => nil } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'An SSML document is required.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'An SSML document is required.' + original_command.response(0.1).should be == error end end end describe 'start-offset' do @@ -193,12 +193,12 @@ context 'set' do let(:command_opts) { { :start_offset => 10 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A start_offset value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A start_offset value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'start-paused' do @@ -212,12 +212,12 @@ context 'true' do let(:command_opts) { { :start_paused => true } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A start_paused value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A start_paused value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'repeat-interval' do @@ -231,12 +231,12 @@ context 'set' do let(:command_opts) { { :repeat_interval => 10 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A repeat_interval value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A repeat_interval value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'repeat-times' do @@ -250,12 +250,12 @@ context 'set' do let(:command_opts) { { :repeat_times => 2 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A repeat_times value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A repeat_times value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'max-time' do @@ -269,12 +269,12 @@ context 'set' do let(:command_opts) { { :max_time => 30 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A max_time value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A max_time value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'voice' do @@ -322,12 +322,12 @@ context "set to :speech" do let(:command_opts) { { :interrupt_on => :speech } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'An interrupt-on value of speech is unsupported.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'An interrupt-on value of speech is unsupported.' + original_command.response(0.1).should be == error end end end end @@ -354,21 +354,21 @@ let :command_options do { :ssml => ssml_doc }.merge(command_opts) end - let :command do + let :original_command do Punchblock::Component::Output.new command_options end describe 'ssml' do context 'unset' do let(:command_opts) { { :ssml => nil } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'An SSML document is required.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'An SSML document is required.' + original_command.response(0.1).should be == error end end context 'with a single audio SSML node' do let(:audio_filename) { 'http://foo.com/bar.mp3' } @@ -386,14 +386,36 @@ it 'should send a complete event when the file finishes playback' do def mock_call.send_agi_action!(*args, &block) block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1) end subject.execute - command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success + original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success end end + context 'with a single text node without spaces' do + let(:audio_filename) { 'tt-monkeys' } + let :command_options do + { + :ssml => RubySpeech::SSML.draw { string audio_filename } + } + end + + it 'should playback the audio file using STREAM FILE' do + expect_stream_file_with_options + subject.execute + end + + it 'should send a complete event when the file finishes playback' do + def mock_call.send_agi_action!(*args, &block) + block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1) + end + subject.execute + original_command.complete_event(0.1).reason.should be_a Punchblock::Component::Output::Complete::Success + end + end + context 'with multiple audio SSML nodes' do let(:audio_filename1) { 'http://foo.com/bar.mp3' } let(:audio_filename2) { 'http://foo.com/baz.mp3' } let :command_options do { @@ -421,30 +443,30 @@ it 'should send a complete event after the final file has finished playback' do def mock_call.send_agi_action!(*args, &block) block.call Punchblock::Component::Asterisk::AGI::Command::Complete::Success.new(:code => 200, :result => 1) end - command.expects(:add_event).once.with do |e| + original_command.expects(:add_event).once.with do |e| e.reason.should be_a Punchblock::Component::Output::Complete::Success end subject.execute end end context "with an SSML document containing elements other than <audio/>" do let :command_options do { :ssml => RubySpeech::SSML.draw do - string "FooBar" + string "Foo Bar" end } end it "should return an unrenderable document error" do subject.execute - error = ProtocolError.new 'unrenderable document error', 'The provided document could not be rendered.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered.' + original_command.response(0.1).should be == error end end end describe 'start-offset' do @@ -458,12 +480,12 @@ context 'set' do let(:command_opts) { { :start_offset => 10 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A start_offset value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A start_offset value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'start-paused' do @@ -477,12 +499,12 @@ context 'true' do let(:command_opts) { { :start_paused => true } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A start_paused value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A start_paused value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'repeat-interval' do @@ -496,12 +518,12 @@ context 'set' do let(:command_opts) { { :repeat_interval => 10 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A repeat_interval value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A repeat_interval value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'repeat-times' do @@ -515,12 +537,12 @@ context 'set' do let(:command_opts) { { :repeat_times => 2 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A repeat_times value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A repeat_times value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'max-time' do @@ -534,12 +556,12 @@ context 'set' do let(:command_opts) { { :max_time => 30 } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A max_time value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A max_time value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'voice' do @@ -553,12 +575,12 @@ context 'set' do let(:command_opts) { { :voice => 'alison' } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'A voice value is unsupported on Asterisk.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'A voice value is unsupported on Asterisk.' + original_command.response(0.1).should be == error end end end describe 'interrupt_on' do @@ -588,16 +610,68 @@ context "set to :speech" do let(:command_opts) { { :interrupt_on => :speech } } it "should return an error and not execute any actions" do subject.execute - error = ProtocolError.new 'option error', 'An interrupt-on value of speech is unsupported.' - command.response(0.1).should be == error + error = ProtocolError.new.setup 'option error', 'An interrupt-on value of speech is unsupported.' + original_command.response(0.1).should be == error end end end end end + + describe "#execute_command" do + context "with a command it does not understand" do + let(:command) { Punchblock::Component::Output::Pause.new } + + before { command.request! } + it "returns a ProtocolError response" do + subject.execute_command command + command.response(0.1).should be_a ProtocolError + end + end + + context "with a Stop command" do + let(:command) { Punchblock::Component::Stop.new } + let(:reason) { original_command.complete_event(5).reason } + let(:channel) { "SIP/1234-00000000" } + let :ami_event do + RubyAMI::Event.new('AsyncAGI').tap do |e| + e['SubEvent'] = "Start" + e['Channel'] = channel + e['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" + end + end + + before do + command.request! + original_command.request! + original_command.execute! + end + + it "sets the command response to true" do + mock_call.expects(:redirect_back!) + subject.execute_command command + command.response(0.1).should be == true + end + + it "sends the correct complete event" do + mock_call.expects(:redirect_back!) + subject.execute_command command + original_command.should_not be_complete + mock_call.process_ami_event! ami_event + reason.should be_a Punchblock::Event::Complete::Stop + original_command.should be_complete + end + + it "redirects the call by unjoining it" do + mock_call.expects(:redirect_back!).with(nil) + subject.execute_command command + end + end + end + end end end end end