File: parser_detection_test.rb

package info (click to toggle)
ruby-multi-xml 0.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 472 kB
  • sloc: ruby: 2,822; sh: 4; makefile: 2
file content (143 lines) | stat: -rw-r--r-- 4,610 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
require "test_helper"

# Shared setup/teardown for tests that modify MultiXml parser state
module ParserStateReset
  def setup
    @original_parser = MultiXml.instance_variable_get(:@parser)
  end

  def teardown
    if @original_parser
      MultiXml.instance_variable_set(:@parser, @original_parser)
    elsif MultiXml.instance_variable_defined?(:@parser)
      MultiXml.send(:remove_instance_variable, :@parser)
    end
  end
end

# Tests for find_loaded_parser method
class FindLoadedParserTest < Minitest::Test
  cover "MultiXml*"
  include ParserStateReset

  def test_returns_best_available_parser_when_defined
    assert_equal best_available_parser, MultiXml.send(:find_loaded_parser)
  end

  def test_returns_nokogiri_when_ox_and_libxml_not_defined
    with_hidden_consts(:Ox, :LibXML) { assert_equal :nokogiri, MultiXml.send(:find_loaded_parser) }
  end

  def test_returns_oga_when_only_oga_defined
    with_hidden_consts(:Ox, :LibXML, :Nokogiri) { assert_equal :oga, MultiXml.send(:find_loaded_parser) }
  end

  def test_returns_nil_when_no_parsers_defined
    with_hidden_consts(:Ox, :LibXML, :Nokogiri, :Oga) { assert_nil MultiXml.send(:find_loaded_parser) }
  end

  private

  def with_hidden_consts(*const_names)
    # Only hide constants that are actually defined
    existing = const_names.select { |name| Object.const_defined?(name) }
    saved = existing.to_h { |name| [name, Object.send(:remove_const, name)] }
    MultiXml.send(:remove_instance_variable, :@parser) if MultiXml.instance_variable_defined?(:@parser)
    yield
  ensure
    saved&.each { |name, value| Object.const_set(name, value) }
  end
end

# Tests for find_available_parser method
class FindAvailableParserTest < Minitest::Test
  cover "MultiXml*"

  def test_returns_symbol
    assert_kind_of Symbol, MultiXml.send(:find_available_parser)
  end

  def test_returns_first_loadable_parser
    assert_equal best_available_parser, MultiXml.send(:find_available_parser)
  end

  def test_returns_nil_when_no_parsers_available
    with_parser_preference([["nonexistent_1", :fake1], ["nonexistent_2", :fake2]]) do
      assert_nil MultiXml.send(:find_available_parser)
    end
  end

  def test_continues_after_load_error
    # Use nokogiri as fallback since it's available on all platforms
    with_parser_preference([["nonexistent_parser_gem", :nonexistent], ["nokogiri", :nokogiri]]) do
      assert_equal :nokogiri, MultiXml.send(:find_available_parser)
    end
  end

  private

  def with_parser_preference(preference)
    original = MultiXml::PARSER_PREFERENCE.dup
    MultiXml.send(:remove_const, :PARSER_PREFERENCE)
    MultiXml.const_set(:PARSER_PREFERENCE, preference)
    yield
  ensure
    MultiXml.send(:remove_const, :PARSER_PREFERENCE)
    MultiXml.const_set(:PARSER_PREFERENCE, original.freeze)
  end
end

# Tests for detect_parser method
class DetectParserTest < Minitest::Test
  cover "MultiXml*"
  include ParserStateReset

  def test_returns_loaded_parser_when_available
    assert_equal best_available_parser, MultiXml.send(:detect_parser)
  end

  def test_falls_back_to_find_available_when_loaded_returns_nil
    MultiXml.stub(:find_loaded_parser, nil) do
      assert_equal best_available_parser, MultiXml.send(:detect_parser)
    end
  end

  def test_uses_find_loaded_result_not_find_available
    MultiXml.stub(:find_available_parser, :rexml) do
      assert_equal best_available_parser, MultiXml.send(:detect_parser)
    end
  end

  def test_raises_when_no_parser_available
    with_no_parsers_available do
      assert_raises(MultiXml::NoParserError) { MultiXml.send(:detect_parser) }
    end
  end

  private

  def with_no_parsers_available
    # Only remove constants that are actually defined
    existing = %i[Ox LibXML Nokogiri Oga].select { |n| Object.const_defined?(n) }
    saved_consts = existing.to_h { |n| [n, Object.send(:remove_const, n)] }
    saved_pref = MultiXml::PARSER_PREFERENCE
    MultiXml.send(:remove_const, :PARSER_PREFERENCE)
    MultiXml.const_set(:PARSER_PREFERENCE, [["nonexistent", :fake]])
    yield
  ensure
    saved_consts.each { |name, value| Object.const_set(name, value) }
    MultiXml.send(:remove_const, :PARSER_PREFERENCE)
    MultiXml.const_set(:PARSER_PREFERENCE, saved_pref)
  end
end

# Tests for raise_no_parser_error method
class RaiseNoParserErrorTest < Minitest::Test
  cover "MultiXml*"

  def test_raises_no_parser_error_with_helpful_message
    error = assert_raises(MultiXml::NoParserError) { MultiXml.send(:raise_no_parser_error) }
    assert_match(/No XML parser detected/, error.message)
    assert_match(/ox/, error.message)
  end
end