# ── VibeFinance testscript (PowerShell) ────────────────────────────────── # Draait de volledige testsuite voor de 2-container opzet. Alles gebeurt in # Docker, dus je hebt geen Node op de host nodig. # # 1. Dependency-check (staan package.json's op de laatste versies?) # 2. Backend-tests (Dockerfile target 'test' → node --test, zonder database) # 3. Productiebuild (Vite-build + app-image; faalt de frontend, faalt dit) # 4. Smoketest (productie-image + postgres, /api/health en / opvragen) # # De smoketest publiceert geen hostpoorten en gebruikt een eigen netwerk, dus # hij botst niet met een draaiende dev-stack. # # Gebruik: # .\test.ps1 # alle stappen # .\test.ps1 -Unit # dependency-check + backend-tests # .\test.ps1 -NoSmoke # zonder de stack te starten # .\test.ps1 -Strict # faal als een dependency achterloopt # .\test.ps1 -SkipDeps # dependency-check overslaan (bijv. offline) param( [switch]$Unit, [switch]$NoSmoke, [switch]$Strict, [switch]$SkipDeps ) $ErrorActionPreference = "Stop" $appVersion = (Get-Content (Join-Path $PSScriptRoot "package.json") -Raw | ConvertFrom-Json).version $testImage = "vibefinance/app:test-$appVersion" $prodImage = "vibefinance/app:build-$appVersion" $smokeNet = "vibefinance-smoke-net" $smokeDb = "vibefinance-smoke-db" $smokeApp = "vibefinance-smoke-app" function Write-Step { param([string]$Label) Write-Host "" Write-Host "── $Label" -ForegroundColor Cyan } # ── 1. Dependency-check ─────────────────────────────────────────────────── # Vergelijkt de versies in frontend/ en backend/package.json met het # npm-register. Bewuste uitzonderingen staan in docker/update-exceptions.json. if (-not $SkipDeps) { Write-Step "[1/4] Dependency-check" $checkArgs = @("node", "docker/check-updates.mjs") if ($Strict) { $checkArgs += "--strict" } docker run --rm -v "${PSScriptRoot}:/repo" -w /repo node:22-alpine @checkArgs $checkCode = $LASTEXITCODE if ($checkCode -ne 0) { if ($Strict) { Write-Error "Dependencies lopen achter — bijwerken of -SkipDeps gebruiken." exit 1 } Write-Host "Let op: er zijn nieuwere versies beschikbaar (zie hierboven)." -ForegroundColor Yellow } } else { Write-Step "[1/4] Dependency-check overgeslagen (-SkipDeps)" } # ── 2. Backend-tests ────────────────────────────────────────────────────── Write-Step "[2/4] Backend-tests" docker build --target test -t $testImage $PSScriptRoot if ($LASTEXITCODE -ne 0) { Write-Error "Testimage bouwen mislukt"; exit 1 } docker run --rm $testImage if ($LASTEXITCODE -ne 0) { Write-Error "Backend-tests mislukt"; exit 1 } Write-Host "Backend-tests geslaagd" -ForegroundColor Green if ($Unit) { Write-Host "" Write-Host "Alleen unit-tests gevraagd — klaar." -ForegroundColor Green exit 0 } # ── 3. Productiebuild (inclusief Vite-build) ────────────────────────────── Write-Step "[3/4] Productie-image bouwen" docker build --target production ` --build-arg APP_VERSION=$appVersion ` --build-arg VITE_APP_VERSION=$appVersion ` --build-arg VITE_API_URL=/api ` -t $prodImage $PSScriptRoot if ($LASTEXITCODE -ne 0) { Write-Error "Productiebuild mislukt"; exit 1 } Write-Host "Productie-image gebouwd: $prodImage" -ForegroundColor Green if ($NoSmoke) { Write-Host "" Write-Host "Smoketest overgeslagen (-NoSmoke) — klaar." -ForegroundColor Green exit 0 } # ── 4. Smoketest op het productie-image + postgres ──────────────────────── Write-Step "[4/4] Smoketest (app + postgres)" function Remove-SmokeStack { docker rm -f $smokeApp $smokeDb 2>$null | Out-Null docker network rm $smokeNet 2>$null | Out-Null } # Eventuele resten van een eerdere run opruimen Remove-SmokeStack try { docker network create $smokeNet | Out-Null docker run -d --name $smokeDb --network $smokeNet ` -e POSTGRES_DB=vibefinance ` -e POSTGRES_USER=vibefinance ` -e POSTGRES_PASSWORD=smokepassword ` postgres:18-alpine | Out-Null if ($LASTEXITCODE -ne 0) { throw "Database-container starten mislukt" } Write-Host " Wachten op postgres..." -ForegroundColor DarkGray $dbGereed = $false foreach ($poging in 1..30) { docker exec $smokeDb pg_isready -U vibefinance 2>$null | Out-Null if ($LASTEXITCODE -eq 0) { $dbGereed = $true; break } Start-Sleep -Seconds 2 } if (-not $dbGereed) { throw "Postgres werd niet bereikbaar" } docker run -d --name $smokeApp --network $smokeNet ` -e NODE_ENV=production ` -e JWT_SECRET=smoke-secret ` -e UPDATE_CHECK_URL= ` -e DATABASE_URL=postgresql://vibefinance:smokepassword@$smokeDb`:5432/vibefinance ` $prodImage | Out-Null if ($LASTEXITCODE -ne 0) { throw "App-container starten mislukt" } Write-Host " Wachten op de app..." -ForegroundColor DarkGray $health = $null foreach ($poging in 1..30) { $health = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/api/health 2>$null) -join "" if ($LASTEXITCODE -eq 0 -and $health -match '"status"') { break } $health = $null Start-Sleep -Seconds 2 } if (-not $health) { docker logs --tail 40 $smokeApp throw "App werd niet gezond" } Write-Host " /api/health : ok" -ForegroundColor Green # wget levert meerdere regels; samenvoegen tot één string, want -match op een # array filtert de array in plaats van een test te doen. $index = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/) -join "`n" if ($LASTEXITCODE -ne 0 -or $index -notmatch 'id="root"') { throw "Root gaf geen index.html terug" } Write-Host " / : index.html" -ForegroundColor Green $spa = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/voortgang) -join "`n" if ($LASTEXITCODE -ne 0 -or $spa -notmatch 'id="root"') { throw "SPA-fallback werkt niet" } Write-Host " /voortgang : index.html (SPA-fallback)" -ForegroundColor Green $api404 = (docker exec $smokeApp wget -qO- --server-response http://127.0.0.1:3001/api/bestaat-niet 2>&1) -join "`n" if ($api404 -notmatch "404") { throw "Onbekende API-route gaf geen 404" } Write-Host " /api/bestaat-niet: 404" -ForegroundColor Green Write-Host "" Write-Host "Smoketest geslaagd" -ForegroundColor Green } finally { Remove-SmokeStack } Write-Host "" Write-Host "════════════════════════════════════════" -ForegroundColor Cyan Write-Host " Alle tests geslaagd - $appVersion" -ForegroundColor Green Write-Host "════════════════════════════════════════" -ForegroundColor Cyan Write-Host "" # Expliciete 0: zie release.ps1 — voorkomt een geërfde exitcode. exit 0