modules/testing/Test-Generator.ps1

#Requires -Version 5.1
<#
.SYNOPSIS
    Clean Architecture Generator Smoke Test
.DESCRIPTION
    Bir test projesi uretir, dotnet build calistirir, sonucu raporlar.
    npm build isteğe bagli (SkipNpm ile atlanabilir).
.EXAMPLE
    .\Test-Generator.ps1
    .\Test-Generator.ps1 -OrmMode Hybrid -FrontendMode NextJS
    .\Test-Generator.ps1 -OrmMode Dapper -FrontendMode ReactTS -SkipNpm
    .\Test-Generator.ps1 -All # Tum kombinasyonlari test eder
#>

[CmdletBinding()]
param(
    [ValidateSet("Dapper","EFCore","Hybrid")]
    [string]$OrmMode      = "Dapper",
    [ValidateSet("ReactTS","ReactJS","NextJS")]
    [string]$FrontendMode = "ReactTS",
    [switch]$SkipNpm,
    [switch]$All
)

$ScriptDir    = Split-Path -Parent $MyInvocation.MyCommand.Path
$GenRoot      = Split-Path (Split-Path $ScriptDir -Parent) -Parent
$GeneratorScript = Join-Path $GenRoot "cleanarch-new.ps1"

$TestRoot     = Join-Path $env:TEMP "GeneratorTests"
$Timestamp    = Get-Date -Format "yyyyMMdd_HHmmss"

$PassColor = "Green"
$FailColor = "Red"
$InfoColor = "Cyan"

$Results = @()

function Write-Header($msg) {
    Write-Host ""
    Write-Host "═══════════════════════════════════════" -ForegroundColor DarkCyan
    Write-Host " $msg" -ForegroundColor Cyan
    Write-Host "═══════════════════════════════════════" -ForegroundColor DarkCyan
}

function Run-Test($OrmModeVal, $FrontendModeVal) {
    $testName    = "Test_${OrmModeVal}_${FrontendModeVal}_$Timestamp"
    $testOutput  = Join-Path $TestRoot $testName

    Write-Header "ORM: $OrmModeVal | Frontend: $FrontendModeVal"
    Write-Host " Cikti: $testOutput" -ForegroundColor DarkGray

    $result = [PSCustomObject]@{
        OrmMode      = $OrmModeVal
        FrontendMode = $FrontendModeVal
        Generate     = $false
        Build        = $false
        NpmBuild     = $false
        Duration     = ""
        Error        = ""
    }

    $sw = [System.Diagnostics.Stopwatch]::StartNew()

    try {
        # 1. Generator
        Write-Host " [1/3] Proje uretiliyor..." -ForegroundColor $InfoColor
        & $GeneratorScript `
            -ProjectName  $testName `
            -OrmMode      $OrmModeVal `
            -FrontendMode $FrontendModeVal `
            -OutputRootPath $TestRoot 2>&1 | Out-Null

        if (-not (Test-Path $testOutput)) {
            throw "Generator cikti dizini olusturulmadi."
        }
        $result.Generate = $true
        Write-Host " [1/3] Generator ✓" -ForegroundColor $PassColor

        # 2. dotnet build
        Write-Host " [2/3] dotnet build calistiriliyor..." -ForegroundColor $InfoColor
        $slnFile = Get-ChildItem $testOutput -Filter "*.sln" | Select-Object -First 1
        if (-not $slnFile) { throw "SLN dosyasi bulunamadi." }

        $buildOut = dotnet build $slnFile.FullName --configuration Release 2>&1
        $buildOk  = $LASTEXITCODE -eq 0

        if ($buildOk) {
            $result.Build = $true
            Write-Host " [2/3] dotnet build ✓" -ForegroundColor $PassColor
        } else {
            $errors = $buildOut | Where-Object { $_ -match "error" } | Select-Object -First 5
            throw "Build basarisiz:`n$($errors -join "`n")"
        }

        # 3. npm build (isteğe bağlı)
        if (-not $SkipNpm) {
            $frontendDir = Join-Path $testOutput "frontend"
            if (Test-Path $frontendDir) {
                Write-Host " [3/3] npm install + build calistiriliyor..." -ForegroundColor $InfoColor
                Push-Location $frontendDir
                npm install --silent 2>&1 | Out-Null
                $npmOut = npm run build 2>&1
                $npmOk  = $LASTEXITCODE -eq 0
                Pop-Location

                if ($npmOk) {
                    $result.NpmBuild = $true
                    Write-Host " [3/3] npm build ✓" -ForegroundColor $PassColor
                } else {
                    $npmErrors = $npmOut | Where-Object { $_ -match "error" } | Select-Object -First 5
                    throw "npm build basarisiz:`n$($npmErrors -join "`n")"
                }
            }
        } else {
            $result.NpmBuild = $true  # Atlandi = gecti say
            Write-Host " [3/3] npm build atlandi (SkipNpm)" -ForegroundColor DarkGray
        }

    } catch {
        $result.Error = $_.ToString()
        Write-Host " ✗ HATA: $($result.Error)" -ForegroundColor $FailColor
    } finally {
        $sw.Stop()
        $result.Duration = "$($sw.Elapsed.TotalSeconds.ToString("F1"))s"
        # Test dizinini temizle
        Remove-Item $testOutput -Recurse -Force -ErrorAction SilentlyContinue
    }

    $Results += $result
    return $result
}

# ─── Ana Akis ────────────────────────────────────────────────
New-Item -ItemType Directory -Path $TestRoot -Force | Out-Null

if ($All) {
    $Combos = @(
        @("Dapper","ReactTS"), @("Dapper","NextJS"),
        @("EFCore","ReactTS"), @("EFCore","NextJS"),
        @("Hybrid","ReactTS"), @("Hybrid","NextJS")
    )
    foreach ($c in $Combos) {
        Run-Test $c[0] $c[1] | Out-Null
    }
} else {
    Run-Test $OrmMode $FrontendMode | Out-Null
}

# ─── Rapor ───────────────────────────────────────────────────
Write-Header "TEST RAPORU"
Write-Host ""

$passed = 0
$failed = 0
foreach ($r in $Results) {
    $allOk = $r.Generate -and $r.Build -and $r.NpmBuild
    $icon  = if ($allOk) { "✓" } else { "✗" }
    $color = if ($allOk) { $PassColor } else { $FailColor }

    if ($allOk) { $passed++ } else { $failed++ }

    Write-Host (" {0} {1,-10} + {2,-8} Generate:{3} Build:{4} Npm:{5} [{6}]" -f `
        $icon, $r.OrmMode, $r.FrontendMode,
        $(if($r.Generate){"✓"}else{"✗"}),
        $(if($r.Build){"✓"}else{"✗"}),
        $(if($r.NpmBuild){"✓"}else{"✗"}),
        $r.Duration
    ) -ForegroundColor $color

    if ($r.Error) {
        Write-Host " ↳ $($r.Error.Split("`n")[0])" -ForegroundColor DarkRed
    }
}

Write-Host ""
Write-Host " Gecti: $passed | Basarisiz: $failed" -ForegroundColor $(if ($failed -eq 0) { $PassColor } else { $FailColor })
Write-Host ""

exit $failed