From e3638e809319f2f68fde2f1ffccf9791d5d6d7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Fri, 24 Jul 2026 00:04:49 +0200 Subject: [PATCH] Resolve relative CodeCoverage.ReportRoot to an absolute path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get-RelativePath makes the coverage report paths relative by stripping the report root prefix off the (absolute) file paths. When ReportRoot, or its Run.RepoRoot fallback, is a relative path the prefix never matches, so the report keeps the absolute paths. Get-ReportRoot now resolves the path to absolute before it is used. Fix #2920 🤖 --- src/functions/Coverage.ps1 | 18 +++++++++++++++--- tst/functions/Coverage.Tests.ps1 | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/functions/Coverage.ps1 b/src/functions/Coverage.ps1 index a65784ee3..03fb25aa6 100644 --- a/src/functions/Coverage.ps1 +++ b/src/functions/Coverage.ps1 @@ -727,11 +727,23 @@ function Get-CoverageReport { } function Get-ReportRoot { - if ($null -ne $PesterPreference.CodeCoverage.ReportRoot.Value) { - return $PesterPreference.CodeCoverage.ReportRoot.Value + $reportRoot = if ($null -ne $PesterPreference.CodeCoverage.ReportRoot.Value) { + $PesterPreference.CodeCoverage.ReportRoot.Value + } + else { + $PesterPreference.Run.RepoRoot.Value + } + + if ([string]::IsNullOrEmpty($reportRoot)) { + return $reportRoot } - $PesterPreference.Run.RepoRoot.Value + # Resolve to an absolute path. Get-RelativePath strips this prefix off the + # (absolute) file paths, so a relative ReportRoot/RepoRoot would never match + # and the report would keep the absolute paths instead of making them + # relative (#2920). GetUnresolvedProviderPathFromPSPath resolves against the + # current location without requiring the path to exist. + $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($reportRoot) } function Get-RelativePath { diff --git a/tst/functions/Coverage.Tests.ps1 b/tst/functions/Coverage.Tests.ps1 index 29f23db4f..dda93ff78 100644 --- a/tst/functions/Coverage.Tests.ps1 +++ b/tst/functions/Coverage.Tests.ps1 @@ -1414,4 +1414,30 @@ InPesterModuleScope { # } # } # } + + Describe 'Get-ReportRoot' { + It 'resolves a relative CodeCoverage.ReportRoot to an absolute path (#2920)' { + $PesterPreference = [PesterConfiguration]::Default + $PesterPreference.CodeCoverage.ReportRoot = '.' + [System.IO.Path]::IsPathRooted((Get-ReportRoot)) | Should -BeTrue + } + + It 'resolves a relative Run.RepoRoot fallback to an absolute path (#2920)' { + $PesterPreference = [PesterConfiguration]::Default + $PesterPreference.Run.RepoRoot = '.' + [System.IO.Path]::IsPathRooted((Get-ReportRoot)) | Should -BeTrue + } + + It 'lets a relative ReportRoot still yield relative file paths in the report (#2920)' { + # Reproduces #2920: with a relative ReportRoot, Get-RelativePath could + # not strip the prefix from the absolute file paths, so the report kept + # the absolute paths. Get-ReportRoot now resolves to absolute first. + $PesterPreference = [PesterConfiguration]::Default + $PesterPreference.CodeCoverage.ReportRoot = '.' + $absRoot = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.') + $absFile = Join-Path -Path $absRoot -ChildPath (Join-Path 'sub' 'File.ps1') + $expected = 'sub{0}File.ps1' -f [System.IO.Path]::DirectorySeparatorChar + Get-RelativePath -Path $absFile -RelativeTo (Get-ReportRoot) | Should -Be $expected + } + } }