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 -Platform Both -SkipNpm
#>

[CmdletBinding()]
param(
    [ValidateSet("Dapper","EFCore","Hybrid")]
    [string]$OrmMode      = "Dapper",
    [ValidateSet("Web","Mobile","Both")]
    [string]$Platform     = "Web",
    [switch]$SkipNpm,
    [switch]$All
)

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

$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"

$PassIcon = [char]0x2713
$FailIcon = [char]0x2717

$Results = @()

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

function Run-Test($OrmModeVal) {
    $testName    = "Test_${OrmModeVal}_$Timestamp"
    if ($Platform -eq "Mobile") {
        $testName = "Test_${OrmModeVal}_Mobile_$Timestamp"
    }
    $testOutput  = Join-Path $TestRoot $testName

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

    $result = [PSCustomObject]@{
        OrmMode      = $OrmModeVal
        Platform     = $Platform
        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 `
            -Platform       $Platform `
            -Architecture   "Layered" `
            -SkipNpm `
            -NonInteractive `
            -OutputRootPath $TestRoot 2>&1 | Out-Null

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

        # 2. dotnet build
        Write-Host " [2/3] dotnet build calistiriliyor..." -ForegroundColor $InfoColor
        $slnFile = Get-ChildItem $testOutput -Filter "*.sln" -Recurse | 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 $PassIcon" -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) {
            Write-Host " [3/3] npm install + build calistiriliyor..." -ForegroundColor $InfoColor
            $npmOk = $true
            
            if ($Platform -match "Web|Both") {
                $webDir = Join-Path $testOutput "${testName}-web"
                Push-Location $webDir
                npm install --silent 2>&1 | Out-Null
                $npmOut = npm run build 2>&1
                $npmOk = $npmOk -and ($LASTEXITCODE -eq 0)
                Pop-Location
            }
            if ($Platform -match "Mobile|Both") {
                $mobileDir = Join-Path $testOutput "${testName}-mobile"
                Push-Location $mobileDir
                npm install --silent 2>&1 | Out-Null
                $npmOut = npx expo export 2>&1
                $npmOk = $npmOk -and ($LASTEXITCODE -eq 0)
                Pop-Location
            }

            if ($npmOk) {
                $result.NpmBuild = $true
                Write-Host " [3/3] npm build $PassIcon" -ForegroundColor $PassColor
            } else {
                throw "npm build/export basarisiz."
            }
        } else {
            $result.NpmBuild = $true  # Atlandi = gecti say
            Write-Host " [3/3] npm build atlandi (SkipNpm)" -ForegroundColor DarkGray
        }

    } catch {
        $result.Error = $_.ToString()
        Write-Host " $FailIcon 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 | Out-Null
    }

    $script:Results += $result
    return $result
}

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

if ($All) {
    $OrmModes = @("Dapper", "EFCore", "Hybrid")
    foreach ($orm in $OrmModes) {
        Run-Test $orm | Out-Null
    }
} else {
    Run-Test $OrmMode | 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) { $PassIcon } else { $FailIcon }
    $color = if ($allOk) { $PassColor } else { $FailColor }

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

    Write-Host (" {0} {1,-10} ({2,-6}) Generate:{3} Build:{4} Npm:{5} [{6}]" -f `
        $icon, $r.OrmMode, $r.Platform,
        $(if($r.Generate){$PassIcon}else{$FailIcon}),
        $(if($r.Build){$PassIcon}else{$FailIcon}),
        $(if($r.NpmBuild){$PassIcon}else{$FailIcon}),
        $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