Skip to content

Commit a664e77

Browse files
committed
Merge branch 'super-dm3-main'
2 parents 020143c + bb27bf0 commit a664e77

File tree

4 files changed

+50
-91
lines changed

4 files changed

+50
-91
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ docs/*
1212
doc/*
1313
test/fakepear
1414
vendor/
15-
composer.lock
15+
composer.lock
16+
.phpunit.result.cache
17+
.idea/

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ QueryPath Changelog
44
# 4.0.1
55

66
- Only define global functions qp(), htmlqp(), and html5qp() if they haven't been defined already.
7+
- Fix for :nth-child(n+B) to select B-th and all following elements
8+
- Fix for :nth-child(-n+B) to select first B elements
9+
- Update PHPUnit Test Suite to use @dataProvider in testPseudoClassNthChild() to reduce code repetition
710

811
# 4.0.0
912

src/CSS/QueryPathEventHandler.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,15 @@ protected function parseAnB($rule)
734734
throw new ParseException("nth-child value is invalid.");
735735
}
736736

737-
// Each of these is legal: 1, -1, and -. '-' is shorthand for -1.
737+
// Each of these is legal: 1, -1, - and <empty>. '-' is shorthand for -1. <empty> is shorthand for 1
738738
$aVal = trim($rule[0]);
739-
$aVal = ($aVal == '-') ? -1 : (int) $aVal;
739+
if ($aVal === '') {
740+
$aVal = 1;
741+
} elseif ($aVal === '-') {
742+
$aVal = -1;
743+
} else {
744+
$aVal = (int) $aVal;
745+
}
740746

741747
$bVal = ! empty($rule[1]) ? (int) trim($rule[1]) : 0;
742748

tests/QueryPath/CSS/QueryPathEventHandlerTest.php

Lines changed: 36 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,34 @@ public function testChildAtIndex() {
615615
$this->assertEquals('one', $this->nthMatch($matches, 1)->getAttribute('id'));
616616
}*/
617617

618-
public function testPseudoClassNthChild()
618+
public function nthChildProvider(): array
619+
{
620+
return [
621+
[':root :even', 3, 'four' ], // full list
622+
['i:even', 2, 'four' ], // restricted to specific element
623+
['i:odd', 3, 'three' ], // restricted to specific element, odd this time
624+
['i:nth-child(odd)', 3, 'three' ], // odd
625+
['i:nth-child(2n+1)', 3, 'three' ], // odd, equiv to 2n + 1
626+
['i:nth-child(2n-1)', 3, 'three' ], // odd, equiv to 2n + 1
627+
['i:nth-child(2n)', 2, 'four' ], // even
628+
['i:nth-child(-2n)', 0, null ], // empty list (An+B will only accept positive results and without B this will always be negative)
629+
['i:nth-child(-2n+4)', 2, 'two', 0 ], // two and four only
630+
['i:nth-child(-2n+4)', 2, 'four', 1 ], // two and four only
631+
['i:nth-child(4n)', 1, 'four', 0 ], // every fourth row
632+
['i:nth-child(4n+1)', 2, 'five' ], // first of every four rows
633+
['i:nth-child(1)', 1, 'one', 0 ], // first row
634+
['i:nth-child(0n-0)', 0, null ], // empty list
635+
['i:nth-child(n+3)', 3, 'four' ], // third+ lines
636+
['i:nth-child(-n+3)', 3, 'two' ], // first three elements
637+
['i:nth-child(-n+4)', 4, 'two' ], // first four lines
638+
['i:nth-child(0n+2)', 1, 'two', 0 ], // second element in a group of siblings
639+
];
640+
}
641+
642+
/**
643+
* @dataProvider nthChildProvider
644+
*/
645+
public function testPseudoClassNthChild($selector, $matchesCount, $matchId, $matchIndex = 1)
619646
{
620647
$xml = '<?xml version="1.0" ?>
621648
<test>
@@ -631,95 +658,16 @@ public function testPseudoClassNthChild()
631658

632659
// Test full list
633660
$handler = new QueryPathEventHandler($doc);
634-
$handler->find(':root :even');
635-
$matches = $handler->getMatches();
636-
$this->assertEquals(3, $matches->count());
637-
$this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id'));
638-
639-
// Test restricted to specific element
640-
$handler = new QueryPathEventHandler($doc);
641-
$handler->find('i:even');
642-
$matches = $handler->getMatches();
643-
$this->assertEquals(2, $matches->count());
644-
$this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id'));
645-
646-
// Test restricted to specific element, odd this time
647-
$handler = new QueryPathEventHandler($doc);
648-
$handler->find('i:odd');
649-
$matches = $handler->getMatches();
650-
$this->assertEquals(3, $matches->count());
651-
$this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id'));
652-
653-
// Test nth-child(odd)
654-
$handler = new QueryPathEventHandler($doc);
655-
$handler->find('i:nth-child(odd)');
656-
$matches = $handler->getMatches();
657-
$this->assertEquals(3, $matches->count());
658-
$this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id'));
659-
660-
// Test nth-child(2n+1)
661-
$handler = new QueryPathEventHandler($doc);
662-
$handler->find('i:nth-child(2n+1)');
663-
$matches = $handler->getMatches();
664-
$this->assertEquals(3, $matches->count());
665-
$this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id'));
666-
667-
// Test nth-child(2n) (even)
668-
$handler = new QueryPathEventHandler($doc);
669-
$handler->find('i:nth-child(2n)');
661+
$handler->find($selector);
670662
$matches = $handler->getMatches();
671-
$this->assertEquals(2, $matches->count());
672-
$this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id'));
673-
674-
// Not totally sure what should be returned here
675-
// Test nth-child(-2n)
676-
// $handler = new QueryPathEventHandler($doc);
677-
// $handler->find('i:nth-child(-2n)');
678-
// $matches = $handler->getMatches();
679-
// $this->assertEquals(2, $matches->count());
680-
// $this->assertEquals('four', $this->nthMatch($matches, 1)->getAttribute('id'));
681-
682-
// Test nth-child(2n-1) (odd, equiv to 2n + 1)
683-
$handler = new QueryPathEventHandler($doc);
684-
$handler->find('i:nth-child(2n-1)');
685-
$matches = $handler->getMatches();
686-
$this->assertEquals(3, $matches->count());
687-
$this->assertEquals('three', $this->nthMatch($matches, 1)->getAttribute('id'));
688-
689-
// Test nth-child(4n) (every fourth row)
690-
$handler = new QueryPathEventHandler($doc);
691-
$handler->find('i:nth-child(4n)');
692-
$matches = $handler->getMatches();
693-
$this->assertEquals(1, $matches->count());
694-
$this->assertEquals('four', $this->nthMatch($matches, 0)->getAttribute('id'));
695-
696-
// Test nth-child(4n+1) (first of every four rows)
697-
$handler = new QueryPathEventHandler($doc);
698-
$handler->find('i:nth-child(4n+1)');
699-
$matches = $handler->getMatches();
700-
// Should match rows one and five
701-
$this->assertEquals(2, $matches->count());
702-
$this->assertEquals('five', $this->nthMatch($matches, 1)->getAttribute('id'));
703-
704-
// Test nth-child(1) (First row)
705-
$handler = new QueryPathEventHandler($doc);
706-
$handler->find('i:nth-child(1)');
707-
$matches = $handler->getMatches();
708-
$this->assertEquals(1, $matches->count());
709-
$this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
710-
711-
// Test nth-child(0n-0) (Empty list)
712-
$handler = new QueryPathEventHandler($doc);
713-
$handler->find('i:nth-child(0n-0)');
714-
$matches = $handler->getMatches();
715-
$this->assertEquals(0, $matches->count());
716-
717-
// Test nth-child(-n+3) (First three lines)
718-
// $handler = new QueryPathEventHandler($doc);
719-
// $handler->find('i:nth-child(-n+3)');
720-
// $matches = $handler->getMatches();
721-
// $this->assertEquals(3, $matches->count());
663+
$this->assertEquals($matchesCount, $matches->count());
664+
if ($matchesCount) {
665+
$this->assertEquals($matchId, $this->nthMatch($matches, $matchIndex)->getAttribute('id'));
666+
}
667+
}
722668

669+
public function testPseudoClassNthChildNested()
670+
{
723671
$xml = '<?xml version="1.0" ?>
724672
<test>
725673
<i class="odd" id="one"/>

0 commit comments

Comments
 (0)