# ColaFlow Day 5 QA Integration Test Suite # Comprehensive testing for Refresh Token + RBAC $baseUrl = "http://localhost:5167" $ErrorActionPreference = "Continue" # Test counters $totalTests = 0 $passedTests = 0 $failedTests = 0 $errors = @() function Test-Api { param($Name, $ScriptBlock) $totalTests++ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Test $totalTests : $Name" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan try { & $ScriptBlock $passedTests++ Write-Host "[PASS] $Name" -ForegroundColor Green return $true } catch { $failedTests++ $script:errors += @{Name=$Name; Error=$_.Exception.Message} Write-Host "[FAIL] $Name" -ForegroundColor Red Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red return $false } } Write-Host "===================================================" -ForegroundColor Magenta Write-Host " ColaFlow Day 5 Integration Test Suite" -ForegroundColor Magenta Write-Host " Testing: Refresh Token + RBAC + Regression" -ForegroundColor Magenta Write-Host "===================================================" -ForegroundColor Magenta # Wait for API Write-Host "`nWaiting for API to be ready..." -ForegroundColor Yellow Start-Sleep -Seconds 5 # ============================================================================ # PHASE 1: REFRESH TOKEN TESTS # ============================================================================ Write-Host "`n" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow Write-Host " PHASE 1: REFRESH TOKEN TESTS" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow # Global variables for tokens $script:tenantSlug = "" $script:accessToken1 = "" $script:refreshToken1 = "" $script:accessToken2 = "" $script:refreshToken2 = "" $script:userId = "" # Test 1: Register and Get Tokens Test-Api "Register Tenant - Get Access & Refresh Tokens" { $slug = "test-$(Get-Random -Minimum 1000 -Maximum 9999)" $body = @{ tenantName = "Test Corp Day5" tenantSlug = $slug subscriptionPlan = "Professional" adminEmail = "admin@testday5.com" adminPassword = "Admin@1234" adminFullName = "Test Admin" } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" ` -Method Post -ContentType "application/json" -Body $body if (-not $response.accessToken -or -not $response.refreshToken) { throw "Missing tokens in response" } $script:tenantSlug = $slug $script:accessToken1 = $response.accessToken $script:refreshToken1 = $response.refreshToken $script:userId = $response.user.id Write-Host " Tenant: $slug" -ForegroundColor Gray Write-Host " User ID: $($script:userId)" -ForegroundColor Gray Write-Host " Access Token: $($script:accessToken1.Substring(0,20))..." -ForegroundColor Gray Write-Host " Refresh Token: $($script:refreshToken1.Substring(0,20))..." -ForegroundColor Gray } # Test 2: Use Access Token Test-Api "Access Protected Endpoint with Access Token" { $headers = @{ "Authorization" = "Bearer $($script:accessToken1)" } $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if (-not $response.userId) { throw "No user data returned" } Write-Host " User: $($response.email)" -ForegroundColor Gray } # Test 3: Refresh Token Test-Api "Refresh Access Token (Token Rotation)" { $body = @{ refreshToken = $script:refreshToken1 } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" ` -Method Post -ContentType "application/json" -Body $body if (-not $response.accessToken -or -not $response.refreshToken) { throw "Missing tokens in refresh response" } if ($response.accessToken -eq $script:accessToken1 -or $response.refreshToken -eq $script:refreshToken1) { throw "Tokens were not rotated" } $script:accessToken2 = $response.accessToken $script:refreshToken2 = $response.refreshToken Write-Host " New Access Token: $($script:accessToken2.Substring(0,20))..." -ForegroundColor Gray Write-Host " Tokens rotated successfully" -ForegroundColor Gray } # Test 4: Token Reuse Detection Test-Api "Token Reuse Detection (Security)" { $body = @{ refreshToken = $script:refreshToken1 } | ConvertTo-Json try { $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" ` -Method Post -ContentType "application/json" -Body $body throw "Old refresh token was accepted - SECURITY ISSUE!" } catch { $statusCode = $_.Exception.Response.StatusCode.value__ if ($statusCode -ne 401) { throw "Expected 401, got $statusCode" } Write-Host " Old token correctly rejected (401)" -ForegroundColor Gray } } # Test 5: New Token Works Test-Api "New Access Token Works" { $headers = @{ "Authorization" = "Bearer $($script:accessToken2)" } $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if ($response.userId -ne $script:userId) { throw "User ID mismatch" } Write-Host " New token validated successfully" -ForegroundColor Gray } # Test 6: Logout Test-Api "Logout - Revoke Refresh Token" { $body = @{ refreshToken = $script:refreshToken2 } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/logout" ` -Method Post -ContentType "application/json" -Body $body if (-not ($response.message -like "*success*")) { throw "Logout did not return success" } Write-Host " Token revoked successfully" -ForegroundColor Gray } # Test 7: Revoked Token Rejected Test-Api "Revoked Token Cannot Be Used" { $body = @{ refreshToken = $script:refreshToken2 } | ConvertTo-Json try { $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" ` -Method Post -ContentType "application/json" -Body $body throw "Revoked token was accepted - SECURITY ISSUE!" } catch { $statusCode = $_.Exception.Response.StatusCode.value__ if ($statusCode -ne 401) { throw "Expected 401, got $statusCode" } Write-Host " Revoked token correctly rejected" -ForegroundColor Gray } } # ============================================================================ # PHASE 2: RBAC TESTS # ============================================================================ Write-Host "`n" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow Write-Host " PHASE 2: RBAC TESTS" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow # Global variables for RBAC tests $script:rbacAccessToken = "" $script:rbacRefreshToken = "" $script:rbacTenantSlug = "" # Test 8: Register for RBAC Test-Api "Register Tenant for RBAC Testing" { $slug = "rbac-$(Get-Random -Minimum 1000 -Maximum 9999)" $body = @{ tenantName = "RBAC Test Corp" tenantSlug = $slug subscriptionPlan = "Professional" adminEmail = "rbac@test.com" adminPassword = "Admin@1234" adminFullName = "RBAC Admin" } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" ` -Method Post -ContentType "application/json" -Body $body $script:rbacAccessToken = $response.accessToken $script:rbacRefreshToken = $response.refreshToken $script:rbacTenantSlug = $slug Write-Host " Tenant: $slug" -ForegroundColor Gray } # Test 9: Verify TenantOwner Role Test-Api "Verify TenantOwner Role Assignment" { $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" } $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if ($response.tenantRole -ne "TenantOwner" -or $response.role -ne "TenantOwner") { throw "Expected TenantOwner, got tenantRole=$($response.tenantRole), role=$($response.role)" } Write-Host " Role: $($response.tenantRole)" -ForegroundColor Gray } # Test 10: Role Persistence Test-Api "Role Persistence Across Login" { $body = @{ tenantSlug = $script:rbacTenantSlug email = "rbac@test.com" password = "Admin@1234" } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" ` -Method Post -ContentType "application/json" -Body $body $headers = @{ "Authorization" = "Bearer $($response.accessToken)" } $meResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if ($meResponse.tenantRole -ne "TenantOwner") { throw "Role not persisted, got $($meResponse.tenantRole)" } Write-Host " Role persisted after login" -ForegroundColor Gray } # Test 11: Role in Refreshed Token Test-Api "Role Preserved in Refreshed Token" { $body = @{ refreshToken = $script:rbacRefreshToken } | ConvertTo-Json $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" ` -Method Post -ContentType "application/json" -Body $body $headers = @{ "Authorization" = "Bearer $($response.accessToken)" } $meResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if ($meResponse.tenantRole -ne "TenantOwner") { throw "Role not preserved in refresh, got $($meResponse.tenantRole)" } Write-Host " Role preserved after token refresh" -ForegroundColor Gray } # Test 12: JWT Claims Test-Api "JWT Claims Inspection" { $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" } $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers $required = @("userId", "email", "tenantRole", "role", "tenantId") foreach ($claim in $required) { if (-not $response.$claim) { throw "Missing claim: $claim" } } Write-Host " All required claims present" -ForegroundColor Gray } # ============================================================================ # PHASE 3: REGRESSION TESTS # ============================================================================ Write-Host "`n" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow Write-Host " PHASE 3: REGRESSION TESTS" -ForegroundColor Yellow Write-Host "=====================================" -ForegroundColor Yellow # Test 13: Password Hashing Test-Api "Password Hashing (Day 4 Regression)" { $slug = "hash-$(Get-Random -Minimum 1000 -Maximum 9999)" $body = @{ tenantName = "Hash Test" tenantSlug = $slug subscriptionPlan = "Free" adminEmail = "hash@test.com" adminPassword = "Password@123" adminFullName = "Hash Tester" } | ConvertTo-Json $regResponse = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" ` -Method Post -ContentType "application/json" -Body $body # Try login $loginBody = @{ tenantSlug = $slug email = "hash@test.com" password = "Password@123" } | ConvertTo-Json $loginResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" ` -Method Post -ContentType "application/json" -Body $loginBody if (-not $loginResponse.accessToken) { throw "Login failed after registration" } Write-Host " Password hashing working correctly" -ForegroundColor Gray } # Test 14: JWT Authentication Test-Api "JWT Authentication (Day 4 Regression)" { $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" } $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers if (-not $response.userId) { throw "JWT authentication failed" } Write-Host " JWT authentication working" -ForegroundColor Gray } # ============================================================================ # TEST SUMMARY # ============================================================================ Write-Host "`n" -ForegroundColor Magenta Write-Host "===================================================" -ForegroundColor Magenta Write-Host " TEST EXECUTION SUMMARY" -ForegroundColor Magenta Write-Host "===================================================" -ForegroundColor Magenta Write-Host "`nTotal Tests: $totalTests" -ForegroundColor White Write-Host "Passed: $passedTests" -ForegroundColor Green Write-Host "Failed: $failedTests" -ForegroundColor $(if ($failedTests -eq 0) { "Green" } else { "Red" }) $passRate = if ($totalTests -gt 0) { [math]::Round(($passedTests / $totalTests) * 100, 2) } else { 0 } Write-Host "Pass Rate: $passRate%" -ForegroundColor $(if ($passRate -ge 95) { "Green" } elseif ($passRate -ge 80) { "Yellow" } else { "Red" }) if ($failedTests -gt 0) { Write-Host "`nFailed Tests:" -ForegroundColor Red foreach ($error in $errors) { Write-Host " - $($error.Name)" -ForegroundColor Red Write-Host " $($error.Error)" -ForegroundColor DarkRed } } Write-Host "`n===================================================" -ForegroundColor Magenta Write-Host " DEPLOYMENT RECOMMENDATION" -ForegroundColor Magenta Write-Host "===================================================" -ForegroundColor Magenta if ($passRate -eq 100) { Write-Host "`n[EXCELLENT] All tests passed. Ready for production!" -ForegroundColor Green Write-Host "Recommendation: DEPLOY" -ForegroundColor Green exit 0 } elseif ($passRate -ge 95) { Write-Host "`n[GOOD] Minor issues found. Review failed tests." -ForegroundColor Yellow Write-Host "Recommendation: CONDITIONAL DEPLOY" -ForegroundColor Yellow exit 0 } elseif ($passRate -ge 80) { Write-Host "`n[WARNING] Multiple issues found. Fix before deploy." -ForegroundColor Yellow Write-Host "Recommendation: DO NOT DEPLOY" -ForegroundColor Yellow exit 1 } else { Write-Host "`n[CRITICAL] Major issues found. DO NOT DEPLOY!" -ForegroundColor Red Write-Host "Recommendation: DO NOT DEPLOY" -ForegroundColor Red exit 1 }