scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2  
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11  
12 namespace Symfony\Component\CssSelector\Tests\XPath;
13  
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
16 use Symfony\Component\CssSelector\XPath\Translator;
17  
18 class TranslatorTest extends TestCase
19 {
20 /** @dataProvider getXpathLiteralTestData */
21 public function testXpathLiteral($value, $literal)
22 {
23 $this->assertEquals($literal, Translator::getXpathLiteral($value));
24 }
25  
26 /** @dataProvider getCssToXPathTestData */
27 public function testCssToXPath($css, $xpath)
28 {
29 $translator = new Translator();
30 $translator->registerExtension(new HtmlExtension($translator));
31 $this->assertEquals($xpath, $translator->cssToXPath($css, ''));
32 }
33  
34 /** @dataProvider getXmlLangTestData */
35 public function testXmlLang($css, array $elementsId)
36 {
37 $translator = new Translator();
38 $document = new \SimpleXMLElement(file_get_contents(__DIR__.'/Fixtures/lang.xml'));
39 $elements = $document->xpath($translator->cssToXPath($css));
40 $this->assertEquals(count($elementsId), count($elements));
41 foreach ($elements as $element) {
42 $this->assertTrue(in_array($element->attributes()->id, $elementsId));
43 }
44 }
45  
46 /** @dataProvider getHtmlIdsTestData */
47 public function testHtmlIds($css, array $elementsId)
48 {
49 $translator = new Translator();
50 $translator->registerExtension(new HtmlExtension($translator));
51 $document = new \DOMDocument();
52 $document->strictErrorChecking = false;
53 $internalErrors = libxml_use_internal_errors(true);
54 $document->loadHTMLFile(__DIR__.'/Fixtures/ids.html');
55 $document = simplexml_import_dom($document);
56 $elements = $document->xpath($translator->cssToXPath($css));
57 $this->assertCount(count($elementsId), $elementsId);
58 foreach ($elements as $element) {
59 if (null !== $element->attributes()->id) {
60 $this->assertTrue(in_array($element->attributes()->id, $elementsId));
61 }
62 }
63 libxml_clear_errors();
64 libxml_use_internal_errors($internalErrors);
65 }
66  
67 /** @dataProvider getHtmlShakespearTestData */
68 public function testHtmlShakespear($css, $count)
69 {
70 $translator = new Translator();
71 $translator->registerExtension(new HtmlExtension($translator));
72 $document = new \DOMDocument();
73 $document->strictErrorChecking = false;
74 $document->loadHTMLFile(__DIR__.'/Fixtures/shakespear.html');
75 $document = simplexml_import_dom($document);
76 $bodies = $document->xpath('//body');
77 $elements = $bodies[0]->xpath($translator->cssToXPath($css));
78 $this->assertCount($count, $elements);
79 }
80  
81 public function getXpathLiteralTestData()
82 {
83 return array(
84 array('foo', "'foo'"),
85 array("foo's bar", '"foo\'s bar"'),
86 array("foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'),
87 array("foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'),
88 );
89 }
90  
91 public function getCssToXPathTestData()
92 {
93 return array(
94 array('*', '*'),
95 array('e', 'e'),
96 array('*|e', 'e'),
97 array('e|f', 'e:f'),
98 array('e[foo]', 'e[@foo]'),
99 array('e[foo|bar]', 'e[@foo:bar]'),
100 array('e[foo="bar"]', "e[@foo = 'bar']"),
101 array('e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"),
102 array('e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"),
103 array('e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"),
104 array('e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"),
105 array('e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"),
106 array('e:nth-child(1)', "*/*[name() = 'e' and (position() = 1)]"),
107 array('e:nth-last-child(1)', "*/*[name() = 'e' and (position() = last() - 0)]"),
108 array('e:nth-last-child(2n+2)', "*/*[name() = 'e' and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"),
109 array('e:nth-of-type(1)', '*/e[position() = 1]'),
110 array('e:nth-last-of-type(1)', '*/e[position() = last() - 0]'),
111 array('div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"),
112 array('e:first-child', "*/*[name() = 'e' and (position() = 1)]"),
113 array('e:last-child', "*/*[name() = 'e' and (position() = last())]"),
114 array('e:first-of-type', '*/e[position() = 1]'),
115 array('e:last-of-type', '*/e[position() = last()]'),
116 array('e:only-child', "*/*[name() = 'e' and (last() = 1)]"),
117 array('e:only-of-type', 'e[last() = 1]'),
118 array('e:empty', 'e[not(*) and not(string-length())]'),
119 array('e:EmPTY', 'e[not(*) and not(string-length())]'),
120 array('e:root', 'e[not(parent::*)]'),
121 array('e:hover', 'e[0]'),
122 array('e:contains("foo")', "e[contains(string(.), 'foo')]"),
123 array('e:ConTains(foo)', "e[contains(string(.), 'foo')]"),
124 array('e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"),
125 array('e#myid', "e[@id = 'myid']"),
126 array('e:not(:nth-child(odd))', 'e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]'),
127 array('e:nOT(*)', 'e[0]'),
128 array('e f', 'e/descendant-or-self::*/f'),
129 array('e > f', 'e/f'),
130 array('e + f', "e/following-sibling::*[name() = 'f' and (position() = 1)]"),
131 array('e ~ f', 'e/following-sibling::f'),
132 array('div#container p', "div[@id = 'container']/descendant-or-self::*/p"),
133 );
134 }
135  
136 public function getXmlLangTestData()
137 {
138 return array(
139 array(':lang("EN")', array('first', 'second', 'third', 'fourth')),
140 array(':lang("en-us")', array('second', 'fourth')),
141 array(':lang(en-nz)', array('third')),
142 array(':lang(fr)', array('fifth')),
143 array(':lang(ru)', array('sixth')),
144 array(":lang('ZH')", array('eighth')),
145 array(':lang(de) :lang(zh)', array('eighth')),
146 array(':lang(en), :lang(zh)', array('first', 'second', 'third', 'fourth', 'eighth')),
147 array(':lang(es)', array()),
148 );
149 }
150  
151 public function getHtmlIdsTestData()
152 {
153 return array(
154 array('div', array('outer-div', 'li-div', 'foobar-div')),
155 array('DIV', array('outer-div', 'li-div', 'foobar-div')), // case-insensitive in HTML
156 array('div div', array('li-div')),
157 array('div, div div', array('outer-div', 'li-div', 'foobar-div')),
158 array('a[name]', array('name-anchor')),
159 array('a[NAme]', array('name-anchor')), // case-insensitive in HTML:
160 array('a[rel]', array('tag-anchor', 'nofollow-anchor')),
161 array('a[rel="tag"]', array('tag-anchor')),
162 array('a[href*="localhost"]', array('tag-anchor')),
163 array('a[href*=""]', array()),
164 array('a[href^="http"]', array('tag-anchor', 'nofollow-anchor')),
165 array('a[href^="http:"]', array('tag-anchor')),
166 array('a[href^=""]', array()),
167 array('a[href$="org"]', array('nofollow-anchor')),
168 array('a[href$=""]', array()),
169 array('div[foobar~="bc"]', array('foobar-div')),
170 array('div[foobar~="cde"]', array('foobar-div')),
171 array('[foobar~="ab bc"]', array('foobar-div')),
172 array('[foobar~=""]', array()),
173 array('[foobar~=" \t"]', array()),
174 array('div[foobar~="cd"]', array()),
175 array('*[lang|="En"]', array('second-li')),
176 array('[lang|="En-us"]', array('second-li')),
177 // Attribute values are case sensitive
178 array('*[lang|="en"]', array()),
179 array('[lang|="en-US"]', array()),
180 array('*[lang|="e"]', array()),
181 // ... :lang() is not.
182 array(':lang("EN")', array('second-li', 'li-div')),
183 array('*:lang(en-US)', array('second-li', 'li-div')),
184 array(':lang("e")', array()),
185 array('li:nth-child(3)', array('third-li')),
186 array('li:nth-child(10)', array()),
187 array('li:nth-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
188 array('li:nth-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
189 array('li:nth-child(2n+0)', array('second-li', 'fourth-li', 'sixth-li')),
190 array('li:nth-child(+2n+1)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
191 array('li:nth-child(odd)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
192 array('li:nth-child(2n+4)', array('fourth-li', 'sixth-li')),
193 array('li:nth-child(3n+1)', array('first-li', 'fourth-li', 'seventh-li')),
194 array('li:nth-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
195 array('li:nth-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
196 array('li:nth-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
197 array('li:nth-child(n+3)', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
198 array('li:nth-child(-n)', array()),
199 array('li:nth-child(-n-1)', array()),
200 array('li:nth-child(-n+1)', array('first-li')),
201 array('li:nth-child(-n+3)', array('first-li', 'second-li', 'third-li')),
202 array('li:nth-last-child(0)', array()),
203 array('li:nth-last-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
204 array('li:nth-last-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
205 array('li:nth-last-child(2n+2)', array('second-li', 'fourth-li', 'sixth-li')),
206 array('li:nth-last-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
207 array('li:nth-last-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
208 array('li:nth-last-child(n-3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
209 array('li:nth-last-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
210 array('li:nth-last-child(n+3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li')),
211 array('li:nth-last-child(-n)', array()),
212 array('li:nth-last-child(-n-1)', array()),
213 array('li:nth-last-child(-n+1)', array('seventh-li')),
214 array('li:nth-last-child(-n+3)', array('fifth-li', 'sixth-li', 'seventh-li')),
215 array('ol:first-of-type', array('first-ol')),
216 array('ol:nth-child(1)', array('first-ol')),
217 array('ol:nth-of-type(2)', array('second-ol')),
218 array('ol:nth-last-of-type(1)', array('second-ol')),
219 array('span:only-child', array('foobar-span')),
220 array('li div:only-child', array('li-div')),
221 array('div *:only-child', array('li-div', 'foobar-span')),
222 array('p:only-of-type', array('paragraph')),
223 array('a:empty', array('name-anchor')),
224 array('a:EMpty', array('name-anchor')),
225 array('li:empty', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li')),
226 array(':root', array('html')),
227 array('html:root', array('html')),
228 array('li:root', array()),
229 array('* :root', array()),
230 array('*:contains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
231 array(':CONtains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
232 array('*:contains("LInk")', array()), // case sensitive
233 array('*:contains("e")', array('html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em')),
234 array('*:contains("E")', array()), // case-sensitive
235 array('.a', array('first-ol')),
236 array('.b', array('first-ol')),
237 array('*.a', array('first-ol')),
238 array('ol.a', array('first-ol')),
239 array('.c', array('first-ol', 'third-li', 'fourth-li')),
240 array('*.c', array('first-ol', 'third-li', 'fourth-li')),
241 array('ol *.c', array('third-li', 'fourth-li')),
242 array('ol li.c', array('third-li', 'fourth-li')),
243 array('li ~ li.c', array('third-li', 'fourth-li')),
244 array('ol > li.c', array('third-li', 'fourth-li')),
245 array('#first-li', array('first-li')),
246 array('li#first-li', array('first-li')),
247 array('*#first-li', array('first-li')),
248 array('li div', array('li-div')),
249 array('li > div', array('li-div')),
250 array('div div', array('li-div')),
251 array('div > div', array()),
252 array('div>.c', array('first-ol')),
253 array('div > .c', array('first-ol')),
254 array('div + div', array('foobar-div')),
255 array('a ~ a', array('tag-anchor', 'nofollow-anchor')),
256 array('a[rel="tag"] ~ a', array('nofollow-anchor')),
257 array('ol#first-ol li:last-child', array('seventh-li')),
258 array('ol#first-ol *:last-child', array('li-div', 'seventh-li')),
259 array('#outer-div:first-child', array('outer-div')),
260 array('#outer-div :first-child', array('name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href')),
261 array('a[href]', array('tag-anchor', 'nofollow-anchor')),
262 array(':not(*)', array()),
263 array('a:not([href])', array('name-anchor')),
264 array('ol :Not(li[class])', array('first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li')),
265 // HTML-specific
266 array(':link', array('link-href', 'tag-anchor', 'nofollow-anchor', 'area-href')),
267 array(':visited', array()),
268 array(':enabled', array('link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href')),
269 array(':disabled', array('checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled')),
270 array(':checked', array('checkbox-checked', 'checkbox-disabled-checked')),
271 );
272 }
273  
274 public function getHtmlShakespearTestData()
275 {
276 return array(
277 array('*', 246),
278 array('div:contains(CELIA)', 26),
279 array('div:only-child', 22), // ?
280 array('div:nth-child(even)', 106),
281 array('div:nth-child(2n)', 106),
282 array('div:nth-child(odd)', 137),
283 array('div:nth-child(2n+1)', 137),
284 array('div:nth-child(n)', 243),
285 array('div:last-child', 53),
286 array('div:first-child', 51),
287 array('div > div', 242),
288 array('div + div', 190),
289 array('div ~ div', 190),
290 array('body', 1),
291 array('body div', 243),
292 array('div', 243),
293 array('div div', 242),
294 array('div div div', 241),
295 array('div, div, div', 243),
296 array('div, a, span', 243),
297 array('.dialog', 51),
298 array('div.dialog', 51),
299 array('div .dialog', 51),
300 array('div.character, div.dialog', 99),
301 array('div.direction.dialog', 0),
302 array('div.dialog.direction', 0),
303 array('div.dialog.scene', 1),
304 array('div.scene.scene', 1),
305 array('div.scene .scene', 0),
306 array('div.direction .dialog ', 0),
307 array('div .dialog .direction', 4),
308 array('div.dialog .dialog .direction', 4),
309 array('#speech5', 1),
310 array('div#speech5', 1),
311 array('div #speech5', 1),
312 array('div.scene div.dialog', 49),
313 array('div#scene1 div.dialog div', 142),
314 array('#scene1 #speech1', 1),
315 array('div[class]', 103),
316 array('div[class=dialog]', 50),
317 array('div[class^=dia]', 51),
318 array('div[class$=log]', 50),
319 array('div[class*=sce]', 1),
320 array('div[class|=dialog]', 50), // ? Seems right
321 array('div[class!=madeup]', 243), // ? Seems right
322 array('div[class~=dialog]', 51), // ? Seems right
323 );
324 }
325 }