Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc7d6231

Browse files
[DomCrawler] AddDomCrawler to leverage PHP 8.4's HTML5-compliant DOM parser
1 parentb223c40 commitc7d6231

File tree

29 files changed

+690
-245
lines changed

29 files changed

+690
-245
lines changed

‎UPGRADE-7.4.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ Console
1818

1919
* Deprecate`Symfony\Component\Console\Application::add()` in favor of`addCommand()`
2020

21+
BrowserKit
22+
----------
23+
24+
* Leverage the native HTML5 parser when using PHP 8.4+
25+
2126
DependencyInjection
2227
-------------------
2328

@@ -29,6 +34,16 @@ DoctrineBridge
2934

3035
* Deprecate`UniqueEntity::getRequiredOptions()` and`UniqueEntity::getDefaultOption()`
3136

37+
DomCrawler
38+
----------
39+
40+
*[BC BREAK] Type widening on public and protected methods/properties to support both
41+
`Dom\*` and`DOM*` native classes for:
42+
* properties`FormField::$document`,`$xpath`,`$node` and method`getLabel()`
43+
* methods`Form::getFormNode()` and`addField()`
44+
* property`AbstractUriElement::$node`, and methods`getNode()` and`setNode()`
45+
* methods`Crawler::add()`,`addDocument()`,`addNodeList()`,`addNode()`,`getNode()` and`sibling()`
46+
3247
FrameworkBundle
3348
---------------
3449

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
usePHPUnit\Framework\Attributes\DataProvider;
1515
useSymfony\Component\DomCrawler\Crawler;
16+
useSymfony\Component\DomCrawler\DomCrawler;
1617
useSymfony\Component\HttpFoundation\JsonResponse;
1718
useSymfony\Component\HttpFoundation\Request;
1819
useSymfony\Component\HttpFoundation\Response;
@@ -426,7 +427,7 @@ public static function mapRequestPayloadProvider(): iterable
426427
</request>
427428
XML,
428429
'responseAssertion' =>staticfunction (string$response) {
429-
$crawler =newCrawler($response);
430+
$crawler =\PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ?newDomCrawler($response) :newCrawler($response);
430431

431432
self::assertSame('https://symfony.com/errors/validation',$crawler->filterXPath('response/type')->text());
432433
self::assertSame('Validation Failed',$crawler->filterXPath('response/title')->text());
@@ -642,7 +643,7 @@ public static function mapRequestPayloadProvider(): iterable
642643
</request>
643644
XML,
644645
'responseAssertion' =>staticfunction (string$response) {
645-
$crawler =newCrawler($response);
646+
$crawler =\PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ?newDomCrawler($response) :newCrawler($response);
646647

647648
self::assertSame('https://symfony.com/errors/validation',$crawler->filterXPath('response/type')->text());
648649
self::assertSame('Validation Failed',$crawler->filterXPath('response/title')->text());
@@ -860,7 +861,7 @@ public static function mapRequestPayloadProvider(): iterable
860861
</request>
861862
XML,
862863
'responseAssertion' =>staticfunction (string$response) {
863-
$crawler =newCrawler($response);
864+
$crawler =\PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ?newDomCrawler($response) :newCrawler($response);
864865

865866
self::assertSame('https://symfony.com/errors/validation',$crawler->filterXPath('response/type')->text());
866867
self::assertSame('Validation Failed',$crawler->filterXPath('response/title')->text());

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

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
useSymfony\Component\BrowserKit\CookieJar;
2424
useSymfony\Component\BrowserKit\History;
2525
useSymfony\Component\DomCrawler\Crawler;
26+
useSymfony\Component\DomCrawler\DomCrawler;
2627
useSymfony\Component\HttpFoundation\CookieasHttpFoundationCookie;
2728
useSymfony\Component\HttpFoundation\Request;
2829
useSymfony\Component\HttpFoundation\Response;
@@ -231,126 +232,156 @@ public function testAssertBrowserHistoryIsNotOnLastPage()
231232

232233
publicfunctiontestAssertSelectorExists()
233234
{
234-
$this->getCrawlerTester(newCrawler('<html><body><h1>'))->assertSelectorExists('body > h1');
235+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
236+
237+
$this->getCrawlerTester(new$crawler('<html><body><h1>'))->assertSelectorExists('body > h1');
235238
$this->expectException(AssertionFailedError::class);
236239
$this->expectExceptionMessage('matches selector "body > h1".');
237-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertSelectorExists('body > h1');
240+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertSelectorExists('body > h1');
238241
}
239242

240243
publicfunctiontestAssertSelectorNotExists()
241244
{
242-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertSelectorNotExists('body > h1');
245+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
246+
247+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertSelectorNotExists('body > h1');
243248
$this->expectException(AssertionFailedError::class);
244249
$this->expectExceptionMessage('does not match selector "body > h1".');
245-
$this->getCrawlerTester(newCrawler('<html><body><h1>'))->assertSelectorNotExists('body > h1');
250+
$this->getCrawlerTester(new$crawler('<html><body><h1>'))->assertSelectorNotExists('body > h1');
246251
}
247252

248253
publicfunctiontestAssertSelectorCount()
249254
{
250-
$this->getCrawlerTester(newCrawler('<html><body><p>Hello</p></body></html>'))->assertSelectorCount(1,'p');
251-
$this->getCrawlerTester(newCrawler('<html><body><p>Hello</p><p>Foo</p></body></html>'))->assertSelectorCount(2,'p');
252-
$this->getCrawlerTester(newCrawler('<html><body><h1>This is not a paragraph.</h1></body></html>'))->assertSelectorCount(0,'p');
255+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
256+
257+
$this->getCrawlerTester(new$crawler('<html><body><p>Hello</p></body></html>'))->assertSelectorCount(1,'p');
258+
$this->getCrawlerTester(new$crawler('<html><body><p>Hello</p><p>Foo</p></body></html>'))->assertSelectorCount(2,'p');
259+
$this->getCrawlerTester(new$crawler('<html><body><h1>This is not a paragraph.</h1></body></html>'))->assertSelectorCount(0,'p');
253260
$this->expectException(AssertionFailedError::class);
254261
$this->expectExceptionMessage('Failed asserting that the Crawler selector "p" was expected to be found 0 time(s) but was found 1 time(s).');
255-
$this->getCrawlerTester(newCrawler('<html><body><p>Hello</p></body></html>'))->assertSelectorCount(0,'p');
262+
$this->getCrawlerTester(new$crawler('<html><body><p>Hello</p></body></html>'))->assertSelectorCount(0,'p');
256263
}
257264

258265
publicfunctiontestAssertSelectorTextNotContains()
259266
{
260-
$this->getCrawlerTester(newCrawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1','Bar');
267+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
268+
269+
$this->getCrawlerTester(new$crawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1','Bar');
261270
$this->expectException(AssertionFailedError::class);
262271
$this->expectExceptionMessage('matches selector "body > h1" and the text "Foo" of the node matching selector "body > h1" does not contain "Foo".');
263-
$this->getCrawlerTester(newCrawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1','Foo');
272+
$this->getCrawlerTester(new$crawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1','Foo');
264273
}
265274

266275
publicfunctiontestAssertAnySelectorTextContains()
267276
{
268-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Foo Baz'))->assertAnySelectorTextContains('ul li','Foo');
277+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
278+
279+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Foo Baz'))->assertAnySelectorTextContains('ul li','Foo');
269280
$this->expectException(AssertionFailedError::class);
270281
$this->expectExceptionMessage('matches selector "ul li" and the text of any node matching selector "ul li" contains "Foo".');
271-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextContains('ul li','Foo');
282+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextContains('ul li','Foo');
272283
}
273284

274285
publicfunctiontestAssertAnySelectorTextSame()
275286
{
276-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextSame('ul li','Foo');
287+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
288+
289+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextSame('ul li','Foo');
277290
$this->expectException(AssertionFailedError::class);
278291
$this->expectExceptionMessage('matches selector "ul li" and has at least a node matching selector "ul li" with content "Foo".');
279-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextSame('ul li','Foo');
292+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextSame('ul li','Foo');
280293
}
281294

282295
publicfunctiontestAssertAnySelectorTextNotContains()
283296
{
284-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextNotContains('ul li','Foo');
297+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
298+
299+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Baz'))->assertAnySelectorTextNotContains('ul li','Foo');
285300
$this->expectException(AssertionFailedError::class);
286301
$this->expectExceptionMessage('matches selector "ul li" and the text of any node matching selector "ul li" does not contain "Foo".');
287-
$this->getCrawlerTester(newCrawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextNotContains('ul li','Foo');
302+
$this->getCrawlerTester(new$crawler('<ul><li>Bar</li><li>Foo'))->assertAnySelectorTextNotContains('ul li','Foo');
288303
}
289304

290305
publicfunctiontestAssertPageTitleSame()
291306
{
292-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertPageTitleSame('Foo');
307+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
308+
309+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertPageTitleSame('Foo');
293310
$this->expectException(AssertionFailedError::class);
294311
$this->expectExceptionMessage('matches selector "title" and has a node matching selector "title" with content "Bar".');
295-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertPageTitleSame('Bar');
312+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertPageTitleSame('Bar');
296313
}
297314

298315
publicfunctiontestAssertPageTitleContains()
299316
{
300-
$this->getCrawlerTester(newCrawler('<html><head><title>Foobar'))->assertPageTitleContains('Foo');
317+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
318+
319+
$this->getCrawlerTester(new$crawler('<html><head><title>Foobar'))->assertPageTitleContains('Foo');
301320
$this->expectException(AssertionFailedError::class);
302321
$this->expectExceptionMessage('matches selector "title" and the text "Foo" of the node matching selector "title" contains "Bar".');
303-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertPageTitleContains('Bar');
322+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertPageTitleContains('Bar');
304323
}
305324

306325
publicfunctiontestAssertInputValueSame()
307326
{
308-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="text" name="username" value="Fabien">'))->assertInputValueSame('username','Fabien');
327+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
328+
329+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="text" name="username" value="Fabien">'))->assertInputValueSame('username','Fabien');
309330
$this->expectException(AssertionFailedError::class);
310331
$this->expectExceptionMessage('matches selector "input[name="password"]" and has a node matching selector "input[name="password"]" with attribute "value" of value "pa$$".');
311-
$this->getCrawlerTester(newCrawler('<html><head><title>Foo'))->assertInputValueSame('password','pa$$');
332+
$this->getCrawlerTester(new$crawler('<html><head><title>Foo'))->assertInputValueSame('password','pa$$');
312333
}
313334

314335
publicfunctiontestAssertInputValueNotSame()
315336
{
316-
$this->getCrawlerTester(newCrawler('<html><body><input type="text" name="username" value="Helene">'))->assertInputValueNotSame('username','Fabien');
337+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
338+
339+
$this->getCrawlerTester(new$crawler('<html><body><input type="text" name="username" value="Helene">'))->assertInputValueNotSame('username','Fabien');
317340
$this->expectException(AssertionFailedError::class);
318341
$this->expectExceptionMessage('matches selector "input[name="password"]" and does not have a node matching selector "input[name="password"]" with attribute "value" of value "pa$$".');
319-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="text" name="password" value="pa$$">'))->assertInputValueNotSame('password','pa$$');
342+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="text" name="password" value="pa$$">'))->assertInputValueNotSame('password','pa$$');
320343
}
321344

322345
publicfunctiontestAssertCheckboxChecked()
323346
{
324-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxChecked('rememberMe');
325-
$this->getCrawlerTester(newCrawler('<!DOCTYPE html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxChecked('rememberMe');
347+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
348+
349+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxChecked('rememberMe');
350+
$this->getCrawlerTester(new$crawler('<!DOCTYPE html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxChecked('rememberMe');
326351
$this->expectException(AssertionFailedError::class);
327352
$this->expectExceptionMessage('matches selector "input[name="rememberMe"]:checked".');
328-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxChecked('rememberMe');
353+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxChecked('rememberMe');
329354
}
330355

331356
publicfunctiontestAssertCheckboxNotChecked()
332357
{
333-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxNotChecked('rememberMe');
334-
$this->getCrawlerTester(newCrawler('<!DOCTYPE html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxNotChecked('rememberMe');
358+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
359+
360+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxNotChecked('rememberMe');
361+
$this->getCrawlerTester(new$crawler('<!DOCTYPE html><body><form><input type="checkbox" name="rememberMe">'))->assertCheckboxNotChecked('rememberMe');
335362
$this->expectException(AssertionFailedError::class);
336363
$this->expectExceptionMessage('does not match selector "input[name="rememberMe"]:checked".');
337-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxNotChecked('rememberMe');
364+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="checkbox" name="rememberMe" checked>'))->assertCheckboxNotChecked('rememberMe');
338365
}
339366

340367
publicfunctiontestAssertFormValue()
341368
{
342-
$this->getCrawlerTester(newCrawler('<html><body><form id="form"><input type="text" name="username" value="Fabien">','http://localhost'))->assertFormValue('#form','username','Fabien');
369+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
370+
371+
$this->getCrawlerTester(new$crawler('<html><body><form id="form"><input type="text" name="username" value="Fabien">','http://localhost'))->assertFormValue('#form','username','Fabien');
343372
$this->expectException(AssertionFailedError::class);
344373
$this->expectExceptionMessage('Failed asserting that two strings are identical.');
345-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="text" name="username" value="Fabien">','http://localhost'))->assertFormValue('#form','username','Jane');
374+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="text" name="username" value="Fabien">','http://localhost'))->assertFormValue('#form','username','Jane');
346375
}
347376

348377
publicfunctiontestAssertNoFormValue()
349378
{
350-
$this->getCrawlerTester(newCrawler('<html><body><form id="form"><input type="checkbox" name="rememberMe">','http://localhost'))->assertNoFormValue('#form','rememberMe');
379+
$crawler = \PHP_VERSION_ID >=80400 &&class_exists(DomCrawler::class) ? DomCrawler::class : Crawler::class;
380+
381+
$this->getCrawlerTester(new$crawler('<html><body><form id="form"><input type="checkbox" name="rememberMe">','http://localhost'))->assertNoFormValue('#form','rememberMe');
351382
$this->expectException(AssertionFailedError::class);
352383
$this->expectExceptionMessage('Field "rememberMe" has a value in form "#form".');
353-
$this->getCrawlerTester(newCrawler('<html><body><form><input type="checkbox" name="rememberMe" checked>','http://localhost'))->assertNoFormValue('#form','rememberMe');
384+
$this->getCrawlerTester(new$crawler('<html><body><form><input type="checkbox" name="rememberMe" checked>','http://localhost'))->assertNoFormValue('#form','rememberMe');
354385
}
355386

356387
publicfunctiontestAssertRequestAttributeValueSame()

‎src/Symfony/Component/BrowserKit/AbstractBrowser.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
useSymfony\Component\BrowserKit\Exception\LogicException;
1717
useSymfony\Component\BrowserKit\Exception\RuntimeException;
1818
useSymfony\Component\DomCrawler\Crawler;
19+
useSymfony\Component\DomCrawler\DomCrawler;
1920
useSymfony\Component\DomCrawler\Form;
2021
useSymfony\Component\DomCrawler\Link;
2122
useSymfony\Component\Process\PhpProcess;
@@ -510,7 +511,11 @@ protected function createCrawlerFromContent(string $uri, string $content, string
510511
returnnull;
511512
}
512513

513-
$crawler =newCrawler(null,$uri,null,$this->useHtml5Parser);
514+
if (\PHP_VERSION_ID >=80400 &&$this->useHtml5Parser &&class_exists(DomCrawler::class)) {
515+
$crawler =newDomCrawler(null,$uri);
516+
}else {
517+
$crawler =newCrawler(null,$uri,null,$this->useHtml5Parser);
518+
}
514519
$crawler->addContent($content,$type);
515520

516521
return$crawler;

‎src/Symfony/Component/BrowserKit/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Add`isFirstPage()` and`isLastPage()` methods to the History class for checking navigation boundaries
88
* Add PHPUnit constraints:`BrowserHistoryIsOnFirstPage` and`BrowserHistoryIsOnLastPage`
9+
* Leverage the native HTML5 parser when using PHP 8.4+
910

1011
6.4
1112
---

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp