8000 [DomCrawler][FrameworkBundle] Add `assertAnySelectorText*` · symfony/symfony@98ebda2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 98ebda2

Browse files
SVillettefabpot
authored andcommitted
[DomCrawler][FrameworkBundle] Add assertAnySelectorText*
1 parent 79ca96f commit 98ebda2

File tree

9 files changed

+272
-1
lines changed

9 files changed

+272
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ CHANGELOG
77
* Add native return type to `Translator` and to `Application::reset()`
88
* Deprecate the integration of Doctrine annotations, either uninstall the `doctrine/annotations` package or disable the integration by setting `framework.annotations` to `false`
99
* Enable `json_decode_detailed_errors` context for Serializer by default if `kernel.debug` is true and the `seld/jsonlint` package is installed
10+
* Add `DomCrawlerAssertionsTrait::assertAnySelectorTextContains(string $selector, string $text)`
11+
* Add `DomCrawlerAssertionsTrait::assertAnySelectorTextSame(string $selector, string $text)`
12+
* Add `DomCrawlerAssertionsTrait::assertAnySelectorTextNotContains(string $selector, string $text)`
1013

1114
6.3
1215
---

src/Symfony/Bundle/FrameworkBundle/Test/DomCrawlerAssertionsTrait.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ public static function assertSelectorTextContains(string $selector, string $text
4747
), $message);
4848
}
4949

50+
public static function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void
51+
{
52+
self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(
53+
new DomCrawlerConstraint\CrawlerSelectorExists($selector),
54+
new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text)
55+
), $message);
56+
}
57+
5058
public static function assertSelectorTextSame(string $selector, string $text, string $message = ''): void
5159
{
5260
self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(
@@ -55,6 +63,14 @@ public static function assertSelectorTextSame(string $selector, string $text, st
5563
), $message);
5664
}
5765

66+
public static function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void
67+
{
68+
self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(
69+
new DomCrawlerConstraint\CrawlerSelectorExists($selector),
70+
new DomCrawlerConstraint\CrawlerAnySelectorTextSame($selector, $text)
71+
), $message);
72+
}
73+
5874
public static function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void
5975
{
6076
self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(
@@ -63,6 +79,14 @@ public static function assertSelectorTextNotContains(string $selector, string $t
6379
), $message);
6480
}
6581

82+
public static function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void
83+
{
84+
self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(
85+
new DomCrawlerConstraint\CrawlerSelectorExists($selector),
86+
new LogicalNot(new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text))
87+
), $message);
88+
}
89+
6690
public static function assertPageTitleSame(string $expectedTitle, string $message = ''): void
6791
{
6892
self::assertSelectorTextSame('title', $expectedTitle, $message);

src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,30 @@ public function testAssertSelectorTextNotContains()
208208
$this->getCrawlerTester(new Crawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1', 'Foo');
209209
}
210210

211+
public function testAssertAnySelectorTextContains()
212+
{
213+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Foo Baz'))->assertAnySelectorTextContains('ul li', 'Foo');
214+
$this->expectException(AssertionFailedError::class);
215+
$this->expectExceptionMessage('matches selector "ul li" and the text of any node matching selector "ul li" contains "Foo".');
216+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextContains('ul li', 'Foo');
217+
}
218+
219+
public function testAssertAnySelectorTextSame()
220+
{
221+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextSame('ul li', 'Foo');
222+
$this->expectException(AssertionFailedError::class);
223+
$this->expectExceptionMessage('matches selector "ul li" and has at least a node matching selector "ul li" with content "Foo".');
224+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextSame('ul li', 'Foo');
225+
}
226+
227+
public function testAssertAnySelectorTextNotContains()
228+
{
229+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextNotContains('ul li', 'Foo');
230+
$this->expectException(AssertionFailedError::class);
231+
$this->expectExceptionMessage('matches selector "ul li" and the text of any node matching selector "ul li" does not contain "Foo".');
232+
$this->getCrawlerTester(new Crawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextNotContains('ul li', 'Foo');
233+
}
234+
211235
public function testAssertPageTitleSame()
212236
{
213237
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertPageTitleSame('Foo');

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"symfony/console": "^5.4.9|^6.0.9|^7.0",
4343
"symfony/clock": "^6.2|^7.0",
4444
"symfony/css-selector": "^5.4|^6.0|^7.0",
45-
"symfony/dom-crawler": "^6.3|^7.0",
45+
"symfony/dom-crawler": "^6.4|^7.0",
4646
"symfony/dotenv": "^5.4|^6.0|^7.0",
4747
"symfony/polyfill-intl-icu": "~1.0",
4848
"symfony/form": "^5.4|^6.0|^7.0",

src/Symfony/Component/DomCrawler/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
6.4
5+
---
6+
7+
* Add `CrawlerAnySelectorTextContains` test constraint
8+
* Add `CrawlerAnySelectorTextSame` test constraint
9+
410
6.3
511
---
612

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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\DomCrawler\Test\Constraint;
13+
14+
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\DomCrawler\Crawler;
16+
17+
final class CrawlerAnySelectorTextContains extends Constraint
18+
{
19+
private string $selector;
20+
private string $expectedText;
21+
private bool $hasNode = false;
22+
23+
public function __construct(string $selector, string $expectedText)
24+
{
25+
$this->selector = $selector;
26+
$this->expectedText = $expectedText;
27+
}
28+
29+
public function toString(): string
30+
{
31+
if ($this->hasNode) {
32+
return sprintf('the text of any node matching selector "%s" contains "%s"', $this->selector, $this->expectedText);
33+
}
34+
35+
return sprintf('the Crawler has a node matching selector "%s"', $this->selector);
36+
}
37+
38+
protected function matches($other): bool
39+
{
40+
if (!$other instanceof Crawler) {
41+
throw new \InvalidArgumentException(sprintf('"%s" constraint expected an argument of type "%s", got "%s".', self::class, Crawler::class, get_debug_type($other)));
42+
}
43+
44+
$other = $other->filter($this->selector);
45+
if (!\count($other)) {
46+
$this->hasNode = false;
47+
48+
return false;
49+
}
50+
51+
$this->hasNode = true;
52+
53+
$nodes = $other->each(fn (Crawler $node) => $node->text(null, true));
54+
$matches = array_filter($nodes, function (string $node): bool {
55+
return str_contains($node, $this->expectedText);
56+
});
57+
58+
return 0 < \count($matches);
59+
}
60+
61+
protected function failureDescription($other): string
62+
{
63+
if (!$other instanceof Crawler) {
64+
throw new \InvalidArgumentException(sprintf('"%s" constraint expected an argument of type "%s", got "%s".', self::class, Crawler::class, get_debug_type($other)));
65+
}
66+
67+
return $this->toString();
68+
}
69+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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\DomCrawler\Test\Constraint;
13+
14+
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\DomCrawler\Crawler;
16+
17+
final class CrawlerAnySelectorTextSame extends Constraint
18+
{
19+
private string $selector;
20+
private string $expectedText;
21+
22+
public function __construct(string $selector, string $expectedText)
23+
{
24+
$this->selector = $selector;
25+
$this->expectedText = $expectedText;
26+
}
27+
28+
public function toString(): string
29+
{
30+
return sprintf('has at least a node matching selector "%s" with content "%s"', $this->selector, $this->expectedText);
31+
}
32+
33+
protected function matches($other): bool
34+
{
35+
if (!$other instanceof Crawler) {
36+
throw new \InvalidArgumentException(sprintf('"%s" constraint expected an argument of type "%s", got "%s".', self::class, Crawler::class, get_debug_type($other)));
37+
}
38+
39+
$other = $other->filter($this->selector);
40+
if (!\count($other)) {
41+
return false;
42+
}
43+
44+
$nodes = $other->each(fn (Crawler $node) => trim($node->text(null, true)));
45+
46+
return \in_array($this->expectedText, $nodes, true);
47+
}
48+
49+
protected function failureDescription($other): string
50+
{
51+
if (!$other instanceof Crawler) {
52+
throw new \InvalidArgumentException(sprintf('"%s" constraint expected an argument of type "%s", got "%s".', self::class, Crawler::class, get_debug_type($other)));
53+
}
54+
55+
return 'the Crawler '.$this->toString();
56+
}
57+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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\DomCrawler\Tests\Test\Constraint;
13+
14+
use PHPUnit\Framework\ExpectationFailedException;
15+
use PHPUnit\Framework\TestCase;
16+
use PHPUnit\Framework\TestFailure;
17+
use Symfony\Component\DomCrawler\Crawler;
18+
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextContains;
19+
20+
class CrawlerAnySelectorTextContainsTest extends TestCase
21+
{
22+
public function testConstraint()
23+
{
24+
$constraint = new CrawlerAnySelectorTextContains('ul li', 'Foo');
25+
26+
self::assertTrue($constraint->evaluate(new Crawler('<ul><li>Foo</li>'), '', true));
27+
self::assertTrue($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Foo'), '', true));
28+
self::assertTrue($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Foo Bar Baz'), '', true));
29+
self::assertFalse($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Baz'), '', true));
30+
31+
try {
32+
$constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Baz'));
33+
34+
self::fail();
35+
} catch (ExpectationFailedException $e) {
36+
self::assertEquals("Failed asserting that the text of any node matching selector \"ul li\" contains \"Foo\".\n", TestFailure::exceptionToString($e));
37+
}
38+
39+
try {
40+
$constraint->evaluate(new Crawler('<html><head><title>Foobar'));
41+
42+
self::fail();
43+
} catch (ExpectationFailedException $e) {
44+
self::assertEquals("Failed asserting that the Crawler has a node matching selector \"ul li\".\n", TestFailure::exceptionToString($e));
45+
46+
return;
47+
}
48+
}
49+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 D64B +
namespace Symfony\Component\DomCrawler\Tests\Test\Constraint;
13+
14+
use PHPUnit\Framework\ExpectationFailedException;
15+
use PHPUnit\Framework\TestCase;
16+
use PHPUnit\Framework\TestFailure;
17+
use Symfony\Component\DomCrawler\Crawler;
18+
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextSame;
19+
20+
final class CrawlerAnySelectorTextSameTest extends TestCase
21+
{
22+
public function testConstraint()
23+
{
24+
$constraint = new CrawlerAnySelectorTextSame('ul li', 'Foo');
25+
26+
self::assertTrue($constraint->evaluate(new Crawler('<ul><li>Foo</li>'), '', true));
27+
self::assertTrue($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Foo'), '', true));
28+
self::assertFalse($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Foo Bar Baz'), '', true));
29+
self::assertFalse($constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Baz'), '', true));
30+
31+
try {
32+
$constraint->evaluate(new Crawler('<ul><li>Bar</li><li>Baz'));
33+
34+
self::fail();
35+
} catch (ExpectationFailedException $e) {
36+
self::assertEquals("Failed asserting that the Crawler has at least a node matching selector \"ul li\" with content \"Foo\".\n", TestFailure::exceptionToString($e));
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)
0