require 'test/test_helper' class TestDefinition < ActiveSupport::TestCase def assert_hash(opts, kvp) assert opts.hash? assert !opts.array? assert_equal kvp, {opts.hash.key.type => opts.hash.key.name, opts.hash.value.type => opts.hash.value.name} end def test_empty_array_means_as_array_for_text opts = ROXML::Definition.new(:authors, :as => []) assert opts.array? assert_equal :text, opts.type end def test_attr_in_array_means_as_array_for_attr opts = ROXML::Definition.new(:authors, :as => [], :from => :attr) assert opts.array? assert_equal :attr, opts.type end def test_block_shorthand_in_array_means_array opts = ROXML::Definition.new(:intarray, :as => [Integer]) assert opts.array? assert_equal :text, opts.type assert 1, opts.blocks.size end def test_required assert !ROXML::Definition.new(:author).required? assert ROXML::Definition.new(:author, :required => true).required? assert !ROXML::Definition.new(:author, :required => false).required? end def test_required_conflicts_with_else assert_raise ArgumentError do ROXML::Definition.new(:author, :required => true, :else => 'Johnny') end assert_nothing_raised do ROXML::Definition.new(:author, :required => false, :else => 'Johnny') end end def test_hash_of_attrs opts = ROXML::Definition.new(:attributes, :as => {:key => '@name', :value => '@value'}) assert_hash(opts, :attr => 'name', :attr => 'value') end def test_hash_with_attr_key_and_text_val opts = ROXML::Definition.new(:attributes, :as => {:key => '@name', :value => :value}) assert_hash(opts, :attr => 'name', :text => 'value') end def test_hash_with_string_class_for_type opts = ROXML::Definition.new(:attributes, :as => {:key => 'name', :value => 'value'}) assert_hash(opts, :text => 'name', :text => 'value') end def test_hash_with_attr_key_and_content_val opts = ROXML::Definition.new(:attributes, :as => {:key => '@name', :value => :content}) assert_hash(opts, :attr => 'name', :text => '.') end def test_hash_with_options opts = ROXML::Definition.new(:definitions, :as => {:key => '@dt', :value => '@dd'}, :in => :definitions, :from => 'definition') assert_hash(opts, :attr => 'dt', :attr => 'dd') assert_equal 'definition', opts.hash.wrapper end def test_no_block_shorthand_means_no_block assert ROXML::Definition.new(:count).blocks.empty? end def test_block_integer_shorthand assert_equal 3, ROXML::Definition.new(:count, :as => Integer).blocks.first['3'] end def test_block_float_shorthand assert_equal 3.1, ROXML::Definition.new(:count, :as => Float).blocks.first['3.1'] end def test_from_attr_is_supported opts = ROXML::Definition.new(:count, :from => :attr) assert_equal "count", opts.name assert_equal :attr, opts.type end def test_from_at_name_is_supported opts = ROXML::Definition.new(:count, :from => "@COUNT") assert_equal "COUNT", opts.name assert_equal :attr, opts.type end def test_multiple_shorthands_raises assert_raise ArgumentError do assert_deprecated do ROXML::Definition.new(:count, :as => [Float, Integer]) end end end def test_stacked_blocks assert_equal 2, ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size assert_equal 2, ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size end def test_block_shorthand_supports_bool assert_equal true, ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1") assert_equal [true, false, nil], ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call(["TrUe", "0", "328"]) end def test_block_shorthand_supports_integer assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(" ") assert_equal 792, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792") assert_raise ArgumentError do ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792.13") end assert_equal [792, 12, 328], ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(["792", "12", "328"]) end def test_block_shorthand_supports_float assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(" ") assert_equal 792.13, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("792.13") assert_equal 240.0, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("240") assert_equal [792.13, 240.0, 3.14], ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(["792.13", "240", "3.14"]) end def test_block_shorthand_supports_time assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ") assert_equal 31, ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min assert_equal [31, 0, 59], ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min) end def test_block_shorthand_supports_date assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Date).blocks.first.call(" ") assert_equal "1970-09-03", ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call("September 3rd, 1970").to_s assert_equal ["1970-09-03", "1776-07-04"], ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call(["September 3rd, 1970", "1776-07-04"]).map(&:to_s) end def test_block_shorthand_supports_datetime assert_equal nil, ROXML::Definition.new(:floatvalue, :as => DateTime).blocks.first.call(" ") assert_equal "1970-09-03T12:05:00+00:00", ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call("12:05pm, September 3rd, 1970").to_s assert_equal ["1970-09-03T12:05:00+00:00", "1700-05-22T15:00:00+00:00"], ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call(["12:05pm, September 3rd, 1970", "3:00pm, May 22, 1700"]).map(&:to_s) end def test_name_explicit_indicates_whether_from_option_is_present assert_equal true, ROXML::Definition.new(:element, :from => 'somewhere').name_explicit? assert_equal false, ROXML::Definition.new(:element).name_explicit? end def test_xpath_in_is_formed_properly opts = ROXML::Definition.new(:manufacturer, :in => './') assert_equal "manufacturer", opts.name assert_equal "./", opts.wrapper end def test_cdata_is_specifiable assert ROXML::Definition.new(:manufacturer, :cdata => true).cdata? end def test_as_supports_generic_roxml_types assert_equal RoxmlObject, ROXML::Definition.new(:type, :as => RoxmlObject).type end def test_as_supports_generic_roxml_types_in_arrays assert_equal RoxmlObject, ROXML::Definition.new(:types, :as => [RoxmlObject]).type end def test_default_works opts = ROXML::Definition.new(:missing, :else => true) assert_equal true, opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('')) end def test_default_works_for_arrays opts = ROXML::Definition.new(:missing, :as => []) assert_equal [], opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('')) end def test_default_works_for_recursive_objects opts = ROXML::Definition.new(:missing, :as => RecursiveObject, :else => false) assert_equal false, opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('')) end def test_content_is_accepted_as_from assert ROXML::Definition.new(:author, :from => :content).content? assert ROXML::Definition.new(:author, :from => '.').content? end def test_content_is_a_recognized_type opts = ROXML::Definition.new(:author, :from => :content) assert opts.content? assert_equal '.', opts.name assert_equal :text, opts.type end def test_content_symbol_as_target_is_translated_to_string opts = ROXML::Definition.new(:content, :from => :attr) assert_equal 'content', opts.name assert_equal :attr, opts.type end def test_attr_is_accepted_as_from assert_equal :attr, ROXML::Definition.new(:author, :from => :attr).type assert_equal :attr, ROXML::Definition.new(:author, :from => '@author').type end def test_attr_is_a_recognized_type opts = ROXML::Definition.new(:author, :from => :attr) assert_equal 'author', opts.name assert_equal :attr, opts.type end end class RecursiveObject include ROXML xml_reader :next, :as => RecursiveObject, :else => true end class RoxmlObject include ROXML end class HashDefinitionTest < ActiveSupport::TestCase def test_content_detected_as_from opts = ROXML::Definition.new(:hash, :as => {:key => :content, :value => :name}) assert_equal '.', opts.hash.key.name assert_equal :text, opts.hash.key.type end end