Commit all scripts
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-03 17:19:20 +01:00
parent ebdd4ee0d7
commit 4183b10b39
24 changed files with 4917 additions and 11 deletions

View File

@@ -0,0 +1,379 @@
# 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
}