nokogiri 1.7.2 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.cross_rubies +4 -4
  3. data/.travis.yml +43 -24
  4. data/CHANGELOG.md +54 -6
  5. data/Gemfile +8 -7
  6. data/Gemfile-libxml-ruby +3 -0
  7. data/LICENSE-DEPENDENCIES.md +1612 -0
  8. data/{LICENSE.txt → LICENSE.md} +1 -1
  9. data/Manifest.txt +5 -8
  10. data/README.md +8 -5
  11. data/Rakefile +15 -31
  12. data/appveyor.yml +2 -0
  13. data/dependencies.yml +12 -7
  14. data/ext/nokogiri/extconf.rb +12 -17
  15. data/ext/nokogiri/nokogiri.h +0 -10
  16. data/ext/nokogiri/xml_attr.c +12 -8
  17. data/ext/nokogiri/xml_node.c +17 -14
  18. data/ext/nokogiri/xml_sax_push_parser.c +56 -12
  19. data/lib/nokogiri/html/sax/parser.rb +10 -0
  20. data/lib/nokogiri/version.rb +5 -4
  21. data/lib/nokogiri/xml/document.rb +9 -9
  22. data/lib/nokogiri/xml/node.rb +7 -7
  23. data/lib/nokogiri/xml/node_set.rb +12 -7
  24. data/lib/nokogiri/xml/sax/parser.rb +6 -7
  25. data/lib/nokogiri/xml/searchable.rb +34 -25
  26. data/lib/nokogiri/xml/syntax_error.rb +24 -1
  27. data/test/decorators/test_slop.rb +4 -1
  28. data/test/helper.rb +10 -0
  29. data/test/html/sax/test_parser.rb +27 -0
  30. data/test/html/test_document.rb +12 -1
  31. data/test/html/test_document_encoding.rb +1 -3
  32. data/test/html/test_document_fragment.rb +3 -0
  33. data/test/xml/sax/test_push_parser.rb +48 -0
  34. data/test/xml/test_attr.rb +7 -0
  35. data/test/xml/test_document.rb +1 -1
  36. data/test/xml/test_document_fragment.rb +27 -0
  37. data/test/xml/test_entity_reference.rb +2 -2
  38. data/test/xml/test_node.rb +12 -15
  39. data/test/xml/test_node_reparenting.rb +14 -0
  40. data/test/xml/test_node_set.rb +8 -6
  41. data/test/xml/test_reader.rb +19 -0
  42. data/test/xml/test_syntax_error.rb +21 -15
  43. data/test/xml/test_unparented_node.rb +54 -11
  44. data/test/xml/test_xpath.rb +23 -6
  45. metadata +31 -19
  46. data/suppressions/nokogiri_ree-1.8.7.358.supp +0 -61
  47. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  48. data/suppressions/nokogiri_ruby-1.9.2.320.supp +0 -28
  49. data/suppressions/nokogiri_ruby-1.9.3.327.supp +0 -28
  50. data/test_all +0 -105
@@ -7,7 +7,17 @@ require 'tempfile'
7
7
  require 'pp'
8
8
 
9
9
  require 'nokogiri'
10
+
10
11
  if ENV['TEST_NOKOGIRI_WITH_LIBXML_RUBY']
12
+ #
13
+ # if you'd like to test with the libxml-ruby gem loaded, it's
14
+ # recommended that you set
15
+ #
16
+ # BUNDLE_GEMFILE=Gemfile-libxml-ruby
17
+ #
18
+ # which will a) bundle that gem, and b) set the appropriate env var to
19
+ # trigger this block
20
+ #
11
21
  require 'libxml'
12
22
  warn "#{__FILE__}:#{__LINE__}: loaded libxml-ruby '#{LibXML::XML::VERSION}'"
13
23
  end
@@ -132,6 +132,33 @@ module Nokogiri
132
132
  ], @parser.document.start_elements
133
133
  end
134
134
 
135
+ HTML_WITH_BR_TAG = <<-EOF
136
+ <html>
137
+ <head></head>
138
+ <body>
139
+ <div>
140
+ hello
141
+ <br>
142
+ </div>
143
+
144
+ <div>
145
+ hello again
146
+ </div>
147
+ </body>
148
+ </html>
149
+ EOF
150
+
151
+ def test_parsing_dom_error_from_string
152
+ @parser.parse(HTML_WITH_BR_TAG)
153
+ assert_equal 6, @parser.document.start_elements.length
154
+ end
155
+
156
+ def test_parsing_dom_error_from_io
157
+ @parser.parse(StringIO.new(HTML_WITH_BR_TAG))
158
+ assert_equal 6, @parser.document.start_elements.length
159
+ end
160
+
161
+
135
162
  def test_empty_processing_instruction
136
163
  @parser.parse_memory("<strong>this will segfault<?strong>")
137
164
  end
@@ -15,7 +15,7 @@ module Nokogiri
15
15
  end
16
16
 
17
17
  def test_does_not_fail_with_illformatted_html
18
- doc = Nokogiri::HTML('"</html>";'.force_encoding(Encoding::BINARY))
18
+ doc = Nokogiri::HTML('"</html>";'.dup.force_encoding(Encoding::BINARY))
19
19
  assert_not_nil doc
20
20
  end
21
21
 
@@ -696,6 +696,17 @@ eohtml
696
696
  node = html.xpath("//style").first
697
697
  assert_equal("tr > div { display:block; }", node.inner_html)
698
698
  end
699
+
700
+ it "does not fail when converting to_html using explicit encoding" do
701
+ html_fragment=<<-eos
702
+ <img width="16" height="16" src="images/icon.gif" border="0" alt="Inactive hide details for &quot;User&quot; ---19/05/2015 12:55:29---Provvediamo subito nell&#8217;integrare">
703
+ eos
704
+ doc = Nokogiri::HTML(html_fragment, nil, 'ISO-8859-1')
705
+ html = doc.to_html
706
+ assert html.index("src=\"images/icon.gif\"")
707
+ assert_equal 'ISO-8859-1', html.encoding.name
708
+ end
709
+
699
710
  end
700
711
  end
701
712
  end
@@ -128,9 +128,7 @@ module Nokogiri
128
128
  assert_equal(title, doc_from_string_enc.at('//title/text()').text)
129
129
  assert_equal(title, doc_from_string.at('//title/text()').text)
130
130
  assert_equal(title, doc_from_file_enc.at('//title/text()').text)
131
- unless Nokogiri.jruby? && file == ENCODING_HTML_FILE
132
- assert_equal(title, doc_from_file.at('//title/text()').text)
133
- end
131
+ assert_equal(title, doc_from_file.at('//title/text()').text)
134
132
 
135
133
  evil = (0..72).map { |i| '超' * i + '悪い事を構想中。' }
136
134
 
@@ -234,6 +234,9 @@ module Nokogiri
234
234
  end
235
235
 
236
236
  def test_element_children_counts
237
+ if Nokogiri.uses_libxml? && Nokogiri::VERSION_INFO['libxml']['loaded'] <= "2.9.1"
238
+ skip "#elements doesn't work in 2.9.1, see 1793a5a for history"
239
+ end
237
240
  doc = Nokogiri::HTML::DocumentFragment.parse(" <div> </div>\n ")
238
241
  assert_equal 1, doc.element_children.count
239
242
  end
@@ -151,6 +151,54 @@ module Nokogiri
151
151
  assert_equal "Gau\337", @parser.document.data.join
152
152
  assert_equal [["r"]], @parser.document.end_elements
153
153
  end
154
+
155
+ def test_replace_entities_attribute_behavior
156
+ if Nokogiri.uses_libxml?
157
+ # initially false
158
+ assert_equal false, @parser.replace_entities
159
+
160
+ # can be set to true
161
+ @parser.replace_entities = true
162
+ assert_equal true, @parser.replace_entities
163
+
164
+ # can be set to false
165
+ @parser.replace_entities = false
166
+ assert_equal false, @parser.replace_entities
167
+ else
168
+ # initially true
169
+ assert_equal true, @parser.replace_entities
170
+
171
+ # ignore attempts to set to false
172
+ @parser.replace_entities = false # TODO: should we raise an exception here?
173
+ assert_equal true, @parser.replace_entities
174
+ end
175
+ end
176
+
177
+ def test_untouched_entities
178
+ skip("entities are always replaced in pure Java version") if Nokogiri.jruby?
179
+ @parser.<<(<<-eoxml)
180
+ <p id="asdf&amp;asdf">
181
+ <!-- This is a comment -->
182
+ Paragraph 1 &amp; 2
183
+ </p>
184
+ eoxml
185
+ @parser.finish
186
+ assert_equal [["p", [["id", "asdf&#38;asdf"]]]], @parser.document.start_elements
187
+ assert_equal "Paragraph 1 & 2", @parser.document.data.join.strip
188
+ end
189
+
190
+ def test_replaced_entities
191
+ @parser.replace_entities = true
192
+ @parser.<<(<<-eoxml)
193
+ <p id="asdf&amp;asdf">
194
+ <!-- This is a comment -->
195
+ Paragraph 1 &amp; 2
196
+ </p>
197
+ eoxml
198
+ @parser.finish
199
+ assert_equal [["p", [["id", "asdf&asdf"]]]], @parser.document.start_elements
200
+ assert_equal "Paragraph 1 & 2", @parser.document.data.join.strip
201
+ end
154
202
  end
155
203
  end
156
204
  end
@@ -11,6 +11,13 @@ module Nokogiri
11
11
  }
12
12
  end
13
13
 
14
+ def test_new_raises_argerror_on_nondocument
15
+ document = Nokogiri::XML "<root><foo/></root>"
16
+ assert_raises ArgumentError do
17
+ Nokogiri::XML::Attr.new document.at_css("foo"), "bar"
18
+ end
19
+ end
20
+
14
21
  def test_content=
15
22
  xml = Nokogiri::XML.parse(File.read(XML_FILE), XML_FILE)
16
23
  address = xml.xpath('//address')[3]
@@ -221,7 +221,7 @@ module Nokogiri
221
221
  end
222
222
 
223
223
  def test_pp
224
- out = StringIO.new('')
224
+ out = StringIO.new(String.new)
225
225
  ::PP.pp @xml, out
226
226
  assert_operator out.string.length, :>, 0
227
227
  end
@@ -136,6 +136,23 @@ module Nokogiri
136
136
  assert_equal expected, search_xpath
137
137
  end
138
138
 
139
+ def test_fragment_css_search_with_whitespace_and_node_removal
140
+ # The same xml without leading whitespace in front of the first line
141
+ # does not expose the error. Putting both nodes on the same line
142
+ # instead also fixes the crash.
143
+ fragment = Nokogiri::XML::DocumentFragment.parse <<-EOXML
144
+ <p id="content">hi</p> x <!--y--> <p>another paragraph</p>
145
+ EOXML
146
+ children = fragment.css('p')
147
+ assert_equal 2, children.length
148
+ # removing the last node instead does not yield the error. Probably the
149
+ # node removal leaves around two consecutive text nodes which make the
150
+ # css search crash?
151
+ children.first.remove
152
+ assert_equal 1, fragment.xpath('.//p | self::p').length
153
+ assert_equal 1, fragment.css('p').length
154
+ end
155
+
139
156
  def test_fragment_search_three_ways
140
157
  frag = Nokogiri::XML::Document.new.fragment '<p id="content">foo</p><p id="content">bar</p>'
141
158
  expected = frag.xpath('./*[@id = "content"]')
@@ -219,6 +236,16 @@ module Nokogiri
219
236
  assert fragment.children.respond_to?(:awesome!), fragment.children.class
220
237
  end
221
238
 
239
+ def test_decorator_is_applied_to_empty_set
240
+ x = Module.new do
241
+ def awesome!
242
+ end
243
+ end
244
+ util_decorate(@xml, x)
245
+ fragment = Nokogiri::XML::DocumentFragment.new(@xml, "")
246
+ assert fragment.children.respond_to?(:awesome!), fragment.children.class
247
+ end
248
+
222
249
  def test_add_node_to_doc_fragment_segfault
223
250
  frag = Nokogiri::XML::DocumentFragment.new(@xml, '<p>hello world</p>')
224
251
  Nokogiri::XML::Comment.new(frag,'moo')
@@ -141,7 +141,7 @@ EOF
141
141
  end
142
142
  assert_kind_of Nokogiri::XML::EntityReference, doc.xpath('//body').first.children.first
143
143
  if Nokogiri.uses_libxml?
144
- assert_equal ["Entity 'bar' not defined"], doc.errors.map(&:to_s)
144
+ assert_equal ["5:14: ERROR: Entity 'bar' not defined"], doc.errors.map(&:to_s)
145
145
  end
146
146
  end
147
147
 
@@ -159,7 +159,7 @@ EOF
159
159
  end
160
160
  assert_kind_of Nokogiri::XML::EntityReference, doc.xpath('//body').first.children.first
161
161
  if Nokogiri.uses_libxml?
162
- assert_equal ["Attempt to load network entity http://foo.bar.com/", "Entity 'bar' not defined"], doc.errors.map(&:to_s)
162
+ assert_equal ["ERROR: Attempt to load network entity http://foo.bar.com/", "4:34: ERROR: Entity 'bar' not defined"], doc.errors.map(&:to_s)
163
163
  else
164
164
  assert_equal ["Attempt to load network entity http://foo.bar.com/"], doc.errors.map(&:to_s)
165
165
  end
@@ -91,12 +91,14 @@ module Nokogiri
91
91
  assert_equal Nokogiri::XML::ParseOptions::DEFAULT_XML, options.to_i
92
92
  end
93
93
 
94
- # descriptive, not prescriptive.
95
- def test_parse_invalid_html_markup_results_in_empty_nodeset
96
- doc = Nokogiri::HTML("<html></html>")
97
- nodeset = doc.root.parse "<div><div>a</div><snippet>b</snippet></div>"
98
- assert_equal 1, doc.errors.length # "Tag snippet invalid"
94
+ def test_node_context_parsing_of_malformed_html_fragment
95
+ doc = HTML.parse "<html><body><div></div></body></html>"
96
+ context_node = doc.at_css "div"
97
+ nodeset = context_node.parse("<div </div>")
98
+
99
+ assert_equal 1, doc.errors.length
99
100
  assert_equal 1, nodeset.length
101
+ assert_equal "<div></div>", nodeset.to_s
100
102
  end
101
103
 
102
104
  def test_node_context_parsing_of_malformed_html_fragment_with_recover_is_corrected
@@ -105,9 +107,10 @@ module Nokogiri
105
107
  nodeset = context_node.parse("<div </div>") do |options|
106
108
  options.recover
107
109
  end
108
- assert_equal "<div></div>", nodeset.to_s
110
+
109
111
  assert_equal 1, doc.errors.length
110
112
  assert_equal 1, nodeset.length
113
+ assert_equal "<div></div>", nodeset.to_s
111
114
  end
112
115
 
113
116
  def test_node_context_parsing_of_malformed_html_fragment_without_recover_is_not_corrected
@@ -116,6 +119,7 @@ module Nokogiri
116
119
  nodeset = context_node.parse("<div </div>") do |options|
117
120
  options.strict
118
121
  end
122
+
119
123
  assert_equal 1, doc.errors.length
120
124
  assert_equal 0, nodeset.length
121
125
  end
@@ -125,7 +129,7 @@ module Nokogiri
125
129
  @xml.root.parse('<hello>')
126
130
  assert(error_count < @xml.errors.length, "errors should have increased")
127
131
  end
128
-
132
+
129
133
  def test_parse_error_on_fragment_with_empty_document
130
134
  doc = Document.new
131
135
  fragment = DocumentFragment.new(doc, '<foo><bar/></foo>')
@@ -690,14 +694,7 @@ module Nokogiri
690
694
  end
691
695
 
692
696
  def test_find_by_css_class_with_nonstandard_whitespace
693
- doc = Nokogiri::HTML '
694
- <html>
695
- <body>
696
- <div class="a
697
- b"></div>
698
- </body>
699
- </html>
700
- '
697
+ doc = Nokogiri::HTML "<div class='a\nb'></div>"
701
698
  assert_not_nil doc.at_css(".b")
702
699
  end
703
700
 
@@ -418,6 +418,20 @@ module Nokogiri
418
418
  assert_equal "text nodefoo <p></p> bar", xml.root.children.to_html
419
419
  end
420
420
 
421
+ it 'should append a text node before an existing non text node' do
422
+ xml = Nokogiri::XML %Q(<root><p>foo</p><p>bar</p></root>)
423
+ p = xml.at_css 'p'
424
+ p.add_next_sibling 'a'
425
+ assert_equal '<root><p>foo</p>a<p>bar</p></root>', xml.root.to_s
426
+ end
427
+
428
+ it 'should append a text node before an existing text node' do
429
+ xml = Nokogiri::XML %Q(<root><p>foo</p>after</root>)
430
+ p = xml.at_css 'p'
431
+ p.add_next_sibling 'x'
432
+ assert_equal '<root><p>foo</p>xafter</root>', xml.root.to_s
433
+ end
434
+
421
435
  describe "with a text node after" do
422
436
  it "should not defensively dup the 'after' text node" do
423
437
  xml = Nokogiri::XML %Q(<root>before<p></p>after</root>)
@@ -252,12 +252,14 @@ module Nokogiri
252
252
  assert_equal 2, node_set.first(2).length
253
253
  end
254
254
 
255
- def test_dup
256
- assert node_set = @xml.xpath('//employee')
257
- dup = node_set.dup
258
- assert_equal node_set.length, dup.length
259
- node_set.zip(dup).each do |a,b|
260
- assert_equal a, b
255
+ [:dup, :clone].each do |method_name|
256
+ define_method "test_#{method_name}" do
257
+ assert node_set = @xml.xpath('//employee')
258
+ duplicate = node_set.send(method_name)
259
+ assert_equal node_set.length, duplicate.length
260
+ node_set.zip(duplicate).each do |a,b|
261
+ assert_equal a, b
262
+ end
261
263
  end
262
264
  end
263
265
 
@@ -185,6 +185,25 @@ module Nokogiri
185
185
  assert 1, reader.errors.length
186
186
  end
187
187
 
188
+ def test_errors_is_an_array
189
+ reader = Nokogiri::XML::Reader(StringIO.new('&bogus;'))
190
+ assert_raises(SyntaxError) {
191
+ reader.read
192
+ }
193
+ assert_equal [SyntaxError], reader.errors.map(&:class)
194
+ end
195
+
196
+ def test_pushing_to_non_array_raises_TypeError
197
+ skip "TODO: JRuby ext does not internally call `errors`" if Nokogiri.jruby?
198
+ reader = Nokogiri::XML::Reader(StringIO.new('&bogus;'))
199
+ def reader.errors
200
+ 1
201
+ end
202
+ assert_raises(TypeError) {
203
+ reader.read
204
+ }
205
+ end
206
+
188
207
  def test_attributes?
189
208
  reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
190
209
  <x xmlns:tenderlove='http://tenderlovemaking.com/'>
@@ -8,23 +8,29 @@ module Nokogiri
8
8
  assert_equal 'hello', error.message
9
9
  end
10
10
 
11
- def test_pushing_to_array
12
- reader = Nokogiri::XML::Reader(StringIO.new('&bogus;'))
13
- assert_raises(SyntaxError) {
14
- reader.read
15
- }
16
- assert_equal [SyntaxError], reader.errors.map(&:class) unless Nokogiri.jruby? # needs investigation
11
+ def test_line_column_level_libxml
12
+ skip unless Nokogiri.uses_libxml?
13
+
14
+ bad_doc = Nokogiri::XML('test')
15
+ error = bad_doc.errors.first
16
+
17
+ assert_equal "1:1: FATAL: Start tag expected, '<' not found", error.message
18
+ assert_equal 1, error.line
19
+ assert_equal 1, error.column
20
+ assert_equal 3, error.level
17
21
  end
18
22
 
19
- def test_pushing_to_non_array
20
- reader = Nokogiri::XML::Reader(StringIO.new('&bogus;'))
21
- def reader.errors
22
- 1
23
- end
24
- assert_raises(TypeError) {
25
- reader.read
26
- }
27
- end unless Nokogiri.jruby? # which does not internally call `errors`
23
+ def test_line_column_level_jruby
24
+ skip unless Nokogiri.jruby?
25
+
26
+ bad_doc = Nokogiri::XML('<root>test</bar>')
27
+ error = bad_doc.errors.first
28
+
29
+ assert_equal "The element type \"root\" must be terminated by the matching end-tag \"</root>\".", error.message
30
+ assert_equal nil, error.line
31
+ assert_equal nil, error.column
32
+ assert_equal nil, error.level
33
+ end
28
34
  end
29
35
  end
30
36
  end
@@ -223,12 +223,12 @@ module Nokogiri
223
223
  right_space.add_next_sibling(left_space)
224
224
  assert_equal left_space, right_space
225
225
  end
226
-
226
+
227
227
  def test_add_next_sibling_to_root_raises_exception
228
228
  xml = Nokogiri::XML(<<-eoxml)
229
229
  <root />
230
230
  eoxml
231
-
231
+
232
232
  node = Nokogiri::XML::Node.new 'child', xml
233
233
 
234
234
  assert_raise(ArgumentError) do
@@ -240,7 +240,7 @@ module Nokogiri
240
240
  xml = Nokogiri::XML(<<-eoxml)
241
241
  <root />
242
242
  eoxml
243
-
243
+
244
244
  node = Nokogiri::XML::Node.new 'child', xml
245
245
 
246
246
  assert_raise(ArgumentError) do
@@ -248,17 +248,60 @@ module Nokogiri
248
248
  end
249
249
  end
250
250
 
251
- def test_add_pi_as_previous_and_next_sibling_to_root_is_ok
251
+ def test_document_root_can_have_a_comment_sibling_via_add_child
252
+ doc = Nokogiri::XML "<root>foo</root>"
253
+ comment = Nokogiri::XML::Comment.new(doc, "this is a comment")
254
+ doc.add_child comment
255
+ assert_equal [doc.root, comment], doc.children.to_a
256
+ end
257
+
258
+ def test_document_root_can_have_a_comment_sibling_via_prepend_child
259
+ doc = Nokogiri::XML "<root>foo</root>"
260
+ comment = Nokogiri::XML::Comment.new(doc, "this is a comment")
261
+ doc.prepend_child comment
262
+ assert_equal [comment, doc.root], doc.children.to_a
263
+ end
264
+
265
+ def test_document_root_can_have_a_comment_sibling_via_add_next_sibling
266
+ doc = Nokogiri::XML "<root>foo</root>"
267
+ comment = Nokogiri::XML::Comment.new(doc, "this is a comment")
268
+ doc.root.add_next_sibling comment
269
+ assert_equal [doc.root, comment], doc.children.to_a
270
+ end
271
+
272
+ def test_document_root_can_have_a_comment_sibling_via_add_previous_sibling
273
+ doc = Nokogiri::XML "<root>foo</root>"
274
+ comment = Nokogiri::XML::Comment.new(doc, "this is a comment")
275
+ doc.root.add_previous_sibling comment
276
+ assert_equal [comment, doc.root], doc.children.to_a
277
+ end
278
+
279
+ def test_document_root_can_have_a_processing_instruction_sibling_via_add_child
252
280
  doc = Nokogiri::XML "<root>foo</root>"
253
281
  pi = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", %q{type="text/xsl" href="foo.xsl"})
254
- doc.root.add_previous_sibling pi
255
- expected_doc = %Q{<?xml version="1.0"?>\n<?xml-stylesheet type="text/xsl" href="foo.xsl"?>\n<root>foo</root>}
256
- assert_includes doc.to_xml, expected_doc
282
+ doc.add_child pi
283
+ assert_equal [doc.root, pi], doc.children.to_a
284
+ end
285
+
286
+ def test_document_root_can_have_a_processing_instruction_sibling_via_prepend_child
287
+ doc = Nokogiri::XML "<root>foo</root>"
288
+ pi = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", %q{type="text/xsl" href="foo.xsl"})
289
+ doc.prepend_child pi
290
+ assert_equal [pi, doc.root], doc.children.to_a
291
+ end
257
292
 
258
- pi2 = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", %q{type="text/xsl" href="foo2.xsl"})
259
- pi.add_next_sibling pi2
260
- expected_doc = %Q{<?xml version="1.0"?>\n<?xml-stylesheet type="text/xsl" href="foo.xsl"?>\n<?xml-stylesheet type="text/xsl" href="foo2.xsl"?>\n<root>foo</root>}
261
- assert_includes doc.to_xml, expected_doc
293
+ def test_document_root_can_have_a_processing_instruction_sibling_via_add_next_sibling
294
+ doc = Nokogiri::XML "<root>foo</root>"
295
+ pi = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", %q{type="text/xsl" href="foo.xsl"})
296
+ doc.root.add_next_sibling pi
297
+ assert_equal [doc.root, pi], doc.children.to_a
298
+ end
299
+
300
+ def test_document_root_can_have_a_processing_instruction_sibling_via_add_previous_sibling
301
+ doc = Nokogiri::XML "<root>foo</root>"
302
+ pi = Nokogiri::XML::ProcessingInstruction.new(doc, "xml-stylesheet", %q{type="text/xsl" href="foo.xsl"})
303
+ doc.root.add_previous_sibling pi
304
+ assert_equal [pi, doc.root], doc.children.to_a
262
305
  end
263
306
 
264
307
  def test_find_by_css_with_tilde_eql