nokogiri 1.6.1 → 1.6.2.rc1

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 (93) hide show
  1. checksums.yaml +7 -7
  2. data/.editorconfig +17 -0
  3. data/.travis.yml +4 -6
  4. data/CHANGELOG.ja.rdoc +37 -8
  5. data/CHANGELOG.rdoc +48 -3
  6. data/Gemfile +3 -3
  7. data/Manifest.txt +57 -1
  8. data/README.ja.rdoc +22 -16
  9. data/README.rdoc +24 -19
  10. data/ROADMAP.md +1 -2
  11. data/Rakefile +161 -58
  12. data/build_all +56 -31
  13. data/dependencies.yml +3 -3
  14. data/ext/nokogiri/extconf.rb +379 -121
  15. data/ext/nokogiri/html_document.c +2 -2
  16. data/ext/nokogiri/nokogiri.c +6 -1
  17. data/ext/nokogiri/xml_document.c +5 -4
  18. data/ext/nokogiri/xml_node.c +11 -4
  19. data/ext/nokogiri/xml_reader.c +1 -1
  20. data/ext/nokogiri/xml_sax_parser_context.c +40 -0
  21. data/ext/nokogiri/xml_syntax_error.c +10 -5
  22. data/ext/nokogiri/xml_syntax_error.h +1 -1
  23. data/ext/nokogiri/xml_xpath_context.c +2 -14
  24. data/ext/nokogiri/xslt_stylesheet.c +1 -1
  25. data/lib/nokogiri.rb +31 -22
  26. data/lib/nokogiri/css/node.rb +0 -50
  27. data/lib/nokogiri/css/parser.rb +213 -218
  28. data/lib/nokogiri/css/parser.y +21 -30
  29. data/lib/nokogiri/css/xpath_visitor.rb +62 -14
  30. data/lib/nokogiri/html/document.rb +97 -18
  31. data/lib/nokogiri/html/sax/parser.rb +2 -2
  32. data/lib/nokogiri/version.rb +1 -1
  33. data/lib/nokogiri/xml/builder.rb +1 -1
  34. data/lib/nokogiri/xml/document.rb +2 -2
  35. data/lib/nokogiri/xml/dtd.rb +10 -0
  36. data/lib/nokogiri/xml/node.rb +26 -1
  37. data/lib/nokogiri/xml/sax/parser.rb +1 -1
  38. data/ports/archives/libxslt-1.1.28.tar.gz +0 -0
  39. data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
  40. data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
  41. data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
  42. data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
  43. data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
  44. data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
  45. data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
  46. data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
  47. data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
  48. data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
  49. data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
  50. data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
  51. data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
  52. data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
  53. data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
  54. data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
  55. data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
  56. data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
  57. data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
  58. data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
  59. data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
  60. data/suppressions/README.txt +1 -0
  61. data/suppressions/nokogiri_ree-1.8.7.358.supp +61 -0
  62. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  63. data/suppressions/nokogiri_ruby-1.9.2.320.supp +28 -0
  64. data/suppressions/nokogiri_ruby-1.9.3.327.supp +28 -0
  65. data/test/css/test_nthiness.rb +65 -2
  66. data/test/css/test_parser.rb +27 -10
  67. data/test/css/test_tokenizer.rb +1 -1
  68. data/test/css/test_xpath_visitor.rb +6 -1
  69. data/test/files/atom.xml +344 -0
  70. data/test/files/shift_jis_no_charset.html +9 -0
  71. data/test/helper.rb +10 -0
  72. data/test/html/test_document.rb +74 -7
  73. data/test/html/test_document_encoding.rb +10 -0
  74. data/test/html/test_document_fragment.rb +3 -3
  75. data/test/namespaces/test_namespaces_in_cloned_doc.rb +31 -0
  76. data/test/test_nokogiri.rb +6 -0
  77. data/test/test_reader.rb +7 -4
  78. data/test/test_xslt_transforms.rb +25 -0
  79. data/test/xml/sax/test_parser.rb +16 -0
  80. data/test/xml/sax/test_parser_context.rb +9 -0
  81. data/test/xml/test_builder.rb +9 -0
  82. data/test/xml/test_c14n.rb +12 -2
  83. data/test/xml/test_document.rb +66 -0
  84. data/test/xml/test_document_fragment.rb +5 -0
  85. data/test/xml/test_dtd.rb +84 -0
  86. data/test/xml/test_entity_reference.rb +3 -3
  87. data/test/xml/test_node.rb +21 -3
  88. data/test/xml/test_node_attributes.rb +17 -0
  89. data/test/xml/test_schema.rb +26 -0
  90. data/test/xml/test_xpath.rb +81 -0
  91. metadata +254 -174
  92. data/ports/archives/libxslt-1.1.26.tar.gz +0 -0
  93. data/tasks/cross_compile.rb +0 -134
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>����ɂ��́I</title>
4
+ </head>
5
+ <body>
6
+ <h1>This is a Shift_JIS File</h1>
7
+ <h2>����ɂ��́I</h2>
8
+ </body>
9
+ </html>
@@ -26,11 +26,14 @@ module Nokogiri
26
26
  PO_SCHEMA_FILE = File.join(ASSETS_DIR, 'po.xsd')
27
27
  PO_XML_FILE = File.join(ASSETS_DIR, 'po.xml')
28
28
  SHIFT_JIS_HTML = File.join(ASSETS_DIR, 'shift_jis.html')
29
+ SHIFT_JIS_NO_CHARSET= File.join(ASSETS_DIR, 'shift_jis_no_charset.html')
29
30
  SHIFT_JIS_XML = File.join(ASSETS_DIR, 'shift_jis.xml')
30
31
  SNUGGLES_FILE = File.join(ASSETS_DIR, 'snuggles.xml')
31
32
  XML_FILE = File.join(ASSETS_DIR, 'staff.xml')
32
33
  XML_XINCLUDE_FILE = File.join(ASSETS_DIR, 'xinclude.xml')
34
+ XML_ATOM_FILE = File.join(ASSETS_DIR, 'atom.xml')
33
35
  XSLT_FILE = File.join(ASSETS_DIR, 'staff.xslt')
36
+ XPATH_FILE = File.join(ASSETS_DIR, 'slow-xpath.xml')
34
37
 
35
38
  def teardown
36
39
  if ENV['NOKOGIRI_GC']
@@ -69,6 +72,13 @@ module Nokogiri
69
72
  alias :assert_not_nil :refute_nil
70
73
  alias :assert_raise :assert_raises
71
74
  alias :assert_not_equal :refute_equal
75
+
76
+ def assert_not_send send_ary, m = nil
77
+ recv, msg, *args = send_ary
78
+ m = message(m) {
79
+ "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return false" }
80
+ assert !recv.__send__(msg, *args), m
81
+ end unless method_defined?(:assert_not_send)
72
82
  end
73
83
 
74
84
  module SAX
@@ -166,6 +166,20 @@ EOHTML
166
166
  assert_nil doc.meta_encoding
167
167
  end
168
168
 
169
+ def test_meta_encoding_checks_charset
170
+ doc = Nokogiri::HTML(<<-eohtml)
171
+ <html>
172
+ <head>
173
+ <meta charset="UTF-8">
174
+ </head>
175
+ <body>
176
+ foo
177
+ </body>
178
+ </html>
179
+ eohtml
180
+ assert_equal 'UTF-8', doc.meta_encoding
181
+ end
182
+
169
183
  def test_meta_encoding=
170
184
  @html.meta_encoding = 'EUC-JP'
171
185
  assert_equal 'EUC-JP', @html.meta_encoding
@@ -189,11 +203,13 @@ EOHTML
189
203
  </html>
190
204
  eohtml
191
205
  doc.title = 'new'
206
+ assert_equal 1, doc.css('title').size
192
207
  assert_equal 'new', doc.title
193
208
 
194
209
  doc = Nokogiri::HTML(<<eohtml)
195
210
  <html>
196
211
  <head>
212
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
197
213
  </head>
198
214
  <body>
199
215
  foo
@@ -202,6 +218,10 @@ eohtml
202
218
  eohtml
203
219
  doc.title = 'new'
204
220
  assert_equal 'new', doc.title
221
+ title = doc.at('/html/head/title')
222
+ assert_not_nil title
223
+ assert_equal 'new', title.text
224
+ assert_equal -1, doc.at('meta[@http-equiv]') <=> title
205
225
 
206
226
  doc = Nokogiri::HTML(<<eohtml)
207
227
  <html>
@@ -211,19 +231,66 @@ eohtml
211
231
  </html>
212
232
  eohtml
213
233
  doc.title = 'new'
214
- if Nokogiri.uses_libxml?
215
- assert_nil doc.title
216
- else
217
- assert_equal 'new', doc.title
218
- end
234
+ assert_equal 'new', doc.title
235
+ # <head> may or may not be added
236
+ title = doc.at('/html//title')
237
+ assert_not_nil title
238
+ assert_equal 'new', title.text
239
+ assert_equal -1, title <=> doc.at('body')
240
+
241
+ doc = Nokogiri::HTML(<<eohtml)
242
+ <html>
243
+ <meta charset="UTF-8">
244
+ <body>
245
+ foo
246
+ </body>
247
+ </html>
248
+ eohtml
249
+ doc.title = 'new'
250
+ assert_equal 'new', doc.title
251
+ assert_equal -1, doc.at('meta[@charset]') <=> doc.at('title')
252
+ assert_equal -1, doc.at('title') <=> doc.at('body')
253
+
254
+ doc = Nokogiri::HTML('<!DOCTYPE html><p>hello')
255
+ doc.title = 'new'
256
+ assert_equal 'new', doc.title
257
+ assert_instance_of Nokogiri::XML::DTD, doc.children.first
258
+ assert_equal -1, doc.at('title') <=> doc.at('p')
259
+
260
+ doc = Nokogiri::HTML('')
261
+ doc.title = 'new'
262
+ assert_equal 'new', doc.title
263
+ assert_equal 'new', doc.at('/html/head/title/text()').to_s
219
264
  end
220
265
 
221
266
  def test_meta_encoding_without_head
222
- html = Nokogiri::HTML('<html><body>foo</body></html>')
267
+ encoding = 'EUC-JP'
268
+ html = Nokogiri::HTML('<html><body>foo</body></html>', nil, encoding)
269
+
223
270
  assert_nil html.meta_encoding
224
271
 
225
- html.meta_encoding = 'EUC-JP'
272
+ html.meta_encoding = encoding
273
+ assert_equal encoding, html.meta_encoding
274
+
275
+ meta = html.at('/html/head/meta[@http-equiv and boolean(@content)]')
276
+ assert meta, 'meta is in head'
277
+
278
+ assert meta.at('./parent::head/following-sibling::body'), 'meta is before body'
279
+ end
280
+
281
+ def test_html5_meta_encoding_without_head
282
+ encoding = 'EUC-JP'
283
+ html = Nokogiri::HTML('<!DOCTYPE html><html><body>foo</body></html>', nil, encoding)
284
+
226
285
  assert_nil html.meta_encoding
286
+
287
+ html.meta_encoding = encoding
288
+ assert_equal encoding, html.meta_encoding
289
+
290
+ meta = html.at('/html/head/meta[@charset]')
291
+ assert meta, 'meta is in head'
292
+
293
+ assert meta.at('./parent::head/following-sibling::body'), 'meta is before body'
227
294
  end
228
295
 
229
296
  def test_meta_encoding_with_empty_content_type
@@ -19,6 +19,16 @@ module Nokogiri
19
19
  assert_match 'UTF-8', doc.to_html(:encoding => 'UTF-8').encoding.name
20
20
  end
21
21
 
22
+ def test_encoding_without_charset
23
+ doc = Nokogiri::HTML File.open(SHIFT_JIS_NO_CHARSET, 'r:cp932:cp932').read
24
+
25
+ hello = "こんにちは"
26
+
27
+ assert_match hello, doc.content
28
+ assert_match hello, doc.to_html(:encoding => 'UTF-8')
29
+ assert_match 'UTF-8', doc.to_html(:encoding => 'UTF-8').encoding.name
30
+ end
31
+
22
32
  def test_default_to_encoding_from_string
23
33
  bad_charset = <<-eohtml
24
34
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -193,14 +193,14 @@ module Nokogiri
193
193
  end
194
194
 
195
195
  def test_to_xhtml
196
- doc = "<span>foo<br></span><span>bar</span>"
196
+ doc = "<span>foo<br></span><span>bar</span><p></p>"
197
197
  fragment = Nokogiri::HTML::Document.new.fragment(doc)
198
198
  if Nokogiri.jruby? || Nokogiri::VERSION_INFO['libxml']['loaded'] >= "2.7.0"
199
- assert_equal "<span>foo<br /></span><span>bar</span>", fragment.to_xhtml
199
+ assert_equal "<span>foo<br /></span><span>bar</span><p></p>", fragment.to_xhtml
200
200
  else
201
201
  # FIXME: why are we doing this ? this violates the spec,
202
202
  # see http://www.w3.org/TR/xhtml1/#C_2
203
- assert_equal "<span>foo<br></span><span>bar</span>", fragment.to_xhtml
203
+ assert_equal "<span>foo<br></span><span>bar</span><p></p>", fragment.to_xhtml
204
204
  end
205
205
  end
206
206
 
@@ -0,0 +1,31 @@
1
+ require "helper"
2
+
3
+ module Nokogiri
4
+ module XML
5
+ class TestNamespacesInClonedDoc < Nokogiri::TestCase
6
+ def setup
7
+ super
8
+ b = Nokogiri::XML::Builder.new do |xml|
9
+ xml.mods("xmlns"=>"http://www.loc.gov/mods/v3") {
10
+ xml.name(:type=>"personal") {
11
+ xml.namePart()
12
+ }
13
+ }
14
+ end
15
+
16
+ @doc = b.doc
17
+ @clone = Nokogiri::XML(@doc.to_s)
18
+ end
19
+
20
+ def check_namespace e
21
+ e.namespace.nil? ? nil : e.namespace.href
22
+ end
23
+
24
+ def test_namespace_ns
25
+ xpath = '//oxns:name[@type="personal"]'
26
+ namespaces = {'oxns' => "http://www.loc.gov/mods/v3"}
27
+ assert_equal @doc.xpath(xpath, namespaces).length, @clone.xpath(xpath, namespaces).length
28
+ end
29
+ end
30
+ end
31
+ end
@@ -41,6 +41,12 @@ class TestNokogiri < Nokogiri::TestCase
41
41
  assert !doc.html?
42
42
  end
43
43
 
44
+ def test_atom_is_xml?
45
+ doc = Nokogiri.parse(File.read(XML_ATOM_FILE))
46
+ assert doc.xml?
47
+ assert !doc.html?
48
+ end
49
+
44
50
  def test_html?
45
51
  doc = Nokogiri.parse(File.read(HTML_FILE))
46
52
  assert !doc.xml?
@@ -45,14 +45,17 @@ class TestReader < Nokogiri::TestCase
45
45
  node_out = node
46
46
  break
47
47
  end
48
+ rd.close
48
49
  end
49
50
  sleep(1) # sleep for one second to make sure the reader will actually block for input
50
- wr.puts "<foo>"
51
- wr.puts "<bar/>" * 10000
52
- wr.flush
51
+ begin
52
+ wr.puts "<foo>"
53
+ wr.puts "<bar/>" * 10000
54
+ wr.flush
55
+ rescue Errno::EPIPE
56
+ end
53
57
  res = t.join(5) # wait 5 seconds for the thread to finish
54
58
  wr.close
55
- rd.close
56
59
  refute_nil node_out, "Didn't read any nodes, exclude the trivial case"
57
60
  refute_nil res, "Reader blocks trying to read the entire stream"
58
61
  end
@@ -251,4 +251,29 @@ encoding="iso-8859-1" indent="yes"/>
251
251
  assert_equal p.content, params[p.name.intern]
252
252
  end
253
253
  end
254
+
255
+ def test_non_html_xslt_transform
256
+ xml = Nokogiri.XML(<<-EOXML)
257
+ <a>
258
+ <b>
259
+ <c>123</c>
260
+ </b>
261
+ </a>
262
+ EOXML
263
+
264
+ xsl = Nokogiri.XSLT(<<-EOXSL)
265
+ <xsl:stylesheet version="1.0"
266
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
267
+
268
+ <xsl:output encoding="UTF-8" indent="yes" method="xml" />
269
+
270
+ <xsl:template match="/">
271
+ <xsl:value-of select="/a" />
272
+ </xsl:template>
273
+ </xsl:stylesheet>
274
+ EOXSL
275
+
276
+ result = xsl.transform xml
277
+ assert !result.html?
278
+ end
254
279
  end
@@ -360,6 +360,22 @@ module Nokogiri
360
360
 
361
361
  assert_equal [['root', []], ['foo', [['a', '&b'], ['c', '>d']]]], @parser.document.start_elements
362
362
  end
363
+
364
+ def test_recovery_from_incorrect_xml
365
+ xml = <<-eoxml
366
+ <?xml version="1.0" ?><Root><Data><?xml version='1.0'?><Item>hey</Item></Data><Data><Item>hey yourself</Item></Data></Root>
367
+ eoxml
368
+
369
+ block_called = false
370
+ @parser.parse(xml) { |ctx|
371
+ block_called = true
372
+ ctx.recovery = true
373
+ }
374
+
375
+ assert block_called
376
+
377
+ assert_equal [['Root', []], ['Data', []], ['Item', []], ['Data', []], ['Item', []]], @parser.document.start_elements
378
+ end
363
379
  end
364
380
  end
365
381
  end
@@ -65,6 +65,15 @@ world
65
65
  assert_equal true, pc.replace_entities
66
66
  end
67
67
 
68
+ def test_recovery
69
+ pc = ParserContext.new StringIO.new('<root />'), 'UTF-8'
70
+ pc.recovery = false
71
+ assert_equal false, pc.recovery
72
+
73
+ pc.recovery = true
74
+ assert_equal true, pc.recovery
75
+ end
76
+
68
77
  def test_from_io
69
78
  ctx = ParserContext.new StringIO.new('fo'), 'UTF-8'
70
79
  assert ctx
@@ -13,6 +13,15 @@ module Nokogiri
13
13
  assert_equal 'world', doc.root['abcDef']
14
14
  end
15
15
 
16
+ def test_builder_multiple_nodes
17
+ builder = Nokogiri::XML::Builder.new do |xml|
18
+ 0.upto(10) do
19
+ xml.text "test"
20
+ end
21
+ end
22
+ end
23
+
24
+
16
25
  def test_builder_with_utf8_text
17
26
  text = "test ﺵ "
18
27
  doc = Nokogiri::XML::Builder.new(:encoding => "UTF-8") { |xml| xml.test text }.doc
@@ -28,6 +28,8 @@ module Nokogiri
28
28
  assert_no_match(/Comment/, c14n)
29
29
  c14n = doc.canonicalize(nil, nil, true)
30
30
  assert_match(/Comment/, c14n)
31
+ c14n = doc.canonicalize(nil, nil, false)
32
+ assert_no_match(/Comment/, c14n)
31
33
  end
32
34
 
33
35
  def test_exclude_block_params
@@ -100,7 +102,6 @@ module Nokogiri
100
102
  end
101
103
 
102
104
  def test_c14n_modes
103
- skip("C14N Exclusive implementation will complete by next version after 1.5.1") if Nokogiri.jruby?
104
105
  # http://www.w3.org/TR/xml-exc-c14n/#sec-Enveloping
105
106
 
106
107
  doc1 = Nokogiri.XML <<-eoxml
@@ -142,7 +143,16 @@ module Nokogiri
142
143
  assert_equal '<n1:elem2 xmlns:n1="http://example.net" xmlns:n2="http://foo.example" xml:lang="en">
143
144
  <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
144
145
  </n1:elem2>', c14n
145
-
146
+
147
+ end
148
+
149
+ def test_wrong_params
150
+ xml = '<a><b></b></a>'
151
+ doc = Nokogiri.XML xml
152
+
153
+ assert_raise(TypeError){ doc.canonicalize :wrong_type }
154
+ assert_raise(TypeError){ doc.canonicalize nil, :wrong_type }
155
+ doc.canonicalize nil, nil, :wrong_type
146
156
  end
147
157
 
148
158
 
@@ -26,6 +26,13 @@ module Nokogiri
26
26
  assert doc.root
27
27
  end
28
28
 
29
+ # issue #1005
30
+ def test_strict_parsing_empty_doc_should_raise_exception
31
+ assert_raises(SyntaxError) do
32
+ Nokogiri::XML(StringIO.new('')) { |c| c.strict }
33
+ end
34
+ end
35
+
29
36
  # issue #838
30
37
  def test_document_with_invalid_prolog
31
38
  doc = Nokogiri::XML '<? ?>'
@@ -337,6 +344,59 @@ module Nokogiri
337
344
  assert_equal "quack!", doc.root.children.first.content
338
345
  end
339
346
 
347
+ def test_prepend
348
+ doc = Nokogiri::XML('<root>')
349
+
350
+ node_set = doc.root.prepend_child '<branch/>'
351
+ assert_equal %w[branch], node_set.map(&:name)
352
+
353
+ branch = doc.at('//branch')
354
+
355
+ leaves = %w[leaf1 leaf2 leaf3]
356
+ leaves.each { |name|
357
+ branch.prepend_child('<%s/>' % name)
358
+ }
359
+ assert_equal leaves.length, branch.children.length
360
+ assert_equal leaves.reverse, branch.children.map(&:name)
361
+ end
362
+
363
+ def test_prepend_child_fragment_with_single_node
364
+ doc = Nokogiri::XML::Document.new
365
+ fragment = doc.fragment('<hello />')
366
+ doc.prepend_child fragment
367
+ assert_equal '/hello', doc.at('//hello').path
368
+ assert_equal 'hello', doc.root.name
369
+ end
370
+
371
+ def test_prepend_child_fragment_with_multiple_nodes
372
+ doc = Nokogiri::XML::Document.new
373
+ fragment = doc.fragment('<hello /><goodbye />')
374
+ assert_raises(RuntimeError) do
375
+ doc.prepend_child fragment
376
+ end
377
+ end
378
+
379
+ def test_prepend_child_fragment_with_multiple_nodes
380
+ doc = Nokogiri::XML::Document.new
381
+ fragment = doc.fragment('<hello /><goodbye />')
382
+ assert_raises(RuntimeError) do
383
+ doc.prepend_child fragment
384
+ end
385
+ end
386
+
387
+ def test_prepend_child_with_multiple_roots
388
+ assert_raises(RuntimeError) do
389
+ @xml.prepend_child Node.new('foo', @xml)
390
+ end
391
+ end
392
+
393
+ def test_prepend_child_with_string
394
+ doc = Nokogiri::XML::Document.new
395
+ doc.prepend_child "<div>quack!</div>"
396
+ assert_equal 1, doc.root.children.length
397
+ assert_equal "quack!", doc.root.children.first.content
398
+ end
399
+
340
400
  def test_move_root_to_document_with_no_root
341
401
  sender = Nokogiri::XML('<root>foo</root>')
342
402
  newdoc = Nokogiri::XML::Document.new
@@ -483,6 +543,12 @@ module Nokogiri
483
543
  }
484
544
  end
485
545
 
546
+ def test_xpath_syntax_error
547
+ assert_raises(Nokogiri::XML::XPath::SyntaxError) do
548
+ @xml.xpath('\\')
549
+ end
550
+ end
551
+
486
552
  def test_ancestors
487
553
  assert_equal 0, @xml.ancestors.length
488
554
  end