# -*- coding: utf-8 -*-
require "test_helper"
module XmlContentTestSetup
def setup
super
@template_text = 'templateAFTER'
#
@document = Nokogiri::XML(doc_wrapper(@template_text))
@paragraph = @document.xpath('//w:p').first
@node = @paragraph.xpath('.//w:r').first.at_xpath('./w:t')
@env = Sablon::Environment.new(nil)
end
private
def doc_wrapper(content)
doc = <<-XML.gsub(/^\s+|\n/, '')
%s
XML
format(doc, content: content)
end
def assert_xml_equal(expected, document)
expected = Nokogiri::XML(doc_wrapper(expected)).to_xml(indent: 0, save_with: 0)
assert_equal expected, document.to_xml(indent: 0, save_with: 0)
end
end
class ContentTest < Sablon::TestCase
def test_can_build_content_objects
content = Sablon.content(:string, "a string")
assert_instance_of Sablon::Content::String, content
end
def test_raises_error_when_building_non_registered_type
e = assert_raises ArgumentError do
Sablon.content :nope, "this should not work"
end
assert_equal "Could not find Sablon content type with id 'nope'", e.message
end
def test_wraps_string_objects
content = Sablon::Content.wrap(67)
assert_instance_of Sablon::Content::String, content
assert_equal "67", content.string
end
def test_raises_an_error_if_no_wrapping_type_was_found
Sablon::Content.remove Sablon::Content::String
e = assert_raises ArgumentError do
Sablon::Content.wrap(43)
end
assert_equal "Could not find Sablon content type to wrap 43", e.message
ensure
Sablon::Content.register Sablon::Content::String
end
def test_does_not_wrap_content_objects
original_content = Sablon.content(:word_ml, "")
content = Sablon::Content.wrap(original_content)
assert_instance_of Sablon::Content::WordML, content
assert_equal original_content.object_id, content.object_id
end
end
class CustomContentTest < Sablon::TestCase
class MyContent < Struct.new(:numeric)
include Sablon::Content
def self.id; :custom end
def self.wraps?(value); Numeric === value end
def append_to(paragraph, display_node)
end
end
def setup
Sablon::Content.register MyContent
end
def teardown
Sablon::Content.remove MyContent
end
def test_can_build_custom_content
content = Sablon.content(:custom, 42)
assert_instance_of MyContent, content
end
def test_wraps_custom_content
content = Sablon::Content.wrap(31)
assert_instance_of MyContent, content
assert_equal 31, content.numeric
end
end
class ContentStringTest < Sablon::TestCase
include XmlContentTestSetup
def test_single_line_string
Sablon.content(:string, 'a normal string').append_to @paragraph, @node, @env
output = <<-XML.strip
templatea normal stringAFTER
XML
assert_xml_equal output, @document
end
def test_numeric_string
Sablon.content(:string, 42).append_to @paragraph, @node, @env
output = <<-XML.strip
template42AFTER
XML
assert_xml_equal output, @document
end
def test_string_with_newlines
Sablon.content(:string, "a\nmultiline\n\nstring").append_to @paragraph, @node, @env
output = <<-XML.gsub(/\s/, '')
template
a
multiline
string
AFTER
XML
assert_xml_equal output, @document
end
def test_blank_string
Sablon.content(:string, '').append_to @paragraph, @node, @env
assert_xml_equal @template_text, @document
end
end
class ContentWordMLTest < Sablon::TestCase
include XmlContentTestSetup
def test_blank_word_ml
# blank strings in word_ml are an odd corner case, they get treated
# as inline so the paragraph is retained but the display node is still
# removed with nothing being inserted in it's place. Nokogiri automatically
# collapsed the empty tag into a form.
Sablon.content(:word_ml, '').append_to @paragraph, @node, @env
assert_xml_equal "AFTER", @document
end
def test_plain_text_word_ml
# text isn't a valid child element of a w:p tag, so the whole paragraph
# gets replaced.
Sablon.content(:word_ml, "test").append_to @paragraph, @node, @env
assert_xml_equal "testAFTER", @document
end
def test_inserts_paragraph_word_ml_into_the_document
@word_ml = 'a '
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
output = <<-XML.gsub(/^\s+|\n/, '')
a
AFTER
XML
assert_xml_equal output, @document
end
def test_inserts_inline_word_ml_into_the_document
@word_ml = 'inline text '
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
output = <<-XML.gsub(/^\s+|\n/, '')
inline text
AFTER
XML
assert_xml_equal output, @document
end
def test_inserting_word_ml_multiple_times_into_same_paragraph
@word_ml = 'inline text '
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
@word_ml = 'inline text2 '
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
@word_ml = 'inline text3 '
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
# Only a single insertion should work because the node that we insert
# the content afer contains a merge field that needs removed. That means
# in the next two appends the @node variable doesn't exist on the document
# tree
output = <<-XML.gsub(/^\s+|\n/, '')
inline text
AFTER
XML
assert_xml_equal output, @document
end
def test_inserting_multiple_runs_into_same_paragraph
@word_ml = <<-XML.gsub(/^\s+|\n/, '')
inline text
inline text2
inline text3
XML
Sablon.content(:word_ml, @word_ml).append_to @paragraph, @node, @env
# This works because all three runs are added as a single insertion
# event
output = <<-XML.gsub(/^\s+|\n/, '')
inline text
inline text2
inline text3
AFTER
XML
assert_xml_equal output, @document
end
end
class ContentImageTest < Sablon::TestCase
def setup
base_path = Pathname.new(File.expand_path('../', __FILE__))
fixture_dir = base_path.join('fixtures')
@image_path = fixture_dir.join('images', 'r2d2.jpg')
@expected = Sablon::Content::Image.new(@image_path.to_s)
end
def test_inspect
assert_equal '#', @expected.inspect
#
# set some rid's and retest
@expected.rid_by_file['word/test.xml'] = 'rId1'
assert_equal '#"rId1"}>', @expected.inspect
end
def test_wraps_image_from_string_path
#
tested = Sablon.content(:image, @image_path.to_s)
assert_equal @expected, tested
end
def test_wraps_image_from_readable_object_that_can_be_basenamed
tested = Sablon.content(:image, open(@image_path.to_s, 'rb'))
assert_equal @expected, tested
end
def test_wraps_image_from_readable_object_with_filename_supplied
data = StringIO.new(IO.binread(@image_path.to_s))
tested = Sablon.content(:image, data, filename: File.basename(@image_path))
assert_equal @expected, tested
end
def test_wraps_readable_object_that_responds_to_filename
readable = Struct.new(:data, :filename) { alias read data }
#
readable = readable.new(IO.binread(@image_path.to_s), File.basename(@image_path))
tested = Sablon.content(:image, readable)
assert_equal @expected, tested
end
def test_raises_error_when_no_filename
data = StringIO.new(IO.binread(@image_path.to_s))
#
assert_raises ArgumentError do
Sablon.content(:image, data)
end
end
def test_width_conversion
img = Sablon.content(:image, @image_path.to_s, properties: {width: '1.0cm'})
assert_equal 360000, img.width
assert_nil img.height
end
def test_height_conversion
img = Sablon.content(:image, @image_path.to_s, properties: {height: '1.0in'})
assert_nil img.width
assert_equal 914400, img.height
end
def test_invalid_unit_conversion
img = Sablon.content(:image, @image_path.to_s, properties: {width: '100px'})
assert_raises ArgumentError do
img.width
end
end
end