# encoding: UTF-8
require 'spec_helper'
describe XmlWriteStream::YieldingWriter do
let(:stream) do
StringIO.new.tap do |io|
io.set_encoding(Encoding::UTF_8)
end
end
let(:stream_writer) do
XmlWriteStream::StatefulWriter.new(stream)
end
def utf8(str)
str.encode(Encoding::UTF_8)
end
describe '#write_header' do
it 'writes the header with default attributes' do
stream_writer.write_header
stream_writer.close
expect(stream.string).to eq(
utf8("\n")
)
end
it 'allows header attributes to be overwritten' do
stream_writer.write_header(version: '2.0')
stream_writer.close
expect(stream.string).to eq(
utf8("\n")
)
end
it 'raises an error if tags have already been written' do
stream_writer.open_tag('foo')
expect do
stream_writer.write_header
end.to raise_error(XmlWriteStream::InvalidHeaderPositionError)
end
end
describe '#open_single_line_tag' do
it 'writes a tag and its contents on a single line' do
stream_writer.open_single_line_tag('maytag')
stream_writer.write_text('foobar')
stream_writer.close_tag
expect(stream.string).to eq("foobar")
end
it 'works with nested tags' do
stream_writer.open_single_line_tag('maytag')
stream_writer.write_text('foobar')
stream_writer.open_single_line_tag('gutentag')
stream_writer.write_text('foobaz')
stream_writer.close_tag
stream_writer.close_tag
expect(stream.string).to eq(
"foobarfoobaz"
)
end
end
describe '#open_tag' do
it 'writes an opening tag' do
stream_writer.open_tag('maytag')
stream_writer.close
expect(stream.string).to eq(
utf8("\n")
)
end
it 'writes an opening tag with attributes' do
stream_writer.open_tag('maytag', type: 'washing_machine')
stream_writer.close
expect(stream.string).to eq(
utf8("\n")
)
end
it 'raises an error if one of the attribute keys is invalid' do
expect do
stream_writer.open_tag('maytag', '0foo' => '')
end.to raise_error(XmlWriteStream::InvalidAttributeKeyError)
end
it 'raises an error if the tag name is invalid' do
expect do
stream_writer.open_tag('9foo')
end.to raise_error(XmlWriteStream::InvalidTagNameError)
end
it 'allows digits and colons in the tag name' do
stream_writer.open_tag('foo9')
stream_writer.open_tag('bar:baz')
stream_writer.close
expect(stream.string).to eq(
utf8("\n \n \n")
)
end
it 'raises an error if the stream is already closed' do
stream_writer.close
expect do
stream_writer.open_tag('foo')
end.to raise_error(XmlWriteStream::EndOfStreamError)
end
end
describe '#close_tag' do
it 'closes the currently open tag' do
stream_writer.open_tag('maytag')
stream_writer.close_tag
expect(stream.string).to eq(
utf8("\n")
)
end
end
describe '#write_text' do
it 'writes escaped text by default' do
stream_writer.open_tag('places')
stream_writer.write_text("Alaska & Hawai'i")
stream_writer.close
expect(stream.string).to eq(
utf8("\n Alaska & Hawai'i\n")
)
end
it 'writes raw text if asked not to escape' do
stream_writer.open_tag('places')
stream_writer.write_text("Alaska & Hawai'i", escape: false)
stream_writer.close
expect(stream.string).to eq(
utf8("\n Alaska & Hawai'i\n")
)
end
it 'raises an error if no tag has been written yet' do
expect do
stream_writer.write_text('foo')
end.to raise_error(XmlWriteStream::NoTopLevelTagError)
end
it 'raises an error if the stream is already closed' do
stream_writer.close
expect do
stream_writer.write_text('foo')
end.to raise_error(XmlWriteStream::EndOfStreamError)
end
end
describe '#flush' do
it 'closes all open tags' do
stream_writer.open_tag('foo')
stream_writer.open_tag('bar')
stream_writer.open_tag('baz')
stream_writer.flush
expect(stream.string).to eq(
utf8("\n \n \n \n \n")
)
expect(stream).to_not be_closed
expect(stream_writer).to be_eos
end
end
describe '#close' do
it 'closes all open tags and closes the stream' do
stream_writer.open_tag('foo')
stream_writer.open_tag('bar')
stream_writer.open_tag('baz')
stream_writer.close
expect(stream.string).to eq(
utf8("\n \n \n \n \n")
)
expect(stream).to be_closed
expect(stream_writer).to be_eos
end
end
describe '#in_tag?' do
it 'returns true if currently writing a tag, false otherwise' do
expect(stream_writer).to_not be_in_tag
stream_writer.open_tag('foo')
expect(stream_writer).to be_in_tag
end
end
describe '#eos?' do
it 'returns true if the stream is closed, false if it is still open' do
expect(stream_writer).to_not be_eos
stream_writer.close
expect(stream_writer).to be_eos
end
end
end