# ColaFlow Sprint 1 API Validation Script # Backend Support for Frontend Team # Date: 2025-11-04 $baseUrl = "http://localhost:5167" $results = @() Write-Host "========================================" -ForegroundColor Cyan Write-Host "ColaFlow Sprint 1 API Validation" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # Helper function to test endpoint function Test-Endpoint { param( [string]$Method, [string]$Endpoint, [hashtable]$Headers = @{}, [string]$Body = $null, [string]$Description ) Write-Host "Testing: $Description" -ForegroundColor Yellow Write-Host " $Method $Endpoint" -ForegroundColor Gray try { $params = @{ Uri = "$baseUrl$Endpoint" Method = $Method Headers = $Headers ContentType = "application/json" TimeoutSec = 10 } if ($Body) { $params.Body = $Body } $response = Invoke-WebRequest @params -ErrorAction Stop $result = @{ Description = $Description Method = $Method Endpoint = $Endpoint StatusCode = $response.StatusCode Status = "PASS" ResponseTime = $response.Headers['X-Response-Time'] Error = $null } Write-Host " Status: $($response.StatusCode) - PASS" -ForegroundColor Green Write-Host "" return $result } catch { $statusCode = if ($_.Exception.Response) { $_.Exception.Response.StatusCode.Value__ } else { "N/A" } $errorMessage = $_.Exception.Message $result = @{ Description = $Description Method = $Method Endpoint = $Endpoint StatusCode = $statusCode Status = "FAIL" ResponseTime = $null Error = $errorMessage } Write-Host " Status: $statusCode - FAIL" -ForegroundColor Red Write-Host " Error: $errorMessage" -ForegroundColor Red Write-Host "" return $result } } # Test 1: Register a new tenant (company signup) Write-Host "`n--- Phase 1: Authentication Setup ---`n" -ForegroundColor Cyan $tenantSlug = "sprint1test" $registerBody = @{ email = "admin@sprint1test.com" password = "TestPassword123!" fullName = "Sprint 1 Admin" companyName = "Sprint 1 Test Company" slug = $tenantSlug } | ConvertTo-Json Write-Host "Registering new tenant..." -ForegroundColor Yellow try { $registerResponse = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" -Method POST -Body $registerBody -ContentType "application/json" -ErrorAction Stop Write-Host "Tenant registered successfully!" -ForegroundColor Green $results += @{ Description = "Tenant Registration" Method = "POST" Endpoint = "/api/tenants/register" StatusCode = 200 Status = "PASS" ResponseTime = $null Error = $null } Start-Sleep -Seconds 2 } catch { Write-Host "Tenant registration failed (may already exist): $_" -ForegroundColor Yellow $results += @{ Description = "Tenant Registration" Method = "POST" Endpoint = "/api/tenants/register" StatusCode = "Error" Status = "SKIP" ResponseTime = $null Error = "Tenant may already exist" } } # Test 2: Login to get JWT token $loginBody = @{ tenantSlug = $tenantSlug email = "admin@sprint1test.com" password = "TestPassword123!" } | ConvertTo-Json Write-Host "Attempting login..." -ForegroundColor Yellow try { $loginResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" -Method POST -Body $loginBody -ContentType "application/json" -ErrorAction Stop $token = $loginResponse.accessToken $tenantId = $loginResponse.tenantId $userId = $loginResponse.userId if ($token) { Write-Host "Login successful! Token obtained." -ForegroundColor Green Write-Host " TenantId: $tenantId" -ForegroundColor Gray Write-Host " UserId: $userId" -ForegroundColor Gray $results += @{ Description = "User Login" Method = "POST" Endpoint = "/api/auth/login" StatusCode = 200 Status = "PASS" ResponseTime = $null Error = $null } } } catch { Write-Host "Login failed: $_" -ForegroundColor Red Write-Host "Attempting to use default test tenant..." -ForegroundColor Yellow # Try default test tenant $altLoginBody = @{ tenantSlug = "testcompany" email = "admin@testcompany.com" password = "Admin123!" } | ConvertTo-Json try { $loginResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" -Method POST -Body $altLoginBody -ContentType "application/json" -ErrorAction Stop $token = $loginResponse.accessToken $tenantId = $loginResponse.tenantId $userId = $loginResponse.userId Write-Host "Login successful with default test tenant!" -ForegroundColor Green Write-Host " TenantId: $tenantId" -ForegroundColor Gray Write-Host " UserId: $userId" -ForegroundColor Gray } catch { Write-Host "Could not obtain token. Skipping authenticated tests." -ForegroundColor Red $token = $null } } Write-Host "" # Setup auth headers $authHeaders = @{ "Authorization" = "Bearer $token" "Accept" = "application/json" } # Test 3: ProjectManagement API Endpoints Write-Host "`n--- Phase 2: ProjectManagement API Validation ---`n" -ForegroundColor Cyan if ($token) { # Test GET /api/v1/projects $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/projects" -Headers $authHeaders -Description "Get All Projects" $results += $result # Test CREATE Project $createProjectBody = @{ name = "Sprint 1 Test Project" description = "Test project for API validation" key = "SPR1" ownerId = $userId } | ConvertTo-Json Write-Host "Creating test project..." -ForegroundColor Yellow try { $projectResponse = Invoke-RestMethod -Uri "$baseUrl/api/v1/projects" -Method POST -Body $createProjectBody -Headers $authHeaders -ContentType "application/json" -ErrorAction Stop $projectId = $projectResponse.id Write-Host "Project created successfully! ID: $projectId" -ForegroundColor Green $results += @{ Description = "Create Project" Method = "POST" Endpoint = "/api/v1/projects" StatusCode = 201 Status = "PASS" ResponseTime = $null Error = $null } # Test GET /api/v1/projects/{id} $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/projects/$projectId" -Headers $authHeaders -Description "Get Project by ID" $results += $result # Test Epic Endpoints Write-Host "`n--- Testing Epic Endpoints ---`n" -ForegroundColor Cyan # Test GET /api/projects/{projectId}/epics (empty list) $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/projects/$projectId/epics" -Headers $authHeaders -Description "Get Project Epics (empty)" $results += $result # Test CREATE Epic (independent endpoint) $createEpicBody = @{ projectId = $projectId name = "Sprint 1 Epic" description = "Test epic for API validation" createdBy = $userId } | ConvertTo-Json Write-Host "Creating test epic..." -ForegroundColor Yellow try { $epicResponse = Invoke-RestMethod -Uri "$baseUrl/api/v1/epics" -Method POST -Body $createEpicBody -Headers $authHeaders -ContentType "application/json" -ErrorAction Stop $epicId = $epicResponse.id Write-Host "Epic created successfully! ID: $epicId" -ForegroundColor Green $results += @{ Description = "Create Epic (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/epics" StatusCode = 201 Status = "PASS" ResponseTime = $null Error = $null } # Test GET /api/epics/{id} $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/epics/$epicId" -Headers $authHeaders -Description "Get Epic by ID" $results += $result # Test Story Endpoints Write-Host "`n--- Testing Story Endpoints ---`n" -ForegroundColor Cyan # Test GET /api/epics/{epicId}/stories (empty list) $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/epics/$epicId/stories" -Headers $authHeaders -Description "Get Epic Stories (empty)" $results += $result # Test CREATE Story (independent endpoint) $createStoryBody = @{ epicId = $epicId title = "Sprint 1 Story" description = "Test story for API validation" priority = "Medium" estimatedHours = 8 createdBy = $userId } | ConvertTo-Json Write-Host "Creating test story..." -ForegroundColor Yellow try { $storyResponse = Invoke-RestMethod -Uri "$baseUrl/api/v1/stories" -Method POST -Body $createStoryBody -Headers $authHeaders -ContentType "application/json" -ErrorAction Stop $storyId = $storyResponse.id Write-Host "Story created successfully! ID: $storyId" -ForegroundColor Green $results += @{ Description = "Create Story (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/stories" StatusCode = 201 Status = "PASS" ResponseTime = $null Error = $null } # Test GET /api/stories/{id} $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/stories/$storyId" -Headers $authHeaders -Description "Get Story by ID" $results += $result # Test Task Endpoints Write-Host "`n--- Testing Task Endpoints ---`n" -ForegroundColor Cyan # Test GET /api/stories/{storyId}/tasks (empty list) $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/stories/$storyId/tasks" -Headers $authHeaders -Description "Get Story Tasks (empty)" $results += $result # Test CREATE Task (independent endpoint) $createTaskBody = @{ storyId = $storyId title = "Sprint 1 Task" description = "Test task for API validation" priority = "High" estimatedHours = 4 createdBy = $userId } | ConvertTo-Json Write-Host "Creating test task..." -ForegroundColor Yellow try { $taskResponse = Invoke-RestMethod -Uri "$baseUrl/api/v1/tasks" -Method POST -Body $createTaskBody -Headers $authHeaders -ContentType "application/json" -ErrorAction Stop $taskId = $taskResponse.id Write-Host "Task created successfully! ID: $taskId" -ForegroundColor Green $results += @{ Description = "Create Task (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/tasks" StatusCode = 201 Status = "PASS" ResponseTime = $null Error = $null } # Test GET /api/tasks/{id} $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/tasks/$taskId" -Headers $authHeaders -Description "Get Task by ID" $results += $result # Test GET /api/projects/{projectId}/tasks (for Kanban board) $result = Test-Endpoint -Method "GET" -Endpoint "/api/v1/projects/$projectId/tasks" -Headers $authHeaders -Description "Get Project Tasks (for Kanban)" $results += $result # Test UPDATE Task Status (for Kanban drag & drop) $updateTaskStatusBody = @{ newStatus = "InProgress" } | ConvertTo-Json $result = Test-Endpoint -Method "PUT" -Endpoint "/api/v1/tasks/$taskId/status" -Headers $authHeaders -Body $updateTaskStatusBody -Description "Update Task Status" $results += $result Write-Host "`n--- Testing Update Operations ---`n" -ForegroundColor Cyan # Test UPDATE Story $updateStoryBody = @{ title = "Updated Sprint 1 Story" description = "Updated description" status = "InProgress" priority = "High" estimatedHours = 12 } | ConvertTo-Json $result = Test-Endpoint -Method "PUT" -Endpoint "/api/v1/stories/$storyId" -Headers $authHeaders -Body $updateStoryBody -Description "Update Story" $results += $result # Test UPDATE Epic $updateEpicBody = @{ name = "Updated Sprint 1 Epic" description = "Updated epic description" } | ConvertTo-Json $result = Test-Endpoint -Method "PUT" -Endpoint "/api/v1/epics/$epicId" -Headers $authHeaders -Body $updateEpicBody -Description "Update Epic" $results += $result Write-Host "`n--- Testing Delete Operations ---`n" -ForegroundColor Cyan # Test DELETE Task $result = Test-Endpoint -Method "DELETE" -Endpoint "/api/v1/tasks/$taskId" -Headers $authHeaders -Description "Delete Task" $results += $result # Test DELETE Story $result = Test-Endpoint -Method "DELETE" -Endpoint "/api/v1/stories/$storyId" -Headers $authHeaders -Description "Delete Story" $results += $result } catch { Write-Host "Task creation failed: $_" -ForegroundColor Red $results += @{ Description = "Create Task (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/tasks" StatusCode = "Error" Status = "FAIL" ResponseTime = $null Error = $_.Exception.Message } } } catch { Write-Host "Story creation failed: $_" -ForegroundColor Red $results += @{ Description = "Create Story (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/stories" StatusCode = "Error" Status = "FAIL" ResponseTime = $null Error = $_.Exception.Message } } } catch { Write-Host "Epic creation failed: $_" -ForegroundColor Red $results += @{ Description = "Create Epic (Independent Endpoint)" Method = "POST" Endpoint = "/api/v1/epics" StatusCode = "Error" Status = "FAIL" ResponseTime = $null Error = $_.Exception.Message } } } catch { Write-Host "Project creation failed: $_" -ForegroundColor Red $results += @{ Description = "Create Project" Method = "POST" Endpoint = "/api/v1/projects" StatusCode = "Error" Status = "FAIL" ResponseTime = $null Error = $_.Exception.Message } } } else { Write-Host "Skipping authenticated tests (no token available)" -ForegroundColor Yellow } # Test SignalR Hub connectivity Write-Host "`n--- Phase 3: SignalR Hub Validation ---`n" -ForegroundColor Cyan Write-Host "Testing SignalR Hub endpoints..." -ForegroundColor Yellow Write-Host " Hub: /hubs/project" -ForegroundColor Gray Write-Host " Note: Full WebSocket testing requires specialized client" -ForegroundColor Gray $result = Test-Endpoint -Method "POST" -Endpoint "/hubs/project/negotiate" -Headers $authHeaders -Description "SignalR Negotiate (Project Hub)" $results += $result Write-Host "" # Generate Summary Report Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Validation Summary" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan $totalTests = $results.Count $passedTests = ($results | Where-Object { $_.Status -eq "PASS" }).Count $failedTests = ($results | Where-Object { $_.Status -eq "FAIL" }).Count $passRate = [math]::Round(($passedTests / $totalTests) * 100, 2) Write-Host "Total Tests: $totalTests" -ForegroundColor White Write-Host "Passed: $passedTests" -ForegroundColor Green Write-Host "Failed: $failedTests" -ForegroundColor Red Write-Host "Pass Rate: $passRate%" -ForegroundColor $(if ($passRate -ge 90) { "Green" } elseif ($passRate -ge 70) { "Yellow" } else { "Red" }) Write-Host "`n--- Failed Tests ---`n" -ForegroundColor Red $failedResults = $results | Where-Object { $_.Status -eq "FAIL" } if ($failedResults.Count -gt 0) { foreach ($failed in $failedResults) { Write-Host "$($failed.Method) $($failed.Endpoint)" -ForegroundColor Red Write-Host " Description: $($failed.Description)" -ForegroundColor Gray Write-Host " Status Code: $($failed.StatusCode)" -ForegroundColor Gray Write-Host " Error: $($failed.Error)" -ForegroundColor Gray Write-Host "" } } else { Write-Host "No failed tests!" -ForegroundColor Green } # Export results to JSON $reportPath = "c:\Users\yaoji\git\ColaCoder\product-master\colaflow-api\Sprint1-API-Validation-Report.json" $results | ConvertTo-Json -Depth 10 | Out-File $reportPath Write-Host "`nDetailed report saved to: $reportPath" -ForegroundColor Cyan Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Validation Complete" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan