Skip to content

Commit

Permalink
Improve selector integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sirreal committed Dec 5, 2024
1 parent 24a5bb8 commit 935aafa
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 73 deletions.
62 changes: 34 additions & 28 deletions tests/phpunit/tests/html-api/wpHtmlProcessor-select.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,54 +26,60 @@ public function test_select_miss() {
*
* @dataProvider data_selectors
*/
public function test_select( string $html, string $selector ) {
public function test_select_all( string $html, string $selector, int $match_count ) {
$processor = WP_HTML_Processor::create_full_parser( $html );
$this->assertTrue( $processor->select( $selector ) );
$this->assertTrue( $processor->get_attribute( 'match' ) );
$count = 0;
foreach ( $processor->select_all( $selector ) as $_ ) {
$breadcrumb_string = implode( ', ', $processor->get_breadcrumbs() );
$this->assertTrue(
$processor->get_attribute( 'match' ),
"Matched unexpected tag {$processor->get_tag()} @ {$breadcrumb_string}"
);
++$count;
}
$this->assertSame( $match_count, $count, 'Did not match expected number of tags.' );
}

/**
* Data provider.
*
* Most selectors are covered by the tag processor selector tests.
* This suite should focus on complex selectors.
*
* @return array
*/
public static function data_selectors(): array {
return array(
'simple type' => array( '<div match>', 'div' ),
'any type' => array( '<html match>', '*' ),
'simple class' => array( '<div class="x" match>', '.x' ),
'simple id' => array( '<div id="x" match>', '#x' ),
'simple attribute' => array( '<div att match>', '[att]' ),
'attribute value' => array( '<div att="val" match>', '[att=val]' ),
'attribute quoted value' => array( '<div att="::" match>', '[att="::"]' ),
'complex any descendant' => array( '<section><div match>', 'section *' ),
'complex any child' => array( '<section><div match>', 'section > *' ),

'list' => array( '<div><p match>', 'a, p' ),
'compound' => array( '<div att><section att="foo bar" match>', 'section[att~="bar"]' ),
'any descendant' => array( '<section><p match><i match><em match><p match>', 'section *', 4 ),
'any child 1' => array( '<section><p match><i><em><p match>', 'section > *', 2 ),
'any child 2' => array( '<div><section match><div>', 'div > *', 1 ),
);
}

/**
* @ticket TBD
*
* @expectedIncorrectUsage WP_HTML_Processor::select_all
*
* @dataProvider data_invalid_selectors
*/
public function test_select_all() {
$processor = WP_HTML_Processor::create_full_parser( '<div match><p class="x" match><svg><rect match/></svg><i id="y" match></i>' );
$count = 0;
foreach ( $processor->select_all( 'div, .x, svg>rect, #y' ) as $_ ) {
++$count;
$this->assertTrue( $processor->get_attribute( 'match' ) );
}
$this->assertSame( 4, $count );
public function test_invalid_selector( string $selector ) {
$processor = WP_HTML_Processor::create_fragment( 'irrelevant' );
$this->assertFalse( $processor->select( $selector ) );
}

/**
* @ticket TBD
* Data provider.
*
* @expectedIncorrectUsage WP_HTML_Processor::select_all
* @return array
*/
public function test_invalid_selector() {
$processor = WP_HTML_Processor::create_fragment( 'irrelevant' );
$this->assertFalse( $processor->select( '[invalid!selector]' ) );
public static function data_invalid_selectors(): array {
return array(
'invalid selector' => array( '[invalid!selector]' ),

// The class selectors below are not allowed in non-final position.
'unsupported child selector' => array( '.parent > .child' ),
'unsupported descendant selector' => array( '.ancestor .descendant' ),
);
}
}
83 changes: 38 additions & 45 deletions tests/phpunit/tests/html-api/wpHtmlTagProcessor-select.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ public function test_select_miss() {
*
* @dataProvider data_selectors
*/
public function test_select( string $html, string $selector ) {
public function test_select( string $html, string $selector, int $match_count ) {
$processor = new WP_HTML_Tag_Processor( $html );
$this->assertTrue( $processor->select( $selector ) );
$this->assertTrue( $processor->get_attribute( 'match' ) );
$count = 0;
foreach ( $processor->select_all( $selector ) as $_ ) {
$this->assertTrue(
$processor->get_attribute( 'match' ),
"Matched unexpected tag {$processor->get_tag()}"
);
++$count;
}
$this->assertSame( $match_count, $count, 'Did not match expected number of tags.' );
}

/**
Expand All @@ -39,58 +46,44 @@ public function test_select( string $html, string $selector ) {
*/
public static function data_selectors(): array {
return array(
'simple type' => array( '<p><div match>', 'div' ),
'any type' => array( '<div match>', '*' ),
'simple class' => array( '<div><div class="x" match>', '.x' ),
'simple id' => array( '<div><div id="x" match>', '#x' ),
'boolean attribute' => array( '<div tta><div att match>', '[att]' ),
'boolean attribute with string match' => array( '<div tta><div att match>', '[att=""]' ),
'simple type' => array( '<div match><div match><span>', 'div', 2 ),
'any type' => array( '<div match><span match>', '*', 2 ),
'simple class' => array( '<div><div class="x" match><span><span class="x" match>', '.x', 2 ),
'simple id' => array( '<div><div id="x" match><span id="x" match>', '#x', 2 ),

'attribute value' => array( '<div att="v"><div att="val" match>', '[att=val]' ),
'attribute quoted value' => array( '<div att><div att="::" match>', '[att="::"]' ),
'attribute case insensitive' => array( '<div att="value"><div att="val" match>', '[att="VAL"i]' ),
'attribute case sensitive mod' => array( '<div att="VAL"><div att="val" match>', '[att="val"s]' ),
'attribute presence' => array( '<div tta><div att match><span att="foo" match>', '[att]', 2 ),
'attribute empty string match' => array( '<div tta><div att match><span match att=>', '[att=""]', 2 ),
'attribute value' => array( '<div att="v"><div att="val" match><p match att=val>', '[att=val]', 2 ),
'attribute quoted value' => array( '<div att><div att="::" match><p att=\'::\' match>', '[att="::"]', 2 ),
'attribute case insensitive' => array( '<div att="value"><div att="val" match><p match att=VaL>', '[att="VAL"i]', 2 ),
'attribute case sensitive mod' => array( '<div att="VAL"><div att="val" match><p att=val match>', '[att="val"s]', 2 ),

'attribute one of' => array( '<div att="a B c"><div att="a b c" match>', '[att~="b"]' ),
'attribute one of insensitive' => array( '<div att="a c"><div att="a B c" match>', '[att~="b"i]' ),
'attribute one of mod sensitive' => array( '<div att="a B c"><div att="a b c" match>', '[att~="b"s]' ),
'attribute one of whitespace cases' => array( "<div att=' a'><div att='\na\ta b ' match>", '[att~="b"]' ),
'attribute one of' => array( '<div att="a B c"><div att="a b c" match><p att="b" match><p att="abc"><p att="abcdef b " match>', '[att~="b"]', 3 ),
'attribute one of insensitive' => array( '<div att="a c"><div att="a B c" match>', '[att~="b"i]', 1 ),
'attribute one of mod sensitive' => array( '<div att="a B c"><div att="a b c" match>', '[att~="b"s]', 1 ),
'attribute one of whitespace cases' => array( "<div att=' a'><div att='\na\ta b ' match>", '[att~="b"]', 1 ),

'attribute with-hyphen (no hyphen)' => array( '<p att="special_not"><p att="special" match>', '[att|="special"]' ),
'attribute with-hyphen (hyphen prefix)' => array( '<p att="special_not"><p att="special-yeah" match>', '[att|="special"]' ),
'attribute with-hyphen insensitive' => array( '<p att="special_not"><p att="SPECIAL" match>', '[att|="special"i]' ),
'attribute with-hyphen sensitive mod' => array( '<p att="spec"><p att="special" match>', '[att|="special"s]' ),
'attribute with-hyphen' => array( '<p att="special_not"><p att="special" match><p att="special-great" match>', '[att|="special"]', 2 ),
'attribute with-hyphen insensitive' => array( '<p att="special_not"><p att="SPECIAL" match><p att="SPECIAL-great" match>', '[att|="special" i]', 2 ),
'attribute with-hyphen sensitive mod' => array( '<p att="SPECIAL"><p att="special" match>', '[att|="special"s]', 1 ),

'attribute prefixed' => array( '<p att="fix"><p att="prefix" match>', '[att^="p"]' ),
'attribute prefixed insensitive' => array( '<p att="fix"><p att="Prefix" match>', '[att^="p"i]' ),
'attribute prefixed sensitive mod' => array( '<p att="Prefix"><p att="prefix" match>', '[att^="p"s]' ),
'attribute prefixed' => array( '<p att="notprefix"><p att="prefix" match><p att="perfect" match>', '[att^="p"]', 2 ),
'attribute prefixed insensitive' => array( '<p att="notprefix"><p att="Prefix" match>', '[att^="p"i]', 1 ),
'attribute prefixed sensitive mod' => array( '<p att="Prefix"><p att="prefix" match>', '[att^="p"s]', 1 ),

'attribute suffixed' => array( '<p att="suffix_"><p att="suffix" match>', '[att$="x"]' ),
'attribute suffixed insensitive' => array( '<p att="suffix_"><p att="suffiX" match>', '[att$="x"i]' ),
'attribute suffixed sensitive mod' => array( '<p att="suffiX"><p att="suffix" match>', '[att$="x"s]' ),
'attribute suffixed' => array( '<p att="suffix_"><p att="suffix" match><p att="brilliant…x" match>', '[att$="x"]', 2 ),
'attribute suffixed insensitive' => array( '<p att="suffix_"><p att="suffiX" match>', '[att$="x"i]', 1 ),
'attribute suffixed sensitive mod' => array( '<p att="suffiX"><p att="suffix" match>', '[att$="x"s]', 1 ),

'attribute contains' => array( '<p att="abcyz"><p att="abcxyz" match>', '[att*="x"]' ),
'attribute contains insensitive' => array( '<p att="abcyz"><p att="abcXyz" match>', '[att*="x"i]' ),
'attribute contains sensitive mod' => array( '<p att="abcXyz"><p att="abcxyz" match>', '[att*="x"s]' ),
'attribute contains' => array( '<p att="abcyz"><p att="abcxyz" match><p att="x" match>', '[att*="x"]', 2 ),
'attribute contains insensitive' => array( '<p att="abcyz"><p att="abcXyz" match>', '[att*="x"i]', 1 ),
'attribute contains sensitive mod' => array( '<p att="abcXyz"><p att="abcxyz" match>', '[att*="x"s]', 1 ),

'list' => array( '<div><p match>', 'a, p' ),
'compound' => array( '<div att><section att="bar" match>', 'section[att="bar"]' ),
'list' => array( '<div><p match><a match><span>', 'a, p, .class, #id, [att]', 2 ),
'compound' => array( '<div att><custom-el att="bar" fruit="APPLE BANANA" match>', 'custom-el[att="bar"][ fruit ~= "banana" i]', 1 ),
);
}

/**
* @ticket TBD
*/
public function test_select_all() {
$processor = new WP_HTML_Tag_Processor( '<div match><p class="x" match><svg><rect match/></svg><i id="y" match></i>' );
$count = 0;
foreach ( $processor->select_all( 'div, .x, rect, #y' ) as $_ ) {
++$count;
$this->assertTrue( $processor->get_attribute( 'match' ) );
}
$this->assertSame( 4, $count );
}

/**
* @ticket TBD
*
Expand Down

0 comments on commit 935aafa

Please sign in to comment.