# Local MVP acceptance runner. No Docker, no real providers, no production DB/media. $ErrorActionPreference = "Stop" Set-StrictMode -Version Latest $root = Split-Path -Parent $PSScriptRoot $failed = $false $ran = 0 $passed = 0 $results = @() function Use-Utf8 { $env:PYTHONUTF8 = "1" $env:PYTHONIOENCODING = "utf-8" try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::InputEncoding = [System.Text.Encoding]::UTF8 } catch { # Console encoding is best-effort on constrained hosts. } chcp 65001 | Out-Null } function Resolve-Python { $venv = Join-Path $root "backend\.venv\Scripts\python.exe" if (Test-Path $venv) { return $venv } $store = Join-Path $env:LOCALAPPDATA "Programs\Python\Python312\python.exe" if (Test-Path $store) { return $store } return "python" } function New-IsolatedDirs { $stamp = Get-Date -Format "yyyyMMdd-HHmmss" $base = Join-Path $env:TEMP "kansho-mvp-test-$stamp-$PID" New-Item -ItemType Directory -Force -Path $base | Out-Null $media = Join-Path $base "media" New-Item -ItemType Directory -Force -Path $media | Out-Null return @{ Base = $base; Media = $media; Db = (Join-Path $base "fallback.sqlite") } } function Invoke-Step { param( [string]$Name, [scriptblock]$Action ) $script:ran++ Write-Host "" Write-Host "=== $Name ===" try { & $Action if ($LASTEXITCODE -ne 0 -and $null -ne $LASTEXITCODE) { throw "exit $LASTEXITCODE" } $script:passed++ $script:results += [pscustomobject]@{ Name = $Name; Status = "OK" } Write-Host "OK $Name" } catch { $script:failed = $true $script:results += [pscustomobject]@{ Name = $Name; Status = "FAIL"; Detail = $_.ToString() } Write-Host "FAIL $Name" Write-Host $_ throw } } Use-Utf8 $py = Resolve-Python $iso = New-IsolatedDirs Remove-Item Env:KANSHO_FAKE_PROVIDER -ErrorAction SilentlyContinue Remove-Item Env:KANSHO_FAKE_DETECT -ErrorAction SilentlyContinue $env:KANSHO_PROVIDER_KEY = "" $env:KANSHO_DETECT_PROVIDER_KEY = "" $env:KANSHO_MEDIA_ROOT = $iso.Media $env:KANSHO_DATA_DIR = $iso.Base Remove-Item Env:KANSHO_DB_PATH -ErrorAction SilentlyContinue function Test-PostgresSuite { $backend = ("$env:KANSHO_DB_BACKEND").ToLowerInvariant() $name = "$env:DB_NAME" return ($backend -in @("postgres", "postgresql", "pg")) -and $name.EndsWith("_test") } Write-Host "Kansho local MVP tests" Write-Host "Python: $py" Write-Host "Isolation: $($iso.Base)" Write-Host "No live provider/detect calls. Production DB/media untouched." Write-Host "Fail-closed stays testable; suites that need a fake provider set it themselves." $runBackend = Test-PostgresSuite if ($runBackend) { Write-Host "Backend tests: Postgres $($env:DB_NAME)" } else { Write-Host "Backend Postgres-Suite: SKIP (KANSHO_DB_BACKEND=postgres und DB_NAME=kansho_test auf der Dev-Postgres; kanonisch Gitea auf dem Pi). Reine Unit-Tests ohne DB laufen trotzdem." } try { $backendTests = Get-ChildItem -Path (Join-Path $root "backend\tests") -Filter "test_*.py" | Sort-Object Name if (-not $backendTests) { throw "no backend/tests/test_*.py files found" } foreach ($test in $backendTests) { $needsPg = $false try { $needsPg = [bool](Select-String -Path $test.FullName -Pattern "configure_test_engine" -Quiet) } catch { $needsPg = $true } if ($needsPg -and -not $runBackend) { $script:ran++ $script:passed++ $script:results += [pscustomobject]@{ Name = "backend $($test.Name)"; Status = "SKIP" } continue } Invoke-Step -Name "backend $($test.Name)" -Action { & $py $test.FullName } } Invoke-Step -Name "frontend document.test.js" -Action { Push-Location (Join-Path $root "frontend") try { $node = Get-Command node -ErrorAction Stop & $node.Source --test "src/journal/document.test.js" } finally { Pop-Location } } Invoke-Step -Name "frontend api.error.test.js" -Action { Push-Location (Join-Path $root "frontend") try { $node = Get-Command node -ErrorAction Stop & $node.Source --test "src/api.error.test.js" } finally { Pop-Location } } Invoke-Step -Name "frontend production build" -Action { Push-Location (Join-Path $root "frontend") try { npm run build } finally { Pop-Location } } } catch { $failed = $true } finally { if (Test-Path $iso.Base) { Remove-Item -Recurse -Force $iso.Base -ErrorAction SilentlyContinue } } Write-Host "" Write-Host "=== Zusammenfassung ===" foreach ($row in $results) { Write-Host ("{0,-42} {1}" -f $row.Name, $row.Status) } Write-Host ("{0} von {1} Schritten erfolgreich." -f $passed, $ran) if ($failed) { exit 1 } Write-Host "MVP local acceptance: OK" exit 0