nokogiri 1.8.5 → 1.9.1

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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/ext/nokogiri/extconf.rb +10 -6
  4. data/ext/nokogiri/xml_attr.c +26 -21
  5. data/ext/nokogiri/xml_document.c +4 -1
  6. data/ext/nokogiri/xml_namespace.c +3 -3
  7. data/ext/nokogiri/xml_namespace.h +1 -2
  8. data/ext/nokogiri/xml_node.c +55 -15
  9. data/lib/nokogiri/css/parser.rb +61 -61
  10. data/lib/nokogiri/version.rb +1 -1
  11. data/lib/nokogiri/xml/document_fragment.rb +11 -0
  12. data/lib/nokogiri/xml/node.rb +12 -0
  13. data/lib/nokogiri/xml/node_set.rb +4 -8
  14. metadata +17 -153
  15. data/.autotest +0 -22
  16. data/.cross_rubies +0 -8
  17. data/.editorconfig +0 -17
  18. data/.gemtest +0 -0
  19. data/.travis.yml +0 -63
  20. data/CHANGELOG.md +0 -1368
  21. data/CONTRIBUTING.md +0 -42
  22. data/C_CODING_STYLE.rdoc +0 -33
  23. data/Gemfile +0 -23
  24. data/Gemfile-libxml-ruby +0 -3
  25. data/Manifest.txt +0 -370
  26. data/ROADMAP.md +0 -111
  27. data/Rakefile +0 -348
  28. data/SECURITY.md +0 -19
  29. data/STANDARD_RESPONSES.md +0 -47
  30. data/Y_U_NO_GEMSPEC.md +0 -155
  31. data/appveyor.yml +0 -29
  32. data/build_all +0 -44
  33. data/patches/sort-patches-by-date +0 -25
  34. data/suppressions/README.txt +0 -1
  35. data/suppressions/nokogiri_ruby-2.supp +0 -10
  36. data/tasks/test.rb +0 -100
  37. data/test/css/test_nthiness.rb +0 -226
  38. data/test/css/test_parser.rb +0 -386
  39. data/test/css/test_tokenizer.rb +0 -215
  40. data/test/css/test_xpath_visitor.rb +0 -96
  41. data/test/decorators/test_slop.rb +0 -23
  42. data/test/files/2ch.html +0 -108
  43. data/test/files/GH_1042.html +0 -18
  44. data/test/files/address_book.rlx +0 -12
  45. data/test/files/address_book.xml +0 -10
  46. data/test/files/atom.xml +0 -344
  47. data/test/files/bar/bar.xsd +0 -4
  48. data/test/files/bogus.xml +0 -0
  49. data/test/files/dont_hurt_em_why.xml +0 -422
  50. data/test/files/encoding.html +0 -82
  51. data/test/files/encoding.xhtml +0 -84
  52. data/test/files/exslt.xml +0 -8
  53. data/test/files/exslt.xslt +0 -35
  54. data/test/files/foo/foo.xsd +0 -4
  55. data/test/files/metacharset.html +0 -10
  56. data/test/files/namespace_pressure_test.xml +0 -1684
  57. data/test/files/noencoding.html +0 -47
  58. data/test/files/po.xml +0 -32
  59. data/test/files/po.xsd +0 -66
  60. data/test/files/saml/saml20assertion_schema.xsd +0 -283
  61. data/test/files/saml/saml20protocol_schema.xsd +0 -302
  62. data/test/files/saml/xenc_schema.xsd +0 -146
  63. data/test/files/saml/xmldsig_schema.xsd +0 -318
  64. data/test/files/shift_jis.html +0 -10
  65. data/test/files/shift_jis.xml +0 -5
  66. data/test/files/shift_jis_no_charset.html +0 -9
  67. data/test/files/slow-xpath.xml +0 -25509
  68. data/test/files/snuggles.xml +0 -3
  69. data/test/files/staff.dtd +0 -10
  70. data/test/files/staff.xml +0 -59
  71. data/test/files/staff.xslt +0 -32
  72. data/test/files/test_document_url/bar.xml +0 -2
  73. data/test/files/test_document_url/document.dtd +0 -4
  74. data/test/files/test_document_url/document.xml +0 -6
  75. data/test/files/tlm.html +0 -851
  76. data/test/files/to_be_xincluded.xml +0 -2
  77. data/test/files/valid_bar.xml +0 -2
  78. data/test/files/xinclude.xml +0 -4
  79. data/test/helper.rb +0 -271
  80. data/test/html/sax/test_parser.rb +0 -168
  81. data/test/html/sax/test_parser_context.rb +0 -46
  82. data/test/html/sax/test_parser_text.rb +0 -163
  83. data/test/html/sax/test_push_parser.rb +0 -87
  84. data/test/html/test_attributes.rb +0 -85
  85. data/test/html/test_builder.rb +0 -164
  86. data/test/html/test_document.rb +0 -712
  87. data/test/html/test_document_encoding.rb +0 -143
  88. data/test/html/test_document_fragment.rb +0 -310
  89. data/test/html/test_element_description.rb +0 -105
  90. data/test/html/test_named_characters.rb +0 -14
  91. data/test/html/test_node.rb +0 -212
  92. data/test/html/test_node_encoding.rb +0 -91
  93. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
  94. data/test/namespaces/test_namespaces_aliased_default.rb +0 -24
  95. data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
  96. data/test/namespaces/test_namespaces_in_cloned_doc.rb +0 -31
  97. data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
  98. data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -80
  99. data/test/namespaces/test_namespaces_preservation.rb +0 -31
  100. data/test/test_convert_xpath.rb +0 -135
  101. data/test/test_css_cache.rb +0 -47
  102. data/test/test_encoding_handler.rb +0 -48
  103. data/test/test_memory_leak.rb +0 -156
  104. data/test/test_nokogiri.rb +0 -138
  105. data/test/test_soap4r_sax.rb +0 -52
  106. data/test/test_xslt_transforms.rb +0 -314
  107. data/test/xml/node/test_save_options.rb +0 -28
  108. data/test/xml/node/test_subclass.rb +0 -44
  109. data/test/xml/sax/test_parser.rb +0 -402
  110. data/test/xml/sax/test_parser_context.rb +0 -115
  111. data/test/xml/sax/test_parser_text.rb +0 -202
  112. data/test/xml/sax/test_push_parser.rb +0 -265
  113. data/test/xml/test_attr.rb +0 -74
  114. data/test/xml/test_attribute_decl.rb +0 -86
  115. data/test/xml/test_builder.rb +0 -341
  116. data/test/xml/test_c14n.rb +0 -180
  117. data/test/xml/test_cdata.rb +0 -54
  118. data/test/xml/test_comment.rb +0 -40
  119. data/test/xml/test_document.rb +0 -982
  120. data/test/xml/test_document_encoding.rb +0 -31
  121. data/test/xml/test_document_fragment.rb +0 -298
  122. data/test/xml/test_dtd.rb +0 -187
  123. data/test/xml/test_dtd_encoding.rb +0 -31
  124. data/test/xml/test_element_content.rb +0 -56
  125. data/test/xml/test_element_decl.rb +0 -73
  126. data/test/xml/test_entity_decl.rb +0 -122
  127. data/test/xml/test_entity_reference.rb +0 -262
  128. data/test/xml/test_namespace.rb +0 -96
  129. data/test/xml/test_node.rb +0 -1325
  130. data/test/xml/test_node_attributes.rb +0 -115
  131. data/test/xml/test_node_encoding.rb +0 -75
  132. data/test/xml/test_node_inheritance.rb +0 -32
  133. data/test/xml/test_node_reparenting.rb +0 -592
  134. data/test/xml/test_node_set.rb +0 -809
  135. data/test/xml/test_parse_options.rb +0 -64
  136. data/test/xml/test_processing_instruction.rb +0 -30
  137. data/test/xml/test_reader.rb +0 -620
  138. data/test/xml/test_reader_encoding.rb +0 -134
  139. data/test/xml/test_relax_ng.rb +0 -60
  140. data/test/xml/test_schema.rb +0 -142
  141. data/test/xml/test_syntax_error.rb +0 -36
  142. data/test/xml/test_text.rb +0 -60
  143. data/test/xml/test_unparented_node.rb +0 -483
  144. data/test/xml/test_xinclude.rb +0 -83
  145. data/test/xml/test_xpath.rb +0 -470
  146. data/test/xslt/test_custom_functions.rb +0 -133
  147. data/test/xslt/test_exception_handling.rb +0 -37
@@ -1,386 +0,0 @@
1
- require "helper"
2
-
3
- module Nokogiri
4
- module CSS
5
- class TestParser < Nokogiri::TestCase
6
- def setup
7
- super
8
- @parser = Nokogiri::CSS::Parser.new
9
- @parser_with_ns = Nokogiri::CSS::Parser.new({
10
- "xmlns" => "http://default.example.com/",
11
- "hoge" => "http://hoge.example.com/",
12
- })
13
- end
14
-
15
- def test_extra_single_quote
16
- assert_raises(CSS::SyntaxError) { @parser.parse("'") }
17
- end
18
-
19
- def test_syntax_error_raised
20
- assert_raises(CSS::SyntaxError) { @parser.parse("a[x=]") }
21
- end
22
-
23
- def test_function_and_pseudo
24
- assert_xpath '//child::text()[position() = 99]', @parser.parse('text():nth-of-type(99)')
25
- end
26
-
27
- def test_find_by_type
28
- ast = @parser.parse("a:nth-child(2)").first
29
- matches = ast.find_by_type(
30
- [:CONDITIONAL_SELECTOR,
31
- [:ELEMENT_NAME],
32
- [:PSEUDO_CLASS,
33
- [:FUNCTION]
34
- ]
35
- ]
36
- )
37
- assert_equal(1, matches.length)
38
- assert_equal(ast, matches.first)
39
- end
40
-
41
- def test_to_type
42
- ast = @parser.parse("a:nth-child(2)").first
43
- assert_equal(
44
- [:CONDITIONAL_SELECTOR,
45
- [:ELEMENT_NAME],
46
- [:PSEUDO_CLASS,
47
- [:FUNCTION]
48
- ]
49
- ], ast.to_type
50
- )
51
- end
52
-
53
- def test_to_a
54
- asts = @parser.parse("a:nth-child(2)")
55
- assert_equal(
56
- [:CONDITIONAL_SELECTOR,
57
- [:ELEMENT_NAME, ["a"]],
58
- [:PSEUDO_CLASS,
59
- [:FUNCTION, ["nth-child("], ["2"]]
60
- ]
61
- ], asts.first.to_a
62
- )
63
- end
64
-
65
- def test_has
66
- assert_xpath "//a[b]", @parser.parse("a:has(b)")
67
- assert_xpath "//a[b/c]", @parser.parse("a:has(b > c)")
68
- end
69
-
70
- def test_dashmatch
71
- assert_xpath "//a[@class = 'bar' or starts-with(@class, concat('bar', '-'))]",
72
- @parser.parse("a[@class|='bar']")
73
- assert_xpath "//a[@class = 'bar' or starts-with(@class, concat('bar', '-'))]",
74
- @parser.parse("a[@class |= 'bar']")
75
- end
76
-
77
- def test_includes
78
- assert_xpath "//a[contains(concat(\" \", @class, \" \"),concat(\" \", 'bar', \" \"))]",
79
- @parser.parse("a[@class~='bar']")
80
- assert_xpath "//a[contains(concat(\" \", @class, \" \"),concat(\" \", 'bar', \" \"))]",
81
- @parser.parse("a[@class ~= 'bar']")
82
- end
83
-
84
- def test_function_with_arguments
85
- assert_xpath "//a[count(preceding-sibling::*) = 1]",
86
- @parser.parse("a[2]")
87
- assert_xpath "//a[count(preceding-sibling::*) = 1]",
88
- @parser.parse("a:nth-child(2)")
89
- end
90
-
91
- def test_carrot
92
- assert_xpath "//a[starts-with(@id, 'Boing')]",
93
- @parser.parse("a[id^='Boing']")
94
- assert_xpath "//a[starts-with(@id, 'Boing')]",
95
- @parser.parse("a[id ^= 'Boing']")
96
- end
97
-
98
- def test_suffix_match
99
- assert_xpath "//a[substring(@id, string-length(@id) - string-length('Boing') + 1, string-length('Boing')) = 'Boing']",
100
- @parser.parse("a[id$='Boing']")
101
- assert_xpath "//a[substring(@id, string-length(@id) - string-length('Boing') + 1, string-length('Boing')) = 'Boing']",
102
- @parser.parse("a[id $= 'Boing']")
103
- end
104
-
105
- def test_attributes_with_at
106
- ## This is non standard CSS
107
- assert_xpath "//a[@id = 'Boing']",
108
- @parser.parse("a[@id='Boing']")
109
- assert_xpath "//a[@id = 'Boing']",
110
- @parser.parse("a[@id = 'Boing']")
111
- end
112
-
113
- def test_attributes_with_at_and_stuff
114
- ## This is non standard CSS
115
- assert_xpath "//a[@id = 'Boing']//div",
116
- @parser.parse("a[@id='Boing'] div")
117
- end
118
-
119
- def test_not_equal
120
- ## This is non standard CSS
121
- assert_xpath "//a[child::text() != 'Boing']",
122
- @parser.parse("a[text()!='Boing']")
123
- assert_xpath "//a[child::text() != 'Boing']",
124
- @parser.parse("a[text() != 'Boing']")
125
- end
126
-
127
- def test_function
128
- ## This is non standard CSS
129
- assert_xpath "//a[child::text()]",
130
- @parser.parse("a[text()]")
131
-
132
- ## This is non standard CSS
133
- assert_xpath "//child::text()",
134
- @parser.parse("text()")
135
-
136
- ## This is non standard CSS
137
- assert_xpath "//a[contains(child::text(), 'Boing')]",
138
- @parser.parse("a[text()*='Boing']")
139
- assert_xpath "//a[contains(child::text(), 'Boing')]",
140
- @parser.parse("a[text() *= 'Boing']")
141
-
142
- ## This is non standard CSS
143
- assert_xpath "//script//comment()",
144
- @parser.parse("script comment()")
145
- end
146
-
147
- def test_nonstandard_nth_selectors
148
- ## These are non standard CSS
149
- assert_xpath '//a[position() = 1]', @parser.parse('a:first()')
150
- assert_xpath '//a[position() = 1]', @parser.parse('a:first') # no parens
151
- assert_xpath '//a[position() = 99]', @parser.parse('a:eq(99)')
152
- assert_xpath '//a[position() = 99]', @parser.parse('a:nth(99)')
153
- assert_xpath '//a[position() = last()]', @parser.parse('a:last()')
154
- assert_xpath '//a[position() = last()]', @parser.parse('a:last') # no parens
155
- assert_xpath '//a[node()]', @parser.parse('a:parent')
156
- end
157
-
158
- def test_standard_nth_selectors
159
- assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type()')
160
- assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type') # no parens
161
- assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = 1]",
162
- @parser.parse('a.b:first-of-type') # no parens
163
- assert_xpath '//a[position() = 99]', @parser.parse('a:nth-of-type(99)')
164
- assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = 99]",
165
- @parser.parse('a.b:nth-of-type(99)')
166
- assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type()')
167
- assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type') # no parens
168
- assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = last()]",
169
- @parser.parse('a.b:last-of-type') # no parens
170
- assert_xpath '//a[position() = last()]', @parser.parse('a:nth-last-of-type(1)')
171
- assert_xpath '//a[position() = last() - 98]', @parser.parse('a:nth-last-of-type(99)')
172
- assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = last() - 98]",
173
- @parser.parse('a.b:nth-last-of-type(99)')
174
- end
175
-
176
- def test_nth_child_selectors
177
- assert_xpath '//a[count(preceding-sibling::*) = 0]', @parser.parse('a:first-child')
178
- assert_xpath '//a[count(preceding-sibling::*) = 98]', @parser.parse('a:nth-child(99)')
179
- assert_xpath '//a[count(following-sibling::*) = 0]', @parser.parse('a:last-child')
180
- assert_xpath '//a[count(following-sibling::*) = 0]', @parser.parse('a:nth-last-child(1)')
181
- assert_xpath '//a[count(following-sibling::*) = 98]', @parser.parse('a:nth-last-child(99)')
182
- end
183
-
184
- def test_miscellaneous_selectors
185
- assert_xpath '//a[count(preceding-sibling::*) = 0 and count(following-sibling::*) = 0]', @parser.parse('a:only-child')
186
- assert_xpath '//a[last() = 1]', @parser.parse('a:only-of-type')
187
- assert_xpath '//a[not(node())]', @parser.parse('a:empty')
188
- end
189
-
190
- def test_nth_a_n_plus_b
191
- assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(2n)')
192
- assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(2n+1)')
193
- assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(even)')
194
- assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(odd)')
195
- assert_xpath '//a[(position() >= 3) and (((position()-3) mod 4) = 0)]', @parser.parse('a:nth-of-type(4n+3)')
196
- assert_xpath '//a[position() <= 3]', @parser.parse('a:nth-of-type(-1n+3)')
197
- assert_xpath '//a[position() <= 3]', @parser.parse('a:nth-of-type(-n+3)')
198
- assert_xpath '//a[position() >= 3]', @parser.parse('a:nth-of-type(1n+3)')
199
- assert_xpath '//a[position() >= 3]', @parser.parse('a:nth-of-type(n+3)')
200
-
201
- assert_xpath '//a[((last()-position()+1) mod 2) = 0]', @parser.parse('a:nth-last-of-type(2n)')
202
- assert_xpath '//a[((last()-position()+1) >= 1) and ((((last()-position()+1)-1) mod 2) = 0)]', @parser.parse('a:nth-last-of-type(2n+1)')
203
- assert_xpath '//a[((last()-position()+1) mod 2) = 0]', @parser.parse('a:nth-last-of-type(even)')
204
- assert_xpath '//a[((last()-position()+1) >= 1) and ((((last()-position()+1)-1) mod 2) = 0)]', @parser.parse('a:nth-last-of-type(odd)')
205
- assert_xpath '//a[((last()-position()+1) >= 3) and ((((last()-position()+1)-3) mod 4) = 0)]', @parser.parse('a:nth-last-of-type(4n+3)')
206
- assert_xpath '//a[(last()-position()+1) <= 3]', @parser.parse('a:nth-last-of-type(-1n+3)')
207
- assert_xpath '//a[(last()-position()+1) <= 3]', @parser.parse('a:nth-last-of-type(-n+3)')
208
- assert_xpath '//a[(last()-position()+1) >= 3]', @parser.parse('a:nth-last-of-type(1n+3)')
209
- assert_xpath '//a[(last()-position()+1) >= 3]', @parser.parse('a:nth-last-of-type(n+3)')
210
- end
211
-
212
- def test_preceding_selector
213
- assert_xpath "//E/following-sibling::F",
214
- @parser.parse("E ~ F")
215
-
216
- assert_xpath "//E/following-sibling::F//G",
217
- @parser.parse("E ~ F G")
218
- end
219
-
220
- def test_direct_preceding_selector
221
- assert_xpath "//E/following-sibling::*[1]/self::F",
222
- @parser.parse("E + F")
223
-
224
- assert_xpath "//E/following-sibling::*[1]/self::F//G",
225
- @parser.parse("E + F G")
226
- end
227
-
228
- def test_child_selector
229
- assert_xpath("//a//b/i", @parser.parse('a b>i'))
230
- assert_xpath("//a//b/i", @parser.parse('a b > i'))
231
- assert_xpath("//a/b/i", @parser.parse('a > b > i'))
232
- end
233
-
234
- def test_prefixless_child_selector
235
- assert_xpath("./a", @parser.parse('>a'))
236
- assert_xpath("./a", @parser.parse('> a'))
237
- assert_xpath("./a//b/i", @parser.parse('>a b>i'))
238
- assert_xpath("./a/b/i", @parser.parse('> a > b > i'))
239
- end
240
-
241
- def test_prefixless_preceding_sibling_selector
242
- assert_xpath("./following-sibling::a", @parser.parse('~a'))
243
- assert_xpath("./following-sibling::a", @parser.parse('~ a'))
244
- assert_xpath("./following-sibling::a//b/following-sibling::i", @parser.parse('~a b~i'))
245
- assert_xpath("./following-sibling::a//b/following-sibling::i", @parser.parse('~ a b ~ i'))
246
- end
247
-
248
- def test_prefixless_direct_adjacent_selector
249
- assert_xpath("./following-sibling::*[1]/self::a", @parser.parse('+a'))
250
- assert_xpath("./following-sibling::*[1]/self::a", @parser.parse('+ a'))
251
- assert_xpath("./following-sibling::*[1]/self::a/following-sibling::*[1]/self::b", @parser.parse('+a+b'))
252
- assert_xpath("./following-sibling::*[1]/self::a/following-sibling::*[1]/self::b", @parser.parse('+ a + b'))
253
- end
254
-
255
- def test_attribute
256
- assert_xpath "//h1[@a = 'Tender Lovemaking']",
257
- @parser.parse("h1[a='Tender Lovemaking']")
258
- assert_xpath "//h1[@a]",
259
- @parser.parse("h1[a]")
260
- assert_xpath %q{//h1[@a = 'gnewline\n']},
261
- @parser.parse("h1[a='\\gnew\\\nline\\\\n']")
262
- assert_xpath "//h1[@a = 'test']",
263
- @parser.parse(%q{h1[a=\te\st]})
264
- assert_xpath %q{//h1[@a = "'"]},
265
- @parser.parse(%q{h1[a="'"]})
266
- assert_xpath %q{//h1[@a = concat("'", "")]},
267
- @parser.parse(%q{h1[a='\\'']})
268
- assert_xpath %q{//h1[@a = concat("", '"', "'", "")]},
269
- @parser.parse(%q{h1[a='"\'']})
270
- end
271
-
272
- def test_attribute_with_number_or_string
273
- assert_xpath "//img[@width = '200']", @parser.parse("img[width='200']")
274
- assert_xpath "//img[@width = '200']", @parser.parse("img[width=200]")
275
- end
276
-
277
- def test_id
278
- assert_xpath "//*[@id = 'foo']", @parser.parse('#foo')
279
- assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\:needed\,')
280
- assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\3Aneeded\,')
281
- assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\3A needed\2C')
282
- assert_xpath "//*[@id = 'escape:needed']", @parser.parse('#escape\00003Aneeded')
283
- end
284
-
285
- def test_pseudo_class_no_ident
286
- assert_xpath "//*[link(.)]", @parser.parse(':link')
287
- end
288
-
289
- def test_pseudo_class
290
- assert_xpath "//a[link(.)]", @parser.parse('a:link')
291
- assert_xpath "//a[visited(.)]", @parser.parse('a:visited')
292
- assert_xpath "//a[hover(.)]", @parser.parse('a:hover')
293
- assert_xpath "//a[active(.)]", @parser.parse('a:active')
294
- assert_xpath "//a[active(.) and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]",
295
- @parser.parse('a:active.foo')
296
- end
297
-
298
- def test_significant_space
299
- assert_xpath "//x//*[count(preceding-sibling::*) = 0]//*[@a]//*[@b]", @parser.parse("x :first-child [a] [b]")
300
- assert_xpath "//*[@a]//*[@b]", @parser.parse(" [a] [b]")
301
- end
302
-
303
- def test_star
304
- assert_xpath "//*", @parser.parse('*')
305
- assert_xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' pastoral ')]",
306
- @parser.parse('*.pastoral')
307
- end
308
-
309
- def test_class
310
- assert_xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' a ') and contains(concat(' ', normalize-space(@class), ' '), ' b ')]",
311
- @parser.parse('.a.b')
312
- assert_xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' awesome ')]",
313
- @parser.parse('.awesome')
314
- assert_xpath "//foo[contains(concat(' ', normalize-space(@class), ' '), ' awesome ')]",
315
- @parser.parse('foo.awesome')
316
- assert_xpath "//foo//*[contains(concat(' ', normalize-space(@class), ' '), ' awesome ')]",
317
- @parser.parse('foo .awesome')
318
- assert_xpath "//foo//*[contains(concat(' ', normalize-space(@class), ' '), ' awe.some ')]",
319
- @parser.parse('foo .awe\.some')
320
- end
321
-
322
- def test_bare_not
323
- assert_xpath "//*[not(contains(concat(' ', normalize-space(@class), ' '), ' a '))]",
324
- @parser.parse(':not(.a)')
325
- end
326
-
327
- def test_not_so_simple_not
328
- assert_xpath "//*[@id = 'p' and not(contains(concat(' ', normalize-space(@class), ' '), ' a '))]",
329
- @parser.parse('#p:not(.a)')
330
- assert_xpath "//p[contains(concat(' ', normalize-space(@class), ' '), ' a ') and not(contains(concat(' ', normalize-space(@class), ' '), ' b '))]",
331
- @parser.parse('p.a:not(.b)')
332
- assert_xpath "//p[@a = 'foo' and not(contains(concat(' ', normalize-space(@class), ' '), ' b '))]",
333
- @parser.parse("p[a='foo']:not(.b)")
334
- end
335
-
336
- def test_multiple_not
337
- assert_xpath "//p[not(contains(concat(' ', normalize-space(@class), ' '), ' a ')) and not(contains(concat(' ', normalize-space(@class), ' '), ' b ')) and not(contains(concat(' ', normalize-space(@class), ' '), ' c '))]",
338
- @parser.parse("p:not(.a):not(.b):not(.c)")
339
- end
340
-
341
- def test_ident
342
- assert_xpath '//x', @parser.parse('x')
343
- end
344
-
345
- def test_parse_space
346
- assert_xpath '//x//y', @parser.parse('x y')
347
- end
348
-
349
- def test_parse_descendant
350
- assert_xpath '//x/y', @parser.parse('x > y')
351
- end
352
-
353
- def test_parse_slash
354
- ## This is non standard CSS
355
- assert_xpath '//x/y', @parser.parse('x/y')
356
- end
357
-
358
- def test_parse_doubleslash
359
- ## This is non standard CSS
360
- assert_xpath '//x//y', @parser.parse('x//y')
361
- end
362
-
363
- def test_multi_path
364
- assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y, y > z')
365
- assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y,y > z')
366
- ###
367
- # TODO: should we make this work?
368
- # assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y | y > z')
369
- end
370
-
371
- def test_attributes_with_namespace
372
- ## Default namespace is not applied to attributes.
373
- ## So this must be @class, not @xmlns:class.
374
- assert_xpath "//xmlns:a[@class = 'bar']", @parser_with_ns.parse("a[class='bar']")
375
- assert_xpath "//xmlns:a[@hoge:class = 'bar']", @parser_with_ns.parse("a[hoge|class='bar']")
376
- end
377
-
378
- def assert_xpath expecteds, asts
379
- expecteds = [expecteds].flatten
380
- expecteds.zip(asts).each do |expected, actual|
381
- assert_equal expected, actual.to_xpath
382
- end
383
- end
384
- end
385
- end
386
- end
@@ -1,215 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- require "helper"
4
-
5
- module Nokogiri
6
- module CSS
7
- class Tokenizer
8
- alias :scan :scan_setup
9
- end
10
- end
11
- end
12
-
13
- module Nokogiri
14
- module CSS
15
- class TestTokenizer < Nokogiri::TestCase
16
- def setup
17
- super
18
- @scanner = Nokogiri::CSS::Tokenizer.new
19
- end
20
-
21
- def test_has
22
- @scanner.scan("a:has(b)")
23
- assert_tokens(
24
- [[:IDENT, "a"], [":", ":"], [:HAS, "has("], [:IDENT, "b"], [:RPAREN, ")"]],
25
- @scanner)
26
- end
27
-
28
- def test_unicode
29
- @scanner.scan("a日本語")
30
- assert_tokens([[:IDENT, 'a日本語']], @scanner)
31
- end
32
-
33
- def test_tokenize_bad_single_quote
34
- @scanner.scan("'")
35
- assert_tokens([["'", "'"]], @scanner)
36
- end
37
-
38
- def test_not_equal
39
- @scanner.scan("h1[a!='Tender Lovemaking']")
40
- assert_tokens([ [:IDENT, 'h1'],
41
- [:LSQUARE, '['],
42
- [:IDENT, 'a'],
43
- [:NOT_EQUAL, '!='],
44
- [:STRING, "'Tender Lovemaking'"],
45
- [:RSQUARE, ']'],
46
- ], @scanner)
47
- end
48
-
49
- def test_negation
50
- @scanner.scan("p:not(.a)")
51
- assert_tokens([ [:IDENT, 'p'],
52
- [:NOT, ':not('],
53
- ['.', '.'],
54
- [:IDENT, 'a'],
55
- [:RPAREN, ')'],
56
- ], @scanner)
57
- end
58
-
59
- def test_function
60
- @scanner.scan("script comment()")
61
- assert_tokens([ [:IDENT, 'script'],
62
- [:S, ' '],
63
- [:FUNCTION, 'comment('],
64
- [:RPAREN, ')'],
65
- ], @scanner)
66
- end
67
-
68
- def test_preceding_selector
69
- @scanner.scan("E ~ F")
70
- assert_tokens([ [:IDENT, 'E'],
71
- [:TILDE, ' ~ '],
72
- [:IDENT, 'F'],
73
- ], @scanner)
74
- end
75
-
76
- def test_scan_attribute_string
77
- @scanner.scan("h1[a='Tender Lovemaking']")
78
- assert_tokens([ [:IDENT, 'h1'],
79
- [:LSQUARE, '['],
80
- [:IDENT, 'a'],
81
- [:EQUAL, '='],
82
- [:STRING, "'Tender Lovemaking'"],
83
- [:RSQUARE, ']'],
84
- ], @scanner)
85
- @scanner.scan('h1[a="Tender Lovemaking"]')
86
- assert_tokens([ [:IDENT, 'h1'],
87
- [:LSQUARE, '['],
88
- [:IDENT, 'a'],
89
- [:EQUAL, '='],
90
- [:STRING, '"Tender Lovemaking"'],
91
- [:RSQUARE, ']'],
92
- ], @scanner)
93
- end
94
-
95
- def test_scan_id
96
- @scanner.scan('#foo')
97
- assert_tokens([ [:HASH, '#foo'] ], @scanner)
98
- end
99
-
100
- def test_scan_pseudo
101
- @scanner.scan('a:visited')
102
- assert_tokens([ [:IDENT, 'a'],
103
- [':', ':'],
104
- [:IDENT, 'visited']
105
- ], @scanner)
106
- end
107
-
108
- def test_scan_star
109
- @scanner.scan('*')
110
- assert_tokens([ ['*', '*'], ], @scanner)
111
- end
112
-
113
- def test_scan_class
114
- @scanner.scan('x.awesome')
115
- assert_tokens([ [:IDENT, 'x'],
116
- ['.', '.'],
117
- [:IDENT, 'awesome'],
118
- ], @scanner)
119
- end
120
-
121
- def test_scan_greater
122
- @scanner.scan('x > y')
123
- assert_tokens([ [:IDENT, 'x'],
124
- [:GREATER, ' > '],
125
- [:IDENT, 'y']
126
- ], @scanner)
127
- end
128
-
129
- def test_scan_slash
130
- @scanner.scan('x/y')
131
- assert_tokens([ [:IDENT, 'x'],
132
- [:SLASH, '/'],
133
- [:IDENT, 'y']
134
- ], @scanner)
135
- end
136
-
137
- def test_scan_doubleslash
138
- @scanner.scan('x//y')
139
- assert_tokens([ [:IDENT, 'x'],
140
- [:DOUBLESLASH, '//'],
141
- [:IDENT, 'y']
142
- ], @scanner)
143
- end
144
-
145
- def test_scan_function_selector
146
- @scanner.scan('x:eq(0)')
147
- assert_tokens([ [:IDENT, 'x'],
148
- [':', ':'],
149
- [:FUNCTION, 'eq('],
150
- [:NUMBER, "0"],
151
- [:RPAREN, ')'],
152
- ], @scanner)
153
- end
154
-
155
- def test_scan_nth
156
- @scanner.scan('x:nth-child(5n+3)')
157
- assert_tokens([ [:IDENT, 'x'],
158
- [':', ':'],
159
- [:FUNCTION, 'nth-child('],
160
- [:NUMBER, '5'],
161
- [:IDENT, 'n'],
162
- [:PLUS, '+'],
163
- [:NUMBER, '3'],
164
- [:RPAREN, ')'],
165
- ], @scanner)
166
-
167
- @scanner.scan('x:nth-child(-1n+3)')
168
- assert_tokens([ [:IDENT, 'x'],
169
- [':', ':'],
170
- [:FUNCTION, 'nth-child('],
171
- [:NUMBER, '-1'],
172
- [:IDENT, 'n'],
173
- [:PLUS, '+'],
174
- [:NUMBER, '3'],
175
- [:RPAREN, ')'],
176
- ], @scanner)
177
-
178
- @scanner.scan('x:nth-child(-n+3)')
179
- assert_tokens([ [:IDENT, 'x'],
180
- [':', ':'],
181
- [:FUNCTION, 'nth-child('],
182
- [:IDENT, '-n'],
183
- [:PLUS, '+'],
184
- [:NUMBER, '3'],
185
- [:RPAREN, ')'],
186
- ], @scanner)
187
- end
188
-
189
- def test_significant_space
190
- @scanner.scan('x :first-child [a] [b]')
191
- assert_tokens([ [:IDENT, 'x'],
192
- [:S, ' '],
193
- [':', ':'],
194
- [:IDENT, 'first-child'],
195
- [:S, ' '],
196
- [:LSQUARE, '['],
197
- [:IDENT, 'a'],
198
- [:RSQUARE, ']'],
199
- [:S, ' '],
200
- [:LSQUARE, '['],
201
- [:IDENT, 'b'],
202
- [:RSQUARE, ']'],
203
- ], @scanner)
204
- end
205
-
206
- def assert_tokens(tokens, scanner)
207
- toks = []
208
- while tok = @scanner.next_token
209
- toks << tok
210
- end
211
- assert_equal(tokens, toks)
212
- end
213
- end
214
- end
215
- end