From 9d2c92900d65d56b2f719fc798c8816bfbb98085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Z=C5=82otnicki?= Date: Thu, 10 Sep 2026 19:41:23 +0200 Subject: [PATCH 1/2] Name failure screenshots after the failing test PHPUnit 10 renamed getName() to name(), so the method_exists() check in tearDownPlaywright() always fell through to the 'test' default. With more than one failing test in a run, every screenshot overwrote the previous one and the evidence was gone by the time the run finished. resolveTestName() asks name() first and falls back to getName(), so the trait keeps working on PHPUnit 9 as well. The name ends up in a file name and a data set turns it into something like `testFoo with data set "a/b"`, so it is sanitized before use. --- CHANGELOG.md | 3 ++ src/Testing/PlaywrightTestCaseTrait.php | 28 +++++++++++++++++-- tests/Unit/Testing/PlaywrightTestCaseTest.php | 26 +++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f403d3c..922958e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Added - Targeted browser installation through `playwright-install [browser...]` +### Fixed +- Failure screenshots are named after the failing test again on PHPUnit 10 and newer + ## [1.4.0] - 2026-08-10 ### Added diff --git a/src/Testing/PlaywrightTestCaseTrait.php b/src/Testing/PlaywrightTestCaseTrait.php index a8f97a5..7de60d3 100644 --- a/src/Testing/PlaywrightTestCaseTrait.php +++ b/src/Testing/PlaywrightTestCaseTrait.php @@ -93,8 +93,7 @@ protected function tearDownPlaywright(): void $status = $this->status(); if ($status->isFailure() || $status->isError()) { - $testName = method_exists($this, 'getName') && is_string($this->getName()) ? $this->getName() : 'test'; - $this->captureFailureArtifacts($testName); + $this->captureFailureArtifacts($this->resolveTestName()); } $this->safeClose($this->context); @@ -180,6 +179,31 @@ private function shouldTrace(): bool return '' !== $value && '0' !== $value; } + private function resolveTestName(): string + { + foreach (['name', 'getName'] as $method) { + if (!method_exists($this, $method)) { + continue; + } + + $name = $this->{$method}(); + + if (is_string($name) && '' !== $name) { + return self::sanitizeFileName($name); + } + } + + return 'test'; + } + + private static function sanitizeFileName(string $name): string + { + $sanitized = preg_replace('/[^A-Za-z0-9._-]+/', '_', $name) ?? ''; + $sanitized = trim($sanitized, '_.'); + + return '' === $sanitized ? 'test' : $sanitized; + } + private function captureFailureArtifacts(string $testName): void { $dir = getcwd().'/test-failures'; diff --git a/tests/Unit/Testing/PlaywrightTestCaseTest.php b/tests/Unit/Testing/PlaywrightTestCaseTest.php index 78879ce..d55945a 100644 --- a/tests/Unit/Testing/PlaywrightTestCaseTest.php +++ b/tests/Unit/Testing/PlaywrightTestCaseTest.php @@ -59,4 +59,30 @@ public function testSetUpCallsSetUpPlaywright(): void $this->assertTrue($setUpMethod->hasReturnType()); $this->assertEquals('void', $setUpMethod->getReturnType()->getName()); } + + public function testResolveTestNameUsesTheRunningTestName(): void + { + $case = new class('testExample') extends PlaywrightTestCase { + public function testExample(): void + { + } + }; + + $method = new \ReflectionMethod($case, 'resolveTestName'); + + $this->assertSame('testExample', $method->invoke($case)); + } + + public function testResolveTestNameStaysUsableAsAFileName(): void + { + $case = new class('testExample with data set "a/b"') extends PlaywrightTestCase { + public function testExample(): void + { + } + }; + + $method = new \ReflectionMethod($case, 'resolveTestName'); + + $this->assertSame('testExample_with_data_set_a_b', $method->invoke($case)); + } } From b2695c6553839bd73cca96bdae6feca985c5a74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Z=C5=82otnicki?= Date: Thu, 10 Sep 2026 21:06:39 +0200 Subject: [PATCH 2/2] Cover the fallback in resolveTestName() The loop skipping a missing accessor and the final default were the two lines Codecov reported as uncovered. --- tests/Unit/Testing/PlaywrightTestCaseTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Unit/Testing/PlaywrightTestCaseTest.php b/tests/Unit/Testing/PlaywrightTestCaseTest.php index d55945a..19f5dd9 100644 --- a/tests/Unit/Testing/PlaywrightTestCaseTest.php +++ b/tests/Unit/Testing/PlaywrightTestCaseTest.php @@ -85,4 +85,17 @@ public function testExample(): void $this->assertSame('testExample_with_data_set_a_b', $method->invoke($case)); } + + public function testResolveTestNameFallsBackWhenTheNameIsEmpty(): void + { + $case = new class('') extends PlaywrightTestCase { + public function testExample(): void + { + } + }; + + $method = new \ReflectionMethod($case, 'resolveTestName'); + + $this->assertSame('test', $method->invoke($case)); + } }