# -*- coding: utf-8 -*- require "test_helper" require "support/document_xml_helper" require "support/xml_snippets" class ProcessorDocumentTest < Sablon::TestCase include DocumentXMLHelper include XMLSnippets TestHandler = Struct.new(:handles, :statement) do def handles?(*) handles end def build_statement(*) statement end end def setup super @processor = Sablon::Processor::Document @processor.instance_variable_set(:@default_field_handler, nil) end def teardown super @processor.instance_variable_set(:@default_field_handler, nil) end def test_register_field_handler test_handlers = {} handler = TestHandler.new(nil, nil) # @processor.stub(:field_handlers, test_handlers) do @processor.register_field_handler 'test', handler # assert @processor.field_handlers.keys.include?(:test), 'handler was not added to handlers hash' assert_equal handler, @processor.field_handlers[:test] # # try and re-register a handler handler2 = 'test' e = assert_raises(ArgumentError, 'Should not have been able to overwrite a handler using this method') do @processor.register_field_handler 'test', handler2 end # assert_equal "Handler named: 'test' already exists. Use `replace_field_handler` instead.", e.message assert_equal handler, @processor.field_handlers[:test], 'pre-existing handler should not have been changed' end end def test_register_default_field_handler handler = TestHandler.new(nil, nil) @processor.register_field_handler :default, handler # assert !@processor.field_handlers.keys.include?(:default), 'default handler should not get added to the handlers hash' assert_equal handler, @processor.default_field_handler # # try and re-register a handler handler2 = 'test' e = assert_raises(ArgumentError, 'Should not have been able to overwrite a handler using this method') do @processor.register_field_handler 'default', handler2 end # assert_equal "Handler named: 'default' already exists. Use `replace_field_handler` instead.", e.message assert_equal handler, @processor.default_field_handler, 'pre-existing default handler should not have been changed' end def test_remove_field_handler handler = TestHandler.new(nil, nil) test_handlers = { test: handler } # @processor.stub(:field_handlers, test_handlers) do removed = @processor.remove_field_handler 'test' # assert !@processor.field_handlers.keys.include?(:test), 'handler was not removed from handlers hash' assert_equal handler, removed, 'handler should have been returned after removal' # # try and remove a non-existant handler removed = @processor.remove_field_handler '_i_do_not_exist_' assert_nil removed, 'Removing a non-existant handler should just return nil' end end def test_remove_default_field_handler handler = TestHandler.new(nil, nil) @processor.instance_variable_set(:@default_field_handler, handler) # removed = @processor.remove_field_handler :default assert_equal handler, removed, 'default handler should have been returned after removal' # # try and remove the default handler again removed = @processor.remove_field_handler :default assert_nil removed, 'Removing a non-existant default handler should just return nil' end def test_replace_field_handler handler = TestHandler.new(nil, nil) handler2 = TestHandler.new(false, nil) test_handlers = { test: handler } # @processor.stub(:field_handlers, test_handlers) do assert @processor.field_handlers.keys.include?(:test), 'the test key has to already exist for this test to be meaningful' @processor.replace_field_handler :test, handler2 # assert @processor.field_handlers.keys.include?(:test), 'The test key remains in the hash' assert_equal handler2, @processor.field_handlers[:test], 'The handler was not replaced' end end def test_replace_default_field_handler handler = TestHandler.new(nil, nil) handler2 = TestHandler.new(false, nil) @processor.instance_variable_set(:@default_field_handler, handler) # @processor.replace_field_handler 'default', handler2 assert_equal handler2, @processor.default_field_handler, 'The default handler was not replaced' end def test_simple_field_replacement result = process(snippet("simple_field"), {"first_name" => "Jack"}) assert_equal "Hello! My Name is Jack , nice to meet you.", text(result) assert_xml_equal <<-document, result Hello! My Name is Jack , nice to meet you. document end def test_simple_field_replacement_with_nil result = process(snippet("simple_field"), {"first_name" => nil}) assert_equal "Hello! My Name is , nice to meet you.", text(result) assert_xml_equal <<-document, result Hello! My Name is , nice to meet you. document end def test_simple_field_with_styling_replacement result = process(snippet("simple_field_with_styling"), {"system_name" => "Sablon 1 million"}) assert_equal "Generated by Sablon 1 million", text(result) assert_xml_equal <<-document, result Generated by Sablon 1 million document end def test_context_can_contain_string_and_symbol_keys context = {"first_name" => "Jack", last_name: "Davis"} result = process(snippet("simple_fields"), context) assert_equal "Jack Davis", text(result) end def test_complex_field_replacement result = process(snippet("complex_field"), {"last_name" => "Zane"}) assert_equal "Hello! My Name is Zane , nice to meet you.", text(result) assert_xml_equal <<-document, result Hello! My Name is Zane , nice to meet you. document end def test_complex_field_replacement_with_split_field result = process(snippet("edited_complex_field"), {"first_name" => "Daniel"}) assert_equal "Hello! My Name is Daniel , nice to meet you.", text(result) assert_xml_equal <<-document, result Hello! My Name is Daniel , nice to meet you. document end def test_paragraph_block_replacement result = process(snippet("paragraph_loop"), {"technologies" => ["Ruby", "Rails"]}) assert_equal "Ruby Rails", text(result) assert_xml_equal <<-document, result Ruby Rails document end def test_paragraph_block_within_table_cell result = process(snippet("paragraph_loop_within_table_cell"), {"technologies" => ["Puppet", "Chef"]}) assert_equal "Puppet Chef", text(result) assert_xml_equal <<-document, result Puppet Chef document end def test_paragraph_block_within_empty_table_cell_and_blank_replacement result = process(snippet("paragraph_loop_within_table_cell"), {"technologies" => []}) assert_equal "", text(result) assert_xml_equal <<-document, result document end def test_adds_blank_paragraph_to_empty_table_cells result = process(snippet("corrupt_table"), {}) assert_xml_equal <<-document, result Hans 1. Chef document end def test_single_row_table_loop item = Struct.new(:index, :label, :rating) result = process(snippet("table_row_loop"), {"items" => [item.new("1.", "Milk", "***"), item.new("2.", "Sugar", "**")]}) assert_xml_equal <<-document, result 1. Milk *** 2. Sugar ** document end def test_loop_over_collection_convertable_to_an_enumerable style_collection = Class.new do def to_ary ["CSS", "SCSS", "LESS"] end end result = process(snippet("paragraph_loop"), {"technologies" => style_collection.new}) assert_equal "CSS SCSS LESS", text(result) end def test_loop_over_collection_not_convertable_to_an_enumerable_raises_error not_a_collection = Class.new {} assert_raises Sablon::ContextError do process(snippet("paragraph_loop"), {"technologies" => not_a_collection.new}) end end def test_loop_with_missing_variable_raises_error e = assert_raises Sablon::ContextError do process(snippet("paragraph_loop"), {}) end assert_equal "The expression «technologies» should evaluate to an enumerable but was: nil", e.message end def test_loop_with_missing_end_raises_error e = assert_raises Sablon::TemplateError do process(snippet("loop_without_ending"), {}) end assert_equal "Could not find end field for «technologies:each(technology)». Was looking for «technologies:endEach»", e.message end def test_loop_incrementing_unique_ids context = { fruits: %w[Apple Blueberry Cranberry Date].map { |i| { name: i } }, cars: %w[Silverado Serria Ram Tundra].map { |i| { name: i } } } # xml = Nokogiri::XML(process(snippet('loop_with_unique_ids'), context)) # # all unique ids should get incremented to stay unique ids = xml.xpath("//*[local-name() = 'docPr']").map { |n| n.attr('id') } assert_equal %w[1 2 3 4], ids # ids = xml.xpath("//*[local-name() = 'cNvPr']").map { |n| n.attr('id') } assert_equal %w[1 2 3 4], ids end def test_conditional_with_missing_end_raises_error e = assert_raises Sablon::TemplateError do process(snippet("conditional_without_ending"), {}) end assert_equal "Could not find end field for «middle_name:if». Was looking for «middle_name:endIf»", e.message end def test_multi_row_table_loop item = Struct.new(:index, :label, :body) context = {"foods" => [item.new("1.", "Milk", "Milk is a white liquid."), item.new("2.", "Sugar", "Sugar is the generalized name for carbohydrates.")]} result = process(snippet("table_multi_row_loop"), context) assert_equal "1. Milk Milk is a white liquid. 2. Sugar Sugar is the generalized name for carbohydrates.", text(result) end def test_conditional result = process(snippet("conditional"), {"middle_name" => "Michael"}) assert_equal "Anthony Michael Hall", text(result) result = process(snippet("conditional"), {"middle_name" => nil}) assert_equal "Anthony Hall", text(result) end def test_simple_field_conditional_inline result = process(snippet("conditional_inline"), {"middle_name" => true}) assert_equal "Anthony Michael Hall", text(result) end def test_complex_field_conditional_inline with_false = process(snippet("complex_field_inline_conditional"), {"boolean" => false}) assert_equal "ParagraphBefore Before After ParagraphAfter", text(with_false) with_true = process(snippet("complex_field_inline_conditional"), {"boolean" => true}) assert_equal "ParagraphBefore Before Content After ParagraphAfter", text(with_true) end def test_ignore_complex_field_spanning_multiple_paragraphs result = process(snippet("test_ignore_complex_field_spanning_multiple_paragraphs"), {"current_time" => '14:53'}) assert_equal "AUTOTEXT Header:Date \\* MERGEFORMAT Day Month Year 14:53", text(result) assert_xml_equal <<-document, result AUTOTEXT Header:Date \\* MERGEFORMAT Day Month Year 14:53 document end def test_conditional_with_predicate result = process(snippet("conditional_with_predicate"), {"body" => ""}) assert_equal "some content", text(result) result = process(snippet("conditional_with_predicate"), {"body" => "not empty"}) assert_equal "", text(result) end def test_conditional_with_elsif_else_clauses result = process(snippet("conditional_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: true, method_b: true)}) assert_xml_equal <<-document, result Method A was true document result = process(snippet("conditional_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: false, method_b: true)}) assert_xml_equal <<-document, result Method B was true document result = process(snippet("conditional_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: false, method_b: false)}) assert_xml_equal <<-document, result Method A and B were false document end def test_inline_conditional_with_elsif_else_clauses result = process(snippet("conditional_inline_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: true, method_b: true)}) assert_xml_equal <<-document, result Before Method A was true After document result = process(snippet("conditional_inline_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: false, method_b: true)}) assert_xml_equal <<-document, result Before Method B was true After document result = process(snippet("conditional_inline_with_elsif_else_clauses"), {'object' => OpenStruct.new(method_a: false, method_b: false)}) assert_xml_equal <<-document, result Before Method A and B were false After document end def test_comment result = process(snippet("comment"), {}) assert_equal "Before After", text(result) end def test_comment_block_and_comment_as_key result = process(snippet("comment_block_and_comment_as_key"), {comment: 'Contents of comment key'}) assert_xml_equal <<-document, result Before After Contents of comment key document end def test_image_replacement base_path = Pathname.new(File.expand_path("../../", __FILE__)) image = Sablon.content(:image, base_path + "fixtures/images/r2d2.jpg") result = process(snippet("image"), { "item" => { "image" => image } }) assert_xml_equal <<-document, result document end private def process(document, context) env = Sablon::Environment.new(MockTemplate.new, context) env.document.current_entry = 'word/document.xml' @processor.process(wrap(document), env).to_xml end end