# frozen_string_literal: true
require_relative '../../spec_helper'
require 'ostruct'
require 'base64'
module Aws
module Xml
describe DocBuilder do
let(:result) { String.new }
let(:options) { { target: result, indent: '' } }
let(:xml) { DocBuilder.new(options) }
it 'creates empty xml documents' do
xml.node('Xml')
expect(result).to eq('')
end
it 'nests elements' do
xml.node('xml') do
xml.node('element')
end
expect(result).to eq('')
end
it 'nests elements deeply' do
xml.node('xml') do
xml.node('a') do
xml.node('b') do
xml.node('c')
end
end
end
expect(result).to eq('')
end
it 'supports flat elements with nested elements' do
xml.node('xml') do
xml.node('a') do
xml.node('b')
end
xml.node('c')
end
expect(result).to eq('')
end
it 'accepts element values' do
xml.node('xml') do
xml.node('element', 'value')
end
expect(result).to eq('value')
end
it 'accepts element attributes' do
xml.node('xml') do
xml.node('el', abc: 123, mno: 'xyz')
end
expect(result).to eq('')
end
it 'accepts element values and attributes at the same time' do
xml.node('xml') do
xml.node('el', 'value', abc: 'xyz')
end
expect(result).to eq('value')
end
it 'accepts attributes on outer elements' do
xml.node('xml', xmlns: 'abc') do
xml.node('out', a: 'b') do
xml.node('c')
end
end
expect(result).to eq('')
end
it 'escapes attribute values and element text' do
xml.node('xml', xmlns: 'a"b') do
xml.node('this & that')
end
expect(result).to eq('')
end
it 'escapes carriage return in attributes' do
xml.node('xml', key: "my\rkey")
expect(result).to include("my
key")
end
context 'End Of Line Characters' do
# human readable input is tricky for these - so use a base64 encoded
# string to ensure we get exactly what should be tested
it 'encodes line feeds' do
# "\n \n"
input = Base64.decode64('CiAK').force_encoding('utf-8')
xml.node('xml', input)
expect(result).to include('
')
end
it 'encodes line feeds and carriage returns' do
# "a\r\n b\n c\r"
input = Base64.decode64('YQ0KIGIKIGMN').force_encoding('utf-8')
xml.node('xml', input)
expect(result).to include('a
b
c
')
end
it 'encodes next lines' do
# "a\r\u0085 b\u0085"
input = Base64.decode64('YQ3ChSBiwoU=').force_encoding('utf-8')
xml.node('xml', input)
expect(result).to include('a
b
')
end
it 'encodes line separators' do
# "a\r\u2028 b\u0085 c\u2028"
input = Base64.decode64('YQ3igKggYsKFIGPigKg=').force_encoding('utf-8')
xml.node('xml', input)
expect(result).to include('a
b
c
')
end
end
it 'accepts :indent and initial :pad options' do
options[:indent] = ' '
options[:pad] = ' ' * 5
xml.node('xml', xmlns: 'http://example.com') do
xml.node('empty')
xml.node('attributes', a: 'b', c: 'd')
xml.node('value', 'content')
xml.node('both', 'content', m: 'n')
xml.node('branch') do
xml.node('leaf')
xml.node('branch') do
xml.node('leaf', 'abc')
xml.node('leaf', 'mno')
end
xml.node('branch') do
xml.node('leaf', 'xyz')
end
xml.node('leaf')
end
end
expect(result).to eq(<<-XML)
content
content
abc
mno
xyz
XML
end
it 'can build xml to any object that responds to #<<' do
options[:indent] = ' '
options[:pad] = ' ' * 5
options[:target] = []
xml.node('xml') do
xml.node('el', 'value')
end
expect(xml.target.join).to eq(<<-XML)
value
XML
end
end
end
end