MilliSim/test-all-apis.ps1

547 lines
18 KiB
PowerShell

# MilliSim System - Full API Integration Test Script
$baseUrl = "http://localhost:5173"
$apiBase = "$baseUrl/api"
$token = $null
$passCount = 0
$failCount = 0
$results = @()
function Write-TestResult {
param($name, $success, $detail = "")
$status = if ($success) { "PASS" } else { "FAIL" }
$color = if ($success) { "Green" } else { "Red" }
Write-Host "[$status] $name - $detail" -ForegroundColor $color
$script:results += [PSCustomObject]@{
Name = $name
Status = $status
Detail = $detail
}
if ($success) { $script:passCount++ } else { $script:failCount++ }
}
function Get-CaptchaCode {
param($svg)
$m = [regex]::Matches($svg, '<text[^>]*>([A-Za-z0-9])</text>')
$code = ""
foreach ($x in $m) {
$code += $x.Groups[1].Value
}
return $code
}
function Safe-Invoke {
param($uri, $method, $headers = $null, $body = $null)
$params = @{
Uri = $uri
Method = $method
ContentType = "application/json"
}
if ($headers) { $params.Headers = $headers }
if ($body) { $params.Body = $body }
try {
$resp = Invoke-RestMethod @params
return @{ Success = $true; Data = $resp; Error = $null }
} catch {
$errDetail = $_.Exception.Message
if ($_.Exception.Response) {
try {
$sr = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
$errBody = $sr.ReadToEnd() | ConvertFrom-Json
$errDetail = $errBody.message
} catch {}
}
return @{ Success = $false; Data = $null; Error = $errDetail }
}
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "MilliSim System - Full API Integration Test" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Part 1: Public APIs
Write-Host "--- Part 1: Public API Tests ---" -ForegroundColor Yellow
# 1. Captcha
$r = Safe-Invoke "$apiBase/auth/captcha" "Get"
if ($r.Success) {
$captchaCode = Get-CaptchaCode -svg $r.Data.data.svg
$captchaId = $r.Data.data.captchaId
Write-TestResult "Captcha" ($r.Data.code -eq 200 -and $captchaCode.Length -eq 4) "code=$($r.Data.code), captcha=$captchaCode"
} else {
Write-TestResult "Captcha" $false $r.Error
}
# 2. Public Projects
$r = Safe-Invoke "$apiBase/projects/public?page=1&pageSize=10" "Get"
if ($r.Success) {
Write-TestResult "Public Projects" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Public Projects" $false $r.Error
}
# 3. Categories
$r = Safe-Invoke "$apiBase/categories" "Get"
if ($r.Success) {
Write-TestResult "Categories" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Categories" $false $r.Error
}
# 4. Platforms
$r = Safe-Invoke "$apiBase/platforms" "Get"
if ($r.Success) {
Write-TestResult "Platforms" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Platforms" $false $r.Error
}
# 5. Tags
$r = Safe-Invoke "$apiBase/tags" "Get"
if ($r.Success) {
Write-TestResult "Tags" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Tags" $false $r.Error
}
# 6. Banners
$r = Safe-Invoke "$apiBase/banners" "Get"
if ($r.Success) {
Write-TestResult "Banners" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Banners" $false $r.Error
}
# 7. Partners
$r = Safe-Invoke "$apiBase/partners" "Get"
if ($r.Success) {
Write-TestResult "Partners" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Partners" $false $r.Error
}
# 8. Project Detail
$r = Safe-Invoke "$apiBase/projects/public/1" "Get"
if ($r.Success) {
Write-TestResult "Project Detail" ($r.Data.code -eq 200) "title=$($r.Data.data.name)"
} else {
Write-TestResult "Project Detail" $false $r.Error
}
# 9. Wake Protocols (public)
$r = Safe-Invoke "$apiBase/system/wake-protocols" "Get"
if ($r.Success) {
Write-TestResult "Wake Protocols" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Wake Protocols" $false $r.Error
}
Write-Host ""
# Part 2: Login Auth Tests
Write-Host "--- Part 2: Login Auth Tests ---" -ForegroundColor Yellow
# 10. Wrong captcha login
$body = @{ username = "admin"; password = "admin123"; captchaId = $captchaId; captchaCode = "XXXX" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/auth/login" "Post" $null $body
if (-not $r.Success -or $r.Data.code -eq 400) {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Wrong Captcha Login" $true "rejected: $msg"
} else {
Write-TestResult "Wrong Captcha Login" $false "should be rejected"
}
# 11. Correct login
$r = Safe-Invoke "$apiBase/auth/captcha" "Get"
if ($r.Success) {
$captchaCode = Get-CaptchaCode -svg $r.Data.data.svg
$captchaId = $r.Data.data.captchaId
$body = @{ username = "admin"; password = "admin123"; captchaId = $captchaId; captchaCode = $captchaCode } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/auth/login" "Post" $null $body
if ($r.Success -and $r.Data.code -eq 200) {
$token = $r.Data.data.token
Write-TestResult "Admin Login" $true "user=$($r.Data.data.username), role=$($r.Data.data.roleName), tokenLen=$($token.Length)"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Admin Login" $false $msg
}
} else {
Write-TestResult "Admin Login" $false "captcha failed: $($r.Error)"
}
Write-Host ""
# Part 3: Authenticated API Tests
Write-Host "--- Part 3: Authenticated API Tests (Admin Token) ---" -ForegroundColor Yellow
$headers = @{ Authorization = "Bearer $token" }
# 12. Profile
$r = Safe-Invoke "$apiBase/auth/profile" "Get" $headers
if ($r.Success) {
Write-TestResult "Get Profile" ($r.Data.code -eq 200) "user=$($r.Data.data.username), role=$($r.Data.data.roleName)"
} else {
Write-TestResult "Get Profile" $false $r.Error
}
# 13. Users List
$r = Safe-Invoke "$apiBase/users?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Users List" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Users List" $false $r.Error
}
# 14. User Detail
$r = Safe-Invoke "$apiBase/users/1" "Get" $headers
if ($r.Success) {
Write-TestResult "User Detail" ($r.Data.code -eq 200) "user=$($r.Data.data.username)"
} else {
Write-TestResult "User Detail" $false $r.Error
}
# 15. System Settings
$r = Safe-Invoke "$apiBase/system/settings" "Get" $headers
if ($r.Success) {
Write-TestResult "System Settings" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "System Settings" $false $r.Error
}
# 16. Operation Logs
$r = Safe-Invoke "$apiBase/system/logs?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Operation Logs" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Operation Logs" $false $r.Error
}
# 17. Backups
$r = Safe-Invoke "$apiBase/system/backups" "Get" $headers
if ($r.Success) {
Write-TestResult "Backups List" ($r.Data.code -eq 200) "count=$($r.Data.data.Count)"
} else {
Write-TestResult "Backups List" $false $r.Error
}
# 18. Notifications
$r = Safe-Invoke "$apiBase/notifications?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Notifications List" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Notifications List" $false $r.Error
}
# 19. Unread Count
$r = Safe-Invoke "$apiBase/notifications/unread-count" "Get" $headers
if ($r.Success) {
Write-TestResult "Unread Count" ($r.Data.code -eq 200) "unread=$($r.Data.data)"
} else {
Write-TestResult "Unread Count" $false $r.Error
}
# 20. Authorizations
$r = Safe-Invoke "$apiBase/authorizations?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Authorizations List" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Authorizations List" $false $r.Error
}
# 21. Consultations
$r = Safe-Invoke "$apiBase/consultations?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Consultations List" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Consultations List" $false $r.Error
}
# 22. Dashboard Stats
$r = Safe-Invoke "$apiBase/dashboard" "Get" $headers
if ($r.Success) {
Write-TestResult "Dashboard Stats" ($r.Data.code -eq 200) "projects=$($r.Data.data.stats.projectCount), customers=$($r.Data.data.stats.customerCount)"
} else {
Write-TestResult "Dashboard Stats" $false $r.Error
}
# 23. Dashboard Trends
if ($r.Success) {
Write-TestResult "Dashboard Trends" ($r.Data.data.trends.Count -ge 0) "points=$($r.Data.data.trends.Count)"
} else {
Write-TestResult "Dashboard Trends" $false "see Dashboard Stats"
}
# 24. Admin Projects List
$r = Safe-Invoke "$apiBase/projects?page=1&pageSize=10" "Get" $headers
if ($r.Success) {
Write-TestResult "Admin Projects List" ($r.Data.code -eq 200) "count=$($r.Data.data.items.Count)"
} else {
Write-TestResult "Admin Projects List" $false $r.Error
}
Write-Host ""
# Part 4: CRUD Tests
Write-Host "--- Part 4: CRUD Operation Tests ---" -ForegroundColor Yellow
# 25. Create Category
$newCategoryId = 0
$body = @{ name = "TestCategory_$(Get-Random)"; sort = 99; icon = "folder" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/categories" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newCategoryId = $r.Data.data.id
Write-TestResult "Create Category" $true "id=$newCategoryId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create Category" $false $msg
}
# 26. Update Category
if ($newCategoryId -gt 0) {
$body = @{ name = "TestCategoryUpdated_$(Get-Random)"; sort = 99; icon = "folder" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/categories/$newCategoryId" "Put" $headers $body
if ($r.Success) {
Write-TestResult "Update Category" ($r.Data.code -eq 200) "id=$newCategoryId"
} else {
Write-TestResult "Update Category" $false $r.Error
}
}
# 27. Delete Category
if ($newCategoryId -gt 0) {
$r = Safe-Invoke "$apiBase/categories/$newCategoryId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Category" ($r.Data.code -eq 200) "id=$newCategoryId"
} else {
Write-TestResult "Delete Category" $false $r.Error
}
}
# 28. Create Tag
$newTagId = 0
$body = @{ name = "TestTag_$(Get-Random)"; color = "#1677FF" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/tags" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newTagId = $r.Data.data.id
Write-TestResult "Create Tag" $true "id=$newTagId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create Tag" $false $msg
}
# 29. Delete Tag
if ($newTagId -gt 0) {
$r = Safe-Invoke "$apiBase/tags/$newTagId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Tag" ($r.Data.code -eq 200) "id=$newTagId"
} else {
Write-TestResult "Delete Tag" $false $r.Error
}
}
# 30. Create Platform
$newPlatformId = 0
$body = @{ name = "TestPlatform_$(Get-Random)"; code = "TST$(Get-Random)"; icon = "desktop" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/platforms" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newPlatformId = $r.Data.data.id
Write-TestResult "Create Platform" $true "id=$newPlatformId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create Platform" $false $msg
}
# 31. Delete Platform
if ($newPlatformId -gt 0) {
$r = Safe-Invoke "$apiBase/platforms/$newPlatformId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Platform" ($r.Data.code -eq 200) "id=$newPlatformId"
} else {
Write-TestResult "Delete Platform" $false $r.Error
}
}
# 32. Create Banner
$newBannerId = 0
$body = @{ title = "TestBanner_$(Get-Random)"; image = "/uploads/test.jpg"; link = "/projects"; sortOrder = 99; status = "Active" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/banners" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newBannerId = $r.Data.data.id
Write-TestResult "Create Banner" $true "id=$newBannerId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create Banner" $false $msg
}
# 33. Delete Banner
if ($newBannerId -gt 0) {
$r = Safe-Invoke "$apiBase/banners/$newBannerId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Banner" ($r.Data.code -eq 200) "id=$newBannerId"
} else {
Write-TestResult "Delete Banner" $false $r.Error
}
}
# 34. Create Partner
$newPartnerId = 0
$body = @{ name = "TestPartner_$(Get-Random)"; logo = "/uploads/logo.jpg"; link = "https://example.com"; sort = 99 } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/partners" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newPartnerId = $r.Data.data.id
Write-TestResult "Create Partner" $true "id=$newPartnerId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create Partner" $false $msg
}
# 35. Delete Partner
if ($newPartnerId -gt 0) {
$r = Safe-Invoke "$apiBase/partners/$newPartnerId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Partner" ($r.Data.code -eq 200) "id=$newPartnerId"
} else {
Write-TestResult "Delete Partner" $false $r.Error
}
}
# 36. Create User (Sales)
$newUserId = 0
$body = @{ username = "testsales_$(Get-Random)"; password = "Test1234"; nickname = "TestSales"; role = "Sales"; phone = "13800000000"; email = "test@test.com" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/users" "Post" $headers $body
if ($r.Success -and $r.Data.code -eq 200) {
$newUserId = $r.Data.data.id
Write-TestResult "Create User" $true "id=$newUserId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Create User" $false $msg
}
# 37. Delete User
if ($newUserId -gt 0) {
$r = Safe-Invoke "$apiBase/users/$newUserId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete User" ($r.Data.code -eq 200) "id=$newUserId"
} else {
Write-TestResult "Delete User" $false $r.Error
}
}
# 38. Submit Consultation
$newConsultationId = 0
$body = @{ name = "TestUser"; contact = "13800000000"; content = "Test consultation content" } | ConvertTo-Json
$r = Safe-Invoke "$apiBase/consultations" "Post" $null $body
if ($r.Success -and $r.Data.code -eq 200) {
$newConsultationId = $r.Data.data.id
Write-TestResult "Submit Consultation" $true "id=$newConsultationId"
} else {
$msg = if ($r.Data) { $r.Data.message } else { $r.Error }
Write-TestResult "Submit Consultation" $false $msg
}
# 39. Mark Consultation as Read
if ($newConsultationId -gt 0) {
$r = Safe-Invoke "$apiBase/consultations/$newConsultationId/read" "Post" $headers
if ($r.Success) {
Write-TestResult "Mark Consultation Read" ($r.Data.code -eq 200) "id=$newConsultationId"
} else {
Write-TestResult "Mark Consultation Read" $false $r.Error
}
}
# 40. Delete Consultation
if ($newConsultationId -gt 0) {
$r = Safe-Invoke "$apiBase/consultations/$newConsultationId" "Delete" $headers
if ($r.Success) {
Write-TestResult "Delete Consultation" ($r.Data.code -eq 200) "id=$newConsultationId"
} else {
Write-TestResult "Delete Consultation" $false $r.Error
}
}
Write-Host ""
# Part 5: Permission Isolation Tests
Write-Host "--- Part 5: Permission Isolation Tests ---" -ForegroundColor Yellow
# 41. No Token Access
$r = Safe-Invoke "$apiBase/auth/profile" "Get"
if (-not $r.Success) {
Write-TestResult "No Token Access" $true "rejected (401)"
} else {
Write-TestResult "No Token Access" $false "should be 401"
}
# 42. No Token Access Settings
$r = Safe-Invoke "$apiBase/system/settings" "Get"
if (-not $r.Success) {
Write-TestResult "No Token Settings" $true "rejected (401)"
} else {
Write-TestResult "No Token Settings" $false "should be 401"
}
Write-Host ""
# Part 6: Frontend Page Tests
Write-Host "--- Part 6: Frontend Page Tests ---" -ForegroundColor Yellow
# 43. Home Page
try {
$resp = Invoke-WebRequest -Uri "$baseUrl/" -Method Get -UseBasicParsing
Write-TestResult "Home Page" ($resp.StatusCode -eq 200) "HTTP $($resp.StatusCode), len=$($resp.Content.Length)"
} catch {
Write-TestResult "Home Page" $false $_.Exception.Message
}
# 44. Projects Page
try {
$resp = Invoke-WebRequest -Uri "$baseUrl/projects" -Method Get -UseBasicParsing
Write-TestResult "Projects Page" ($resp.StatusCode -eq 200) "HTTP $($resp.StatusCode)"
} catch {
Write-TestResult "Projects Page" $false $_.Exception.Message
}
# 45. Login Page
try {
$resp = Invoke-WebRequest -Uri "$baseUrl/login" -Method Get -UseBasicParsing
Write-TestResult "Login Page" ($resp.StatusCode -eq 200) "HTTP $($resp.StatusCode)"
} catch {
Write-TestResult "Login Page" $false $_.Exception.Message
}
# 46. Admin Login Page
try {
$resp = Invoke-WebRequest -Uri "$baseUrl/admin/login" -Method Get -UseBasicParsing
Write-TestResult "Admin Login Page" ($resp.StatusCode -eq 200) "HTTP $($resp.StatusCode)"
} catch {
Write-TestResult "Admin Login Page" $false $_.Exception.Message
}
# 47. Frontend Assets
try {
$resp = Invoke-WebRequest -Uri "$baseUrl/" -Method Get -UseBasicParsing
$content = $resp.Content
$hasJs = $content -match "script.+src"
$hasCss = $content -match "link.+href"
Write-TestResult "Frontend Assets" ($hasJs -or $hasCss) "JS=$hasJs, CSS=$hasCss"
} catch {
Write-TestResult "Frontend Assets" $false $_.Exception.Message
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Test Summary" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
$totalColor = if ($failCount -eq 0) { "Green" } else { "Yellow" }
Write-Host "Pass: $passCount Fail: $failCount Total: $($passCount + $failCount)" -ForegroundColor $totalColor
Write-Host ""
if ($failCount -gt 0) {
Write-Host "Failed Items:" -ForegroundColor Red
$results | Where-Object { $_.Status -eq "FAIL" } | ForEach-Object {
Write-Host " - $($_.Name): $($_.Detail)" -ForegroundColor Red
}
}
Write-Host ""