From 9a9c04512e5dcb77c7fe5d850e3f2a0250cc160e Mon Sep 17 00:00:00 2001 From: emkael Date: Wed, 18 Jan 2017 20:07:16 +0100 Subject: * Motor Sport Magazine feed provider --- .../QueryPath/CSS/QueryPathEventHandlerTest.php | 1439 ++++++++++++++++++++ 1 file changed, 1439 insertions(+) create mode 100644 lib/querypath/test/Tests/QueryPath/CSS/QueryPathEventHandlerTest.php (limited to 'lib/querypath/test/Tests/QueryPath/CSS/QueryPathEventHandlerTest.php') diff --git a/lib/querypath/test/Tests/QueryPath/CSS/QueryPathEventHandlerTest.php b/lib/querypath/test/Tests/QueryPath/CSS/QueryPathEventHandlerTest.php new file mode 100644 index 0000000..01af591 --- /dev/null +++ b/lib/querypath/test/Tests/QueryPath/CSS/QueryPathEventHandlerTest.php @@ -0,0 +1,1439 @@ + + + + This is the title + + +
+
+
+ Inner text. +
+
+
+ Nada +

8

+ + + + '; + + private function firstMatch($matches) { + $matches->rewind(); + return $matches->current(); + } + private function nthMatch($matches, $n = 0) { + foreach ($matches as $m) { + if ($matches->key() == $n) return $m; + } + } + + public function testGetMatches() { + // Test root element: + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test handing it a DOM Document + $handler = new QueryPathEventHandler($doc); + $matches = $handler->getMatches(); + $this->assertTrue($matches->count() == 1); + $match = $this->firstMatch($matches); + $this->assertEquals('test', $match->tagName); + + // Test handling single element + $root = $doc->documentElement; + $handler = new QueryPathEventHandler($root); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('test', $match->tagName); + + // Test handling a node list + $eles = $doc->getElementsByTagName('inside'); + $handler = new QueryPathEventHandler($eles); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('inside', $match->tagName); + + // Test handling an array of elements + $eles = $doc->getElementsByTagName('inside'); + $array = array(); + foreach ($eles as $ele) $array[] = $ele; + $handler = new QueryPathEventHandler($array); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('inside', $match->tagName); + } + + /** + * @expectedException \QueryPath\CSS\ParseException + */ + public function testEmptySelector() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Basic test + $handler = new QueryPathEventHandler($doc); + $handler->find(''); + $matches = $handler->getMatches(); + $this->assertEquals(0, $matches->count()); + } + + public function testElementNS() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Basic test + $handler = new QueryPathEventHandler($doc); + $handler->find('t|inside'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('t:inside', $match->tagName); + + // Basic test + $handler = new QueryPathEventHandler($doc); + $handler->find('t|test'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('t:test', $match->tagName); + } + + + /** + * @expectedException \QueryPath\CSS\ParseException + */ + public function testFailedElementNS() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('myns\:mytest'); + } + + public function testElement() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Basic test + $handler = new QueryPathEventHandler($doc); + $handler->find('inside'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('inside', $match->tagName); + + $doc = new \DomDocument(); + $doc->loadXML($this->xml); + + // Test getting nested + $handler = new QueryPathEventHandler($doc); + $handler->find('div'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('div', $match->tagName); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test getting a list + $handler = new QueryPathEventHandler($doc); + $handler->find('li'); + $matches = $handler->getMatches(); + $this->assertEquals(10, $matches->count()); + $match = $this->firstMatch($matches); + //$this->assertEquals('div', $match->tagName); + $this->assertEquals('li-one', $match->getAttribute('id')); + + // Test getting the root element + $handler = new QueryPathEventHandler($doc); + $handler->find('html'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('html', $match->tagName); + } + + public function testElementId() { + // Test root element: + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#first'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('inside', $match->tagName); + + // Test a search with restricted scope: + $handler = new QueryPathEventHandler($doc); + $handler->find('inside#first'); + $matches = $handler->getMatches(); + + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('inside', $match->tagName); + + } + + public function testAnyElementInNS() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test handing it a DOM Document + $handler = new QueryPathEventHandler($doc); + $handler->find('ns1|*'); + $matches = $handler->getMatches(); + + $this->assertEquals(3, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('ns1:test', $match->tagName); + + // Test Issue #30: + $xml = ' + + + Test + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('ns1|test>*'); + $matches = $handler->getMatches(); + + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('ns1:inside', $match->tagName); + } + + public function testAnyElement() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test handing it a DOM Document + $handler = new QueryPathEventHandler($doc); + $handler->find('*'); + $matches = $handler->getMatches(); + + $this->assertEquals(3, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('test', $match->tagName); + + $doc = new \DomDocument(); + $doc->loadXML($this->xml); + + // Test handing it a DOM Document + $handler = new QueryPathEventHandler($doc); + $handler->find('#two *'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('three', $match->getAttribute('id')); + + // Regression for issue #30 + $handler = new QueryPathEventHandler($doc); + $handler->find('#one>*'); + $matches = $handler->getMatches(); + + $this->assertEquals(1, $matches->count(), 'Should match just top div.'); + $match = $this->firstMatch($matches); + $this->assertEquals('two', $match->getAttribute('id'), 'Should match ID #two'); + } + + public function testElementClass() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test basic class + $handler = new QueryPathEventHandler($doc); + $handler->find('.foo'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test class in element + $doc = new \DomDocument(); + $doc->loadXML($this->xml); + $handler = new QueryPathEventHandler($doc); + $handler->find('li.Odd'); + $matches = $handler->getMatches(); + $this->assertEquals(5, $matches->count()); + $match = $this->nthMatch($matches, 4); + $this->assertEquals('li-nine', $match->getAttribute('id')); + + // Test ID/class combo + $handler = new QueryPathEventHandler($doc); + $handler->find('.Odd#li-nine'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('li-nine', $match->getAttribute('id')); + + } + + public function testDirectDescendant() { + $xml = ' + + + Text + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test direct descendent + $handler = new QueryPathEventHandler($doc); + $handler->find('test > inside'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->nthMatch($matches, 1); + $this->assertEquals('two', $match->getAttribute('id')); + + } + + public function testAttribute() { + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test match on attr name + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test broken form + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[@name]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test match on attr name and equals value + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name="antidisestablishmentarianism"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test match on containsInString + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name*="disestablish"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test match on beginsWith + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name^="anti"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test match on endsWith + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name$="ism"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test containsWithSpace + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name~="dis"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + // Test containsWithHyphen + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('inside[name|="us"]'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + } + + public function testPseudoClassLang() { + + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':lang(en-us)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('inside:lang(en)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('inside:lang(us)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + $xml = 'Text'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':lang(us)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->nthMatch($matches, 1); + $this->assertEquals('two', $match->getAttribute('id')); + + $xml = ' + + Text + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':lang(us)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $match = $this->nthMatch($matches, 1); + $this->assertEquals('two', $match->getAttribute('id')); + } + + public function testPseudoClassEnabledDisabledChecked() { + $xml = ' + + Text + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':enabled'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('one', $match->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':disabled'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('two', $match->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':checked()'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $match = $this->firstMatch($matches); + $this->assertEquals('three', $match->getAttribute('id')); + } + + public function testPseudoClassLink() { + $xml = ''; + $qp = qp($xml, ':link'); + $this->assertEquals(2, $qp->size()); + } + + public function testPseudoClassXReset() { + $xml = ' + + Text + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('inside'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $handler->find(':x-reset'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('test', $this->firstMatch($matches)->tagName); + } + + public function testPseudoClassRoot() { + $xml = ' + + Text + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + $start = $doc->getElementsByTagName('inside'); + + // Start "deep in the doc" and traverse backward. + $handler = new QueryPathEventHandler($start); + $handler->find(':root'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('test', $this->firstMatch($matches)->tagName); + } + + // Test removed so I can re-declare + // listPeerElements as private. + public function xtestListPeerElements() { + $xml = ' + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test full list + $handler = new QueryPathEventHandler($doc); + $handler->find('#one'); + $matches = $handler->getMatches(); + $peers = $handler->listPeerElements($this->firstMatch($matches)); + $this->assertEquals(6, count($peers)); + } + /* + public function testChildAtIndex() { + $xml = ' + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test full list + $handler = new QueryPathEventHandler($doc); + $handler->find('test:child-at-index(1)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->nthMatch($matches, 1)->getAttribute('id')); + }*/ + + public function testPseudoClassNthChild() { + $xml = ' + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test full list + $handler = new QueryPathEventHandler($doc); + $handler->find(':root :even'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test restricted to specific element + $handler = new QueryPathEventHandler($doc); + $handler->find('i:even'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test restricted to specific element, odd this time + $handler = new QueryPathEventHandler($doc); + $handler->find('i:odd'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(odd) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(odd)'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(2n+1) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(2n+1)'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(2n) (even) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(2n)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Not totally sure what should be returned here + // Test nth-child(-2n) + // $handler = new QueryPathEventHandler($doc); + // $handler->find('i:nth-child(-2n)'); + // $matches = $handler->getMatches(); + // $this->assertEquals(2, $matches->count()); + // $this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(2n-1) (odd, equiv to 2n + 1) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(2n-1)'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(4n) (every fourth row) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(4n)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('four', $this->nthMatch($matches, 0)->getAttribute('id')); + + // Test nth-child(4n+1) (first of every four rows) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(4n+1)'); + $matches = $handler->getMatches(); + // Should match rows one and five + $this->assertEquals(2, $matches->count()); + $this->assertEquals('five', $this->nthMatch($matches, 1)->getAttribute('id')); + + // Test nth-child(1) (First row) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(1)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + // Test nth-child(0n-0) (Empty list) + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(0n-0)'); + $matches = $handler->getMatches(); + $this->assertEquals(0, $matches->count()); + + // Test nth-child(-n+3) (First three lines) + // $handler = new QueryPathEventHandler($doc); + // $handler->find('i:nth-child(-n+3)'); + // $matches = $handler->getMatches(); + // $this->assertEquals(3, $matches->count()); + + $xml = ' + + + + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test nested items. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-child(odd)'); + $matches = $handler->getMatches(); + $this->assertEquals(4, $matches->count()); + $matchIDs = array(); + foreach ($matches as $m) { + $matchIDs[] = $m->getAttribute('id'); + } +// $matchIDs = sort($matchIDs); + $this->assertEquals(array('one', 'three', 'inner-one', 'five'), $matchIDs); + //$this->assertEquals('inner-one', $matches[3]->getAttribute('id')); + + } + public function testPseudoClassOnlyChild() { + $xml = ' + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:only-child'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $xml = ' + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:only-child'); + $matches = $handler->getMatches(); + $this->assertEquals(0, $matches->count()); + //$this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassOnlyOfType() { + // TODO: Added this late (it was missing in original test), + // and I'm not sure if the assumed behavior is correct. + + $xml = ' + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:only-of-type'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + + $xml = ' + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:only-of-type'); + $matches = $handler->getMatches(); + $this->assertEquals(0, $matches->count()); + } + + public function testPseudoClassFirstChild() { + $xml = ' + + + + + + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('#four > i:first-child'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('inner-one', $this->firstMatch($matches)->getAttribute('id')); + + // Test for two last children + $handler = new QueryPathEventHandler($doc); + $handler->find('i:first-child'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-one', $this->nthMatch($matches, 1)->getAttribute('id')); + } + + public function testPseudoClassLastChild() { + //print '----' . PHP_EOL; + $xml = ' + + + + + + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test single last child. + $handler = new QueryPathEventHandler($doc); + $handler->find('#four > i:last-child'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('inner-four', $this->nthMatch($matches, 0)->getAttribute('id')); + + // Test for two last children + $handler = new QueryPathEventHandler($doc); + $handler->find('i:last-child'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-four', $this->nthMatch($matches, 0)->getAttribute('id')); + $this->assertEquals('five', $this->nthMatch($matches, 1)->getAttribute('id')); + } + + public function testPseudoClassNthLastChild() { + $xml = ' + + + + + + + + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('#four > i:nth-last-child(odd)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-two', $this->nthMatch($matches, 0)->getAttribute('id')); + $this->assertEquals('inner-four', $this->nthMatch($matches, 1)->getAttribute('id')); + + // According to spec, this should be last two elements. + $handler = new QueryPathEventHandler($doc); + $handler->find('#four > i:nth-last-child(-1n+2)'); + $matches = $handler->getMatches(); + //print $this->firstMatch($matches)->getAttribute('id'); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-three', $this->nthMatch($matches, 0)->getAttribute('id')); + $this->assertEquals('inner-four', $this->nthMatch($matches, 1)->getAttribute('id')); + } + + public function testPseudoClassFirstOfType() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:first-of-type(odd)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassNthFirstOfType() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:first-of-type(1)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassLastOfType() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:last-of-type(odd)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('three', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoNthClassLastOfType() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-last-of-type(1)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('three', $this->firstMatch($matches)->getAttribute('id')); + + + // Issue #56: an+b not working. + $xml = ' + +
I am the first div.
+
I am the second div.
+
I am the third div.
+
I am the fourth div.
+
I am the fifth div.
+
I am the sixth div.
+
I am the seventh div.
+
'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('div:nth-last-of-type(-n+3)'); + $matches = $handler->getMatches(); + + $this->assertEquals(3, $matches->count()); + $this->assertEquals('five', $this->firstMatch($matches)->getAttribute('id')); + + } + + public function testPseudoClassEmpty() { + $xml = ' + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('n:empty'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('i:empty'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassFirst() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:first'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassLast() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:last'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('three', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassGT() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:gt(1)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + public function testPseudoClassLT() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + // Test alternate rows from the end. + $handler = new QueryPathEventHandler($doc); + $handler->find('i:lt(3)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('one', $this->nthMatch($matches,0)->getAttribute('id')); + $this->assertEquals('two', $this->nthMatch($matches,1)->getAttribute('id')); + } + public function testPseudoClassNTH() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth(2)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('i:eq(2)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + public function testPseudoClassNthOfType() { + $xml = ' + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('i:nth-of-type(2)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassFormElements() { + $form = array('text', 'radio', 'checkbox', 'button', 'password'); + $xml = ' + + + '; + + foreach ($form as $item) { + $doc = new \DomDocument(); + $doc->loadXML(sprintf($xml, $item)); + + $handler = new QueryPathEventHandler($doc); + $handler->find(':' . $item); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + } + + public function testPseudoClassHeader() { + $xml = ' + +

+

+

+ '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('test :header'); + $matches = $handler->getMatches(); + $this->assertEquals(3, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 2)->getAttribute('id')); + } + + public function testPseudoClassContains() { + $xml = ' + +

This is text.

+

More text

+
'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains(This is text.)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('* :contains(More text)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count(), 'Matches two instance of same text?'); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains("This is text.")'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count(), 'Quoted text matches unquoted pcdata'); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains(\\\'This is text.\\\')'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count(), 'One match for quoted string.'); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + // Test for issue #32 + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains(text)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count(), 'Two matches for fragment of string.'); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + } + + public function testPseudoClassContainsExactly() { + $xml = ' + +

This is text.

+

More text

+
'; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains(This is text.)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('* :contains(More text)'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count(), 'Matches two instance of same text.'); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains("This is text.")'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count(), 'Quoted text matches unquoted pcdata'); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('p:contains(\\\'This is text.\\\')'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count(), 'One match for quoted string.'); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassHas() { + $xml = ' + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer:has(inner)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoClassNot() { + $xml = ' + + + + + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer:not(#one)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer:not(inner)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer:not(.notMe)'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testPseudoElement() { + $xml = ' + + Texts + + More text + + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer::first-letter'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('T', $this->firstMatch($matches)->textContent); + + $handler = new QueryPathEventHandler($doc); + $handler->find('outer::first-line'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('Texts', $this->firstMatch($matches)->textContent); + } + + public function testAdjacent() { + $xml = ' + +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#one + li'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id')); + + // Tell it to ignore whitespace nodes. + $doc->loadXML($xml, LIBXML_NOBLANKS); + + // Test with whitespace sensitivity weakened. + $handler = new QueryPathEventHandler($doc); + $handler->find('#four + li'); + $matches = $handler->getMatches(); + $this->assertEquals(1, $matches->count()); + $this->assertEquals('five', $this->firstMatch($matches)->getAttribute('id')); + } + public function testAnotherSelector() { + $xml = ' + +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#one, #two'); + $matches = $handler->getMatches(); + //print $this->firstMatch($matches)->getAttribute('id') . PHP_EOL; + $this->assertEquals(2, $matches->count()); + $this->assertEquals('two', $this->nthMatch($matches, 1)->getAttribute('id')); + + } + public function testSibling() { + $xml = ' + +
  • +
  • +
  • + +
  • +
  • +
  • +
  • +
  • +
  • + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#one ~ li'); + $matches = $handler->getMatches(); + //print $this->firstMatch($matches)->getAttribute('id') . PHP_EOL; + $this->assertEquals(4, $matches->count()); + $this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#two ~ li'); + $matches = $handler->getMatches(); + //print $this->firstMatch($matches)->getAttribute('id') . PHP_EOL; + $this->assertEquals(3, $matches->count()); + //$this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('#inner-one > li ~ il'); + $matches = $handler->getMatches(); + //print $this->firstMatch($matches)->getAttribute('id') . PHP_EOL; + $this->assertEquals(1, $matches->count()); + $this->assertEquals('inner-inner-two', $this->firstMatch($matches)->getAttribute('id')); + } + + public function testAnyDescendant() { + $xml = ' + +
  • +
  • +
  • + +
  • +
  • +
  • +
  • +
  • +
  • + '; + $doc = new \DomDocument(); + $doc->loadXML($xml); + + $handler = new QueryPathEventHandler($doc); + $handler->find('*'); + $matches = $handler->getMatches(); + $this->assertEquals(11, $matches->count()); + + $handler = new QueryPathEventHandler($doc); + $handler->find('*.foo'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-inner-one', $this->nthMatch($matches, 1)->getAttribute('id')); + + $handler = new QueryPathEventHandler($doc); + $handler->find('test > li *.foo'); + $matches = $handler->getMatches(); + $this->assertEquals(2, $matches->count()); + $this->assertEquals('inner-inner-one', $this->nthMatch($matches, 1)->getAttribute('id')); + } +} -- cgit v1.2.3