@@ -2,6 +2,47 @@ BeforeAll {
22 . (Join-Path $PSScriptRoot ' ..' ' scripts' ' build' ' ci' ' CodeSceneCoverageMap.ps1' )
33 . (Join-Path $PSScriptRoot ' ..' ' scripts' ' build' ' ci' ' CodeSceneCoverageXml.ps1' )
44 . (Join-Path $PSScriptRoot ' ..' ' scripts' ' build' ' ci' ' CoverageLowReport.ps1' )
5+
6+ foreach ($functionName in @ (
7+ ' ConvertTo-CoberturaRelativePath'
8+ ' Get-CodeSceneCoverageErrorRecord'
9+ ' Get-SourceSectionListFromBuiltModule'
10+ ' Find-SourceSectionForLine'
11+ ' Get-EmptyCoberturaLineBucket'
12+ ' Add-CoberturaLineHit'
13+ ' Get-CoberturaLineStat'
14+ ' Get-CoberturaPackageName'
15+ ' Get-CoberturaSourceLineRange'
16+ ' Test-CoberturaLineOutsideSourceRange'
17+ ' Add-CoberturaMappedLineHit'
18+ ' Add-CoberturaLineNodeHit'
19+ ' Get-CoberturaLineBucketMap'
20+ ' Add-CoberturaAttribute'
21+ ' Get-CoberturaClassElement'
22+ ' Get-CoberturaPackageElement'
23+ ' Get-CoberturaCoverageAttributeMap'
24+ ' Get-CoberturaCoverageDocument'
25+ ' Convert-CoberturaCoverageToSourcePath'
26+ ' ConvertTo-CoverageLineRate'
27+ ' Get-CoverageLowReportEntryList'
28+ ' Format-CoverageLowReportLine'
29+ ' Write-CoverageLowReport'
30+ )) {
31+ $scriptBlock = (Get-Command - Name $functionName - CommandType Function - ErrorAction Stop).ScriptBlock
32+ Set-Item - Path " function:global:$functionName " - Value $scriptBlock
33+ }
34+
35+ $here = Split-Path - Parent $PSCommandPath
36+ $script :repoRoot = Split-Path - Parent $here
37+ $script :moduleName = (Get-Content - LiteralPath (Join-Path $script :repoRoot ' project.json' ) - Raw | ConvertFrom-Json ).ProjectName
38+ $script :distModuleDir = Join-Path $script :repoRoot " dist/$script :moduleName "
39+
40+ if (-not (Test-Path - LiteralPath $script :distModuleDir )) {
41+ throw " Expected built $script :moduleName module at: $script :distModuleDir . Run Invoke-NovaBuild in the repo root first."
42+ }
43+
44+ Remove-Module $script :moduleName - ErrorAction SilentlyContinue
45+ Import-Module $script :distModuleDir - Force
546}
647
748Describe ' CodeScene Cobertura remapping helpers' {
@@ -204,3 +245,183 @@ Describe 'CodeScene Cobertura remapping helpers' {
204245 )
205246 }
206247}
248+
249+ Describe ' Coverage gaps for quality helpers' {
250+ It ' Write-NovaPesterTestResultReport writes a success NUnit-style report with default suite name' {
251+ $outputPath = Join-Path $TestDrive ' success-report.xml'
252+
253+ InModuleScope $script :moduleName - Parameters @ {OutputPath = $outputPath } {
254+ param ($OutputPath )
255+
256+ $testResult = [pscustomobject ]@ {
257+ Tests = @ (
258+ [pscustomobject ]@ {Result = ' Passed' }
259+ [pscustomobject ]@ {Result = ' Passed' }
260+ [pscustomobject ]@ {Result = ' Skipped' }
261+ [pscustomobject ]@ {Result = ' Inconclusive' }
262+ )
263+ }
264+
265+ Write-NovaPesterTestResultReport - TestResult $testResult - OutputPath $OutputPath
266+
267+ [xml ]$report = Get-Content - LiteralPath $OutputPath - Raw
268+ $testResultsNode = $report.SelectSingleNode (' /test-results' )
269+ $testSuiteNode = $report.SelectSingleNode (' /test-results/test-suite' )
270+
271+ $testResultsNode.name | Should - Be ' NovaModuleTools'
272+ $testResultsNode.total | Should - Be ' 4'
273+ $testResultsNode.failures | Should - Be ' 0'
274+ $testResultsNode.inconclusive | Should - Be ' 1'
275+ $testResultsNode.skipped | Should - Be ' 1'
276+ $testSuiteNode.result | Should - Be ' Success'
277+ $testSuiteNode.success | Should - Be ' True'
278+ $testSuiteNode.passed | Should - Be ' 2'
279+ }
280+ }
281+
282+ It ' Write-NovaPesterTestResultReport writes a failure NUnit-style report when failed tests are present' {
283+ $outputPath = Join-Path $TestDrive ' failure-report.xml'
284+
285+ InModuleScope $script :moduleName - Parameters @ {OutputPath = $outputPath } {
286+ param ($OutputPath )
287+
288+ $testResult = [pscustomobject ]@ {
289+ Tests = @ (
290+ [pscustomobject ]@ {Result = ' Passed' }
291+ [pscustomobject ]@ {Result = ' Failed' }
292+ )
293+ }
294+
295+ Write-NovaPesterTestResultReport - TestResult $testResult - OutputPath $OutputPath - TestSuiteName ' FocusedSuite'
296+
297+ [xml ]$report = Get-Content - LiteralPath $OutputPath - Raw
298+ $testResultsNode = $report.SelectSingleNode (' /test-results' )
299+ $testSuiteNode = $report.SelectSingleNode (' /test-results/test-suite' )
300+
301+ $testResultsNode.name | Should - Be ' FocusedSuite'
302+ $testResultsNode.failures | Should - Be ' 1'
303+ $testSuiteNode.result | Should - Be ' Failure'
304+ $testSuiteNode.success | Should - Be ' False'
305+ $testSuiteNode.failed | Should - Be ' 1'
306+ }
307+ }
308+
309+ It ' Write-NovaPesterTestResultArtifact returns without writing when the result has no Tests property' {
310+ InModuleScope $script :moduleName {
311+ Mock Get-Command {throw ' Get-Command should not be called when Tests is missing.' }
312+
313+ {Write-NovaPesterTestResultArtifact - TestResult ([pscustomobject ]@ {Summary = ' no tests' }) - OutputPath ' /tmp/unused.xml' } | Should -Not - Throw
314+
315+ Assert-MockCalled Get-Command - Times 0
316+ }
317+ }
318+
319+ It ' Write-NovaPesterTestResultArtifact uses the provided report writer when one is supplied' {
320+ InModuleScope $script :moduleName {
321+ $calls = [System.Collections.Generic.List [object ]]::new()
322+ $reportWriter = {
323+ param ($TestResult , $OutputPath )
324+
325+ $calls.Add ([pscustomobject ]@ {
326+ TestResult = $TestResult
327+ OutputPath = $OutputPath
328+ }) | Out-Null
329+ }.GetNewClosure()
330+ $testResult = [pscustomobject ]@ {Tests = @ ([pscustomobject ]@ {Result = ' Passed' })}
331+
332+ Write-NovaPesterTestResultArtifact - TestResult $testResult - OutputPath ' /tmp/provided.xml' - ReportWriter $reportWriter
333+
334+ $calls.Count | Should - Be 1
335+ $calls [0 ].OutputPath | Should - Be ' /tmp/provided.xml'
336+ $calls [0 ].TestResult.Tests[0 ].Result | Should - Be ' Passed'
337+ }
338+ }
339+
340+ It ' Write-NovaPesterTestResultArtifact resolves the default report writer when none is supplied' {
341+ InModuleScope $script :moduleName {
342+ Mock Get-Command {
343+ [pscustomobject ]@ {
344+ ScriptBlock = {
345+ param ($TestResult , $OutputPath )
346+
347+ return [pscustomobject ]@ {
348+ TestCount = @ ($TestResult.Tests ).Count
349+ OutputPath = $OutputPath
350+ }
351+ }
352+ }
353+ } - ParameterFilter {
354+ $Name -eq ' Write-NovaPesterTestResultReport' -and $CommandType -eq ' Function'
355+ }
356+
357+ $result = Write-NovaPesterTestResultArtifact - TestResult ([pscustomobject ]@ {Tests = @ ([pscustomobject ]@ {Result = ' Passed' })}) - OutputPath ' /tmp/default.xml'
358+
359+ $result.TestCount | Should - Be 1
360+ $result.OutputPath | Should - Be ' /tmp/default.xml'
361+ Assert-MockCalled Get-Command - Times 1 - ParameterFilter {
362+ $Name -eq ' Write-NovaPesterTestResultReport' -and $CommandType -eq ' Function'
363+ }
364+ }
365+ }
366+
367+ It ' Initialize-NovaPesterExecutionConfiguration applies returned overrides when <Name>' - ForEach @ (
368+ @ {
369+ Name = ' both verbosity and render mode are provided'
370+ Override = [pscustomobject ]@ {Verbosity = ' Detailed' ; RenderMode = ' Plaintext' }
371+ BoundParameters = @ {OutputVerbosity = ' Detailed' ; OutputRenderMode = ' Plaintext' }
372+ ExpectedVerbosity = ' Detailed'
373+ ExpectedRenderMode = ' Plaintext'
374+ }
375+ @ {
376+ Name = ' only render mode is provided'
377+ Override = [pscustomobject ]@ {Verbosity = $null ; RenderMode = ' Ansi' }
378+ BoundParameters = @ {OutputRenderMode = ' Ansi' }
379+ ExpectedVerbosity = ' Normal'
380+ ExpectedRenderMode = ' Ansi'
381+ }
382+ ) {
383+ $pesterConfig = [pscustomobject ]@ {
384+ Output = [pscustomobject ]@ {
385+ Verbosity = ' Normal'
386+ RenderMode = ' Auto'
387+ }
388+ TestResult = [pscustomobject ]@ {Enabled = $true }
389+ }
390+
391+ InModuleScope $script :moduleName - Parameters @ {TestCase = $_ ; PesterConfig = $pesterConfig } {
392+ param ($TestCase , $PesterConfig )
393+
394+ Mock Get-NovaPesterOutputOptionOverride {$TestCase.Override }
395+
396+ Initialize-NovaPesterExecutionConfiguration - PesterConfig $PesterConfig - BoundParameters $TestCase.BoundParameters
397+
398+ $PesterConfig.Output.Verbosity | Should - Be $TestCase.ExpectedVerbosity
399+ $PesterConfig.Output.RenderMode | Should - Be $TestCase.ExpectedRenderMode
400+ $PesterConfig.TestResult.Enabled | Should - BeFalse
401+ Assert-MockCalled Get-NovaPesterOutputOptionOverride - Times 1
402+ }
403+ }
404+
405+ It ' Initialize-NovaPesterExecutionConfiguration preserves unsupported settings when no overrides are returned' {
406+ $pesterConfig = [pscustomobject ]@ {
407+ Output = [pscustomobject ]@ {
408+ Verbosity = ' Normal'
409+ RenderMode = ' Auto'
410+ }
411+ TestResult = [pscustomobject ]@ {Summary = ' No Enabled property' }
412+ }
413+
414+ InModuleScope $script :moduleName - Parameters @ {PesterConfig = $pesterConfig } {
415+ param ($PesterConfig )
416+
417+ Mock Get-NovaPesterOutputOptionOverride {$null }
418+
419+ Initialize-NovaPesterExecutionConfiguration - PesterConfig $PesterConfig - BoundParameters @ {}
420+
421+ $PesterConfig.Output.Verbosity | Should - Be ' Normal'
422+ $PesterConfig.Output.RenderMode | Should - Be ' Auto'
423+ $PesterConfig.TestResult.PSObject.Properties.Name | Should -Not - Contain ' Enabled'
424+ Assert-MockCalled Get-NovaPesterOutputOptionOverride - Times 1
425+ }
426+ }
427+ }
0 commit comments