spec/punchblock/component/output_spec.rb in punchblock-1.9.4 vs spec/punchblock/component/output_spec.rb in punchblock-2.0.0.beta1
- old
+ new
@@ -4,11 +4,11 @@
module Punchblock
module Component
describe Output do
it 'registers itself' do
- RayoNode.class_from_registration(:output, 'urn:xmpp:rayo:output:1').should be == Output
+ RayoNode.class_from_registration(:output, 'urn:xmpp:rayo:output:1').should be == described_class
end
describe 'default values' do
its(:interrupt_on) { should be nil }
its(:start_offset) { should be nil }
@@ -16,128 +16,255 @@
its(:repeat_interval) { should be nil }
its(:repeat_times) { should be nil }
its(:max_time) { should be nil }
its(:voice) { should be nil }
its(:renderer) { should be nil }
+ its(:render_documents) { should be == [] }
end
+ def ssml_doc(mode = :ordinal)
+ RubySpeech::SSML.draw do
+ say_as(:interpret_as => mode) { string '100' }
+ end
+ end
+
describe "when setting options in initializer" do
subject do
- Output.new :interrupt_on => :speech,
+ Output.new :interrupt_on => :voice,
:start_offset => 2000,
:start_paused => false,
:repeat_interval => 2000,
:repeat_times => 10,
:max_time => 30000,
:voice => 'allison',
- :renderer => 'swift'
+ :renderer => 'swift',
+ :render_document => {:value => ssml_doc}
end
- its(:interrupt_on) { should be == :speech }
+ its(:interrupt_on) { should be == :voice }
its(:start_offset) { should be == 2000 }
its(:start_paused) { should be == false }
its(:repeat_interval) { should be == 2000 }
its(:repeat_times) { should be == 10 }
its(:max_time) { should be == 30000 }
its(:voice) { should be == 'allison' }
its(:renderer) { should be == 'swift' }
+ its(:render_documents) { should be == [Output::Document.new(:value => ssml_doc)] }
+
+ context "using #ssml=" do
+ subject do
+ Output.new :ssml => ssml_doc
+ end
+
+ its(:render_documents) { should be == [Output::Document.new(:value => ssml_doc)] }
+ end
+
+ context "with multiple documents" do
+ subject do
+ Output.new :render_documents => [
+ {:value => ssml_doc},
+ {:value => ssml_doc(:cardinal)}
+ ]
+ end
+
+ its(:render_documents) { should be == [
+ Output::Document.new(:value => ssml_doc),
+ Output::Document.new(:value => ssml_doc(:cardinal))
+ ]}
+ end
+
+ context "with a urilist" do
+ subject do
+ Output.new render_document: {
+ content_type: 'text/uri-list',
+ value: Punchblock::URIList.new('http://example.com/hello.mp3')
+ }
+ end
+
+ its(:render_documents) { should be == [Output::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3'])] }
+
+ describe "exporting to Rayo" do
+ it "should export to XML that can be understood by its parser" do
+ puts subject.to_rayo.to_xml
+ new_instance = RayoNode.from_xml Nokogiri::XML(subject.to_rayo.to_xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root
+ new_instance.render_documents.should be == [Output::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3'])]
+ end
+ end
+ end
+
+ context "with a nil document" do
+ it "removes all documents" do
+ subject.render_document = nil
+ subject.render_documents.should == []
+ end
+ end
+
+ context "without any documents" do
+ subject { described_class.new }
+
+ its(:render_documents) { should == [] }
+ end
+
+ describe "exporting to Rayo" do
+ it "should export to XML that can be understood by its parser" do
+ new_instance = RayoNode.from_xml Nokogiri::XML(subject.to_rayo.to_xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root
+ new_instance.should be_instance_of described_class
+ new_instance.interrupt_on.should be == :voice
+ new_instance.start_offset.should be == 2000
+ new_instance.start_paused.should be == false
+ new_instance.repeat_interval.should be == 2000
+ new_instance.repeat_times.should be == 10
+ new_instance.max_time.should be == 30000
+ new_instance.voice.should be == 'allison'
+ new_instance.renderer.should be == 'swift'
+ new_instance.render_documents.should be == [Output::Document.new(:value => ssml_doc)]
+ end
+
+ it "should wrap the document value in CDATA" do
+ grammar_node = subject.to_rayo.at_xpath('ns:document', ns: described_class.registered_ns)
+ grammar_node.children.first.should be_a Nokogiri::XML::CDATA
+ end
+
+ it "should render to a parent node if supplied" do
+ doc = Nokogiri::XML::Document.new
+ parent = Nokogiri::XML::Node.new 'foo', doc
+ doc.root = parent
+ rayo_doc = subject.to_rayo(parent)
+ rayo_doc.should == parent
+ end
+ end
end
describe "from a stanza" do
let :stanza do
<<-MESSAGE
<output xmlns='urn:xmpp:rayo:output:1'
- interrupt-on='speech'
+ interrupt-on='voice'
start-offset='2000'
start-paused='false'
repeat-interval='2000'
repeat-times='10'
max-time='30000'
voice='allison'
- renderer='swift'>Hello world</output>
+ renderer='swift'>
+ <document content-type="application/ssml+xml">
+ <![CDATA[
+ <speak version="1.0"
+ xmlns="http://www.w3.org/2001/10/synthesis"
+ xml:lang="en-US">
+ <say-as interpret-as="ordinal">100</say-as>
+ </speak>
+ ]]>
+ </document>
+ <document content-type="application/ssml+xml">
+ <![CDATA[
+ <speak version="1.0"
+ xmlns="http://www.w3.org/2001/10/synthesis"
+ xml:lang="en-US">
+ <say-as interpret-as="ordinal">100</say-as>
+ </speak>
+ ]]>
+ </document>
+</output>
MESSAGE
end
- subject { RayoNode.import parse_stanza(stanza).root, '9f00061', '1' }
+ subject { RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
it { should be_instance_of Output }
- its(:interrupt_on) { should be == :speech }
+ its(:interrupt_on) { should be == :voice }
its(:start_offset) { should be == 2000 }
its(:start_paused) { should be == false }
its(:repeat_interval) { should be == 2000 }
its(:repeat_times) { should be == 10 }
its(:max_time) { should be == 30000 }
its(:voice) { should be == 'allison' }
its(:renderer) { should be == 'swift' }
- its(:text) { should be == 'Hello world' }
+ its(:render_documents) { should be == [Output::Document.new(:value => ssml_doc), Output::Document.new(:value => ssml_doc)] }
- context "with SSML" do
+ context "with a urilist" do
let :stanza do
<<-MESSAGE
-<output xmlns='urn:xmpp:rayo:output:1'
- interrupt-on='speech'
- start-offset='2000'
- start-paused='false'
- repeat-interval='2000'
- repeat-times='10'
- max-time='30000'
- voice='allison'
- renderer='swift'>
- <speak version="1.0"
- xmlns="http://www.w3.org/2001/10/synthesis"
- xml:lang="en-US">
- <say-as interpret-as="ordinal">100</say-as>
- </speak>
+<output xmlns='urn:xmpp:rayo:output:1'>
+ <document content-type="text/uri-list">
+ <![CDATA[
+ http://example.com/hello.mp3
+ http://example.com/goodbye.mp3
+ ]]>
+ </document>
</output>
MESSAGE
end
- def ssml_doc(mode = :ordinal)
- RubySpeech::SSML.draw do
- say_as(:interpret_as => mode) { string '100' }
- end
- end
-
- its(:ssml) { should be == ssml_doc }
+ its(:render_documents) { should be == [Output::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'])] }
end
end
- describe "for text" do
- subject { Output.new :text => 'Once upon a time there was a message...', :voice => 'kate' }
+ describe Output::Document do
+ describe "when not passing a content type" do
+ subject { Output::Document.new :value => ssml_doc }
+ its(:content_type) { should be == 'application/ssml+xml' }
+ end
- its(:voice) { should be == 'kate' }
- its(:text) { should be == 'Once upon a time there was a message...' }
- end
+ describe 'with an SSML document' do
+ subject { Output::Document.new :value => ssml_doc, :content_type => 'application/ssml+xml' }
- describe "for SSML" do
- def ssml_doc(mode = :ordinal)
- RubySpeech::SSML.draw do
- say_as(:interpret_as => mode) { string '100' }
+ its(:content_type) { should be == 'application/ssml+xml' }
+
+ its(:value) { should be == ssml_doc }
+
+ describe "comparison" do
+ let(:document2) { Output::Document.new :value => ssml_doc }
+ let(:document3) { Output::Document.new :value => ssml_doc(:normal) }
+
+ it { should be == document2 }
+ it { should_not be == document3 }
end
end
- subject { Output.new :ssml => ssml_doc, :voice => 'kate' }
+ describe 'with a urilist' do
+ subject { Output::Document.new content_type: 'text/uri-list', value: Punchblock::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3') }
- its(:voice) { should be == 'kate' }
+ its(:value) { should be == Punchblock::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3') }
- its(:ssml) { should be == ssml_doc }
+ describe "comparison" do
+ let(:document2) { Output::Document.new content_type: 'text/uri-list', value: Punchblock::URIList.new('http://example.com/hello.mp3', 'http://example.com/goodbye.mp3') }
+ let(:document3) { Output::Document.new value: '<speak xmlns="http://www.w3.org/2001/10/synthesis" version="1.0" xml:lang="en-US"><say-as interpret-as="ordinal">100</say-as></speak>' }
+ let(:document4) { Output::Document.new content_type: 'text/uri-list', value: Punchblock::URIList.new('http://example.com/hello.mp3') }
+ let(:document5) { Output::Document.new content_type: 'text/uri-list', value: Punchblock::URIList.new('http://example.com/goodbye.mp3', 'http://example.com/hello.mp3') }
- describe "comparison" do
- let(:output2) { Output.new :ssml => '<speak xmlns="http://www.w3.org/2001/10/synthesis" version="1.0" xml:lang="en-US"><say-as interpret-as="ordinal">100</say-as></speak>', :voice => 'kate' }
- let(:output3) { Output.new :ssml => ssml_doc, :voice => 'kate' }
- let(:output4) { Output.new :ssml => ssml_doc(:normal), :voice => 'kate' }
+ it { should be == document2 }
+ it { should_not be == document3 }
+ it { should_not be == document4 }
+ it { should_not be == document5 }
+ end
+ end
- it { should be == output2 }
- it { should be == output3 }
- it { should_not be == output4 }
+ describe 'with a document reference by URL' do
+ let(:url) { 'http://foo.com/bar.grxml' }
+
+ subject { Output::Document.new :url => url }
+
+ its(:url) { should be == url }
+ its(:content_type) { should be nil}
+
+ describe "comparison" do
+ it "should be the same with the same url" do
+ Output::Document.new(:url => url).should be == Output::Document.new(:url => url)
+ end
+
+ it "should be different with a different url" do
+ Output::Document.new(:url => url).should_not be == Output::Document.new(:url => 'http://doo.com/dah')
+ end
+ end
end
end
describe "actions" do
- let(:mock_client) { mock 'Client' }
- let(:command) { Output.new :text => 'Once upon a time there was a message...', :voice => 'kate' }
+ let(:mock_client) { double 'Client' }
+ let(:command) { described_class.new }
before do
command.component_id = 'abc123'
command.target_call_id = '123abc'
command.client = mock_client
@@ -594,22 +721,27 @@
end
end
end
end
- describe Output::Complete::Success do
- let :stanza do
- <<-MESSAGE
+ {
+ Output::Complete::Finish => :finish,
+ Output::Complete::MaxTime => :'max-time',
+ }.each do |klass, element_name|
+ describe klass do
+ let :stanza do
+ <<-MESSAGE
<complete xmlns='urn:xmpp:rayo:ext:1'>
-<success xmlns='urn:xmpp:rayo:output:complete:1' />
+<#{element_name} xmlns='urn:xmpp:rayo:output:complete:1' />
</complete>
- MESSAGE
- end
+ MESSAGE
+ end
- subject { RayoNode.import(parse_stanza(stanza).root).reason }
+ subject { RayoNode.from_xml(parse_stanza(stanza).root).reason }
- it { should be_instance_of Output::Complete::Success }
+ it { should be_instance_of klass }
- its(:name) { should be == :success }
+ its(:name) { should be == element_name }
+ end
end
end
-end # Punchblock
+end