diff --git a/src/Plugins/Tia/CoverageMerger.php b/src/Plugins/Tia/CoverageMerger.php index f64f640e..40ea62c0 100644 --- a/src/Plugins/Tia/CoverageMerger.php +++ b/src/Plugins/Tia/CoverageMerger.php @@ -8,6 +8,9 @@ use Pest\Plugins\Tia; use Pest\Plugins\Tia\Contracts\State; use Pest\Support\Container; use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\Selector; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\Serialization\Unserializer; use Throwable; /** @@ -161,7 +164,60 @@ final class CoverageMerger return null; } - return $value instanceof CodeCoverage ? $value : null; + // Legacy `--coverage-php` format: a serialized `CodeCoverage` object. + if ($value instanceof CodeCoverage) { + return $value; + } + + // Since phpunit/php-code-coverage 14, `--coverage-php` writes the report + // as a serialized array (`['codeCoverage' => ..., 'testResults' => ..., + // 'basePath' => ...]`) rather than a `CodeCoverage` object, so it has to + // be rebuilt into one before it can be merged. + return self::coverageFromSerializedData($reportPath); + } + + private static function coverageFromSerializedData(string $reportPath): ?CodeCoverage + { + if ($reportPath === '') { + return null; + } + + try { + $serialized = new Unserializer()->unserialize($reportPath); + } catch (Throwable) { + return null; + } + + $data = $serialized['codeCoverage']; + $basePath = $serialized['basePath']; + + if ($basePath !== '') { + foreach ($data->coveredFiles() as $relativePath) { + $data->renameFile($relativePath, $basePath.DIRECTORY_SEPARATOR.$relativePath); + } + } + + $coverage = self::emptyCoverage(); + + if (! $coverage instanceof CodeCoverage) { + return null; + } + + $coverage->setData($data); + $coverage->setTests($serialized['testResults']); + + return $coverage; + } + + private static function emptyCoverage(): ?CodeCoverage + { + try { + $filter = new Filter; + + return new CodeCoverage(new Selector()->forLineCoverage($filter), $filter); + } catch (Throwable) { + return null; + } } private static function unserializeCoverage(string $bytes): ?CodeCoverage