Payload/scripts/kaden/harness/harness-run-slice-tests.ps1

#Requires -Version 5.1
<#
.SYNOPSIS
    Repo-root runner for one slice's named test files.

.DESCRIPTION
    .Tests.ps1 paths run under Pester. Any other path runs under npm test.
    After that run, the runner writes one line naming the resolved paths:
    [slice-tests] running <paths>.
    Use with harness-step so RED and GREEN share one command_path for continuity.
    Pass -ExpectExit 1 on RED and 0 on GREEN. Prefer real failing tests on RED;
    do not wrap a bare exit 1.

.EXAMPLE
    pwsh -File scripts/kaden/harness-invoke.ps1 harness-step.ps1 -Feature saved-search-queries -Slice mo-save-list -Phase RED -Name slice-tests -Command .\scripts\kaden\harness-run-slice-tests.ps1 -Arguments '-TestFiles','tests/a.test.js' -ExpectExit 1 -TestFiles tests/a.test.js
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string[]]$TestFiles,

    [string]$RepoRoot = ''
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

Import-Module (Join-Path $PSScriptRoot 'lib\RepoRuntime.psm1') -Force
Import-Module (Join-Path $PSScriptRoot 'lib\HarnessContract.psm1') -Force

if ([string]::IsNullOrWhiteSpace($RepoRoot)) {
    $RepoRoot = Get-HarnessRepoRoot -StartPath $PSScriptRoot
}

Initialize-RepoShellEnvironment -LogPrefix 'harness-run-slice-tests' | Out-Null

$TestFiles = @(Expand-HarnessSensorTestFiles -TestFiles $TestFiles)

$resolved = @()
foreach ($f in $TestFiles) {
    $full = if ([System.IO.Path]::IsPathRooted($f)) { $f } else { Join-HarnessPath -Root $RepoRoot -Child $f }
    if (-not (Test-Path -LiteralPath $full)) {
        throw "Test file not found: $f"
    }
    $resolved += $f
}

function Get-SliceTestRunningLine {
    param([Parameter(Mandatory = $true)][string[]]$Resolved)
    $shown = @($Resolved | ForEach-Object { ($_ -replace '\\', '/') })
    return ('[slice-tests] running {0}' -f ($shown -join ','))
}

Push-Location $RepoRoot
try {
    $exitCode = 1
    $pesterFiles = @($resolved | Where-Object { $_ -match '\.Tests\.ps1$' -or $_ -match '\.tests\.ps1$' })
    if ($pesterFiles.Count -eq $resolved.Count -and $pesterFiles.Count -gt 0) {
        Import-Module Pester -MinimumVersion 5.0.0
        $config = New-PesterConfiguration
        $config.Run.Path = @($pesterFiles | ForEach-Object {
                if ([System.IO.Path]::IsPathRooted($_)) { $_ } else { Join-HarnessPath -Root $RepoRoot -Child $_ }
            })
        $config.Run.PassThru = $true
        $config.Output.Verbosity = 'Minimal'
        $result = Invoke-Pester -Configuration $config
        if ($null -ne $result) {
            $exitCode = [int]$result.FailedCount
        }
    } else {
        $npmArgs = @('test', '--') + $resolved
        & npm @npmArgs
        $exitCode = $LASTEXITCODE
    }
    Write-Output (Get-SliceTestRunningLine -Resolved $resolved)
    exit $exitCode
} finally {
    Pop-Location
}