From f038f0afd8cecdc04f5d8f6dd5b2abbd95cd04b9 Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:50:16 -0400 Subject: [PATCH 1/6] Require PHPStan 2.1 or newer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2979148..f62c52d 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.10", + "phpstan/phpstan": "^2.1", "squizlabs/php_codesniffer": "^3.7", "symfony/phpunit-bridge": "^5.2 || ^6.2 || ^7.0" }, From 919eb56c727bee7666d9a0754820864cbbdc0d2b Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:52:17 -0400 Subject: [PATCH 2/6] Ensure that PHPStan can see PHPUnit Bridge, fix broken docblock in test class --- phpstan.neon.dist | 8 ++++++++ tests/MarkupAssertionsTraitTest.php | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b980ecc..f7bec5d 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,7 +1,15 @@ parameters: level: 6 + + # Code to be analyzed paths: - src - tests + + # Don't worry about the coverage reports excludePaths: - tests/coverage + + # PHPUnit Bridge puts the PHPUnit source in an unconventional location + scanDirectories: + - vendor/bin/.phpunit/phpunit diff --git a/tests/MarkupAssertionsTraitTest.php b/tests/MarkupAssertionsTraitTest.php index 642927d..2666c8f 100644 --- a/tests/MarkupAssertionsTraitTest.php +++ b/tests/MarkupAssertionsTraitTest.php @@ -285,7 +285,7 @@ public function getInnerHtmlOfMatchedElements_should_retrieve_the_inner_HTML( /** * Data provider for testFlattenAttributeArray(). * - * @return array,string}> + * @return array,string}> */ public function provideAttributes(): array { From 0c957b336367046e4937496a9abd57c24d6bfbf0 Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:53:38 -0400 Subject: [PATCH 3/6] Since we've effectively dropped PHPUnit 6.x and lower from the running, we no longer need to see whether or not assertStringContainsString() is defined --- src/MarkupAssertionsTrait.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/MarkupAssertionsTrait.php b/src/MarkupAssertionsTrait.php index c580bc8..b9b05d9 100644 --- a/src/MarkupAssertionsTrait.php +++ b/src/MarkupAssertionsTrait.php @@ -127,11 +127,7 @@ public function assertNotHasElementWithAttributes($attributes = [], $markup = '' */ public function assertElementContains($contents, $selector = '', $markup = '', $message = '') { - $method = method_exists($this, 'assertStringContainsString') - ? 'assertStringContainsString' - : 'assertContains'; // @codeCoverageIgnore - - $this->$method( + $this->assertStringContainsString( $contents, $this->getInnerHtmlOfMatchedElements($markup, $selector), $message @@ -152,11 +148,7 @@ public function assertElementContains($contents, $selector = '', $markup = '', $ */ public function assertElementNotContains($contents, $selector = '', $markup = '', $message = '') { - $method = method_exists($this, 'assertStringNotContainsString') - ? 'assertStringNotContainsString' - : 'assertNotContains'; // @codeCoverageIgnore - - $this->$method( + $this->assertStringNotContainsString( $contents, $this->getInnerHtmlOfMatchedElements($markup, $selector), $message @@ -177,6 +169,7 @@ public function assertElementNotContains($contents, $selector = '', $markup = '' */ public function assertElementRegExp($regexp, $selector = '', $markup = '', $message = '') { + // @phpstan-ignore function.alreadyNarrowedType (Introduced in PHPUnit 9.x, PHP 7.3+) $method = method_exists($this, 'assertMatchesRegularExpression') ? 'assertMatchesRegularExpression' : 'assertRegExp'; // @codeCoverageIgnore @@ -202,6 +195,7 @@ public function assertElementRegExp($regexp, $selector = '', $markup = '', $mess */ public function assertElementNotRegExp($regexp, $selector = '', $markup = '', $message = '') { + // @phpstan-ignore function.alreadyNarrowedType (Introduced in PHPUnit 9.x, PHP 7.3+) $method = method_exists($this, 'assertDoesNotMatchRegularExpression') ? 'assertDoesNotMatchRegularExpression' : 'assertNotRegExp'; // @codeCoverageIgnore From fd1be074762b3e820523a470f177c257534b9eaa Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:57:59 -0400 Subject: [PATCH 4/6] Fix an outdated comment in the PHP_CodeSniffer config --- .phpcs.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index 4b4510d..df2db46 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -18,7 +18,7 @@ tests/* - + From c77a031704b2f103daa596ba24bff13fbb43bdaa Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:58:28 -0400 Subject: [PATCH 5/6] =?UTF-8?q?Explicit=20type=20casting=20to=20get=20us?= =?UTF-8?q?=20to=20PHPStan=20level=2010!=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phpstan.neon.dist | 2 +- src/MarkupAssertionsTrait.php | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f7bec5d..9b90598 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,5 @@ parameters: - level: 6 + level: 10 # Code to be analyzed paths: diff --git a/src/MarkupAssertionsTrait.php b/src/MarkupAssertionsTrait.php index b9b05d9..ea94aea 100644 --- a/src/MarkupAssertionsTrait.php +++ b/src/MarkupAssertionsTrait.php @@ -246,7 +246,7 @@ private function flattenAttributeArray(array $attributes) if (empty($value)) { $value = sprintf('[%s]', $key); } else { - $value = sprintf('[%s="%s"]', $key, htmlspecialchars($value)); + $value = sprintf('[%s="%s"]', $key, htmlspecialchars((string) $value)); } }); @@ -270,10 +270,14 @@ private function getInnerHtmlOfMatchedElements($markup, $query) // Loop through results and collect their innerHTML values. foreach ($results as $result) { + if (!isset($result->firstChild)) { + continue; + } + $document = new \DOMDocument(); $document->appendChild($document->importNode($result->firstChild, true)); - $contents[] = trim(html_entity_decode($document->saveHTML())); + $contents[] = trim(html_entity_decode((string) $document->saveHTML())); } return implode(PHP_EOL, $contents); From fdca2a176dca12b780464303fa53efeb53f677ab Mon Sep 17 00:00:00 2001 From: Steve Grunwell <233836+stevegrunwell@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:01:33 -0400 Subject: [PATCH 6/6] Indicate that tests/coverage may or may not exist --- phpstan.neon.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9b90598..3cbe92e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,7 +8,7 @@ parameters: # Don't worry about the coverage reports excludePaths: - - tests/coverage + - tests/coverage (?) # PHPUnit Bridge puts the PHPUnit source in an unconventional location scanDirectories: