selfcheck-plan-chain.ps1 6.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. # 黑盒自测脚本(接口级) — 对应 tests/BLACKBOX-TEST-PLAN.md 4.x 用例
  2. # 目标: http://cfc.iwintrue.com
  3. $ErrorActionPreference = "Continue"
  4. $BASE = "http://cfc.iwintrue.com"
  5. $results = @()
  6. function Invoke-Case([string]$id, [string]$role, [string]$desc, [string]$path, $body, [bool]$auth = $true, [int]$timeoutSec = 20) {
  7. $headers = @{ "Content-Type" = "application/json" }
  8. if ($auth -and $script:token) { $headers["Authorization"] = "Bearer $script:token" }
  9. $jsonBody = if ($null -eq $body) { "{}" } else { $body | ConvertTo-Json -Depth 6 -Compress }
  10. $t0 = Get-Date
  11. try {
  12. $resp = Invoke-RestMethod -Uri ($BASE + $path) -Method Post -Headers $headers -Body $jsonBody -TimeoutSec $timeoutSec
  13. $ms = [int]((Get-Date) - $t0).TotalMilliseconds
  14. $code = $resp.code
  15. $note = $resp.message
  16. $dataInfo = ""
  17. if ($null -ne $resp.data) {
  18. $dataInfo = (($resp.data | ConvertTo-Json -Depth 2 -Compress)).Substring(0, [Math]::Min(120, (($resp.data | ConvertTo-Json -Depth 2 -Compress)).Length))
  19. }
  20. $script:results += [pscustomobject]@{ id = $id; role = $role; api = $path; desc = $desc; code = $code; ms = $ms; note = $note; data = $dataInfo }
  21. "PASS/INFO #$id [$role] $desc -> code=$code ($ms ms)${note} | $dataInfo "
  22. } catch {
  23. $ms = [int]((Get-Date) - $t0).TotalMilliseconds
  24. $err = $_.Exception.Message
  25. $code = "EX"
  26. if ($_.Exception.Response) { try { $code = [int]$_.Exception.Response.StatusCode } catch {} }
  27. $script:results += [pscustomobject]@{ id = $id; role = $role; api = $path; desc = $desc; code = $code; ms = $ms; note = $err; data = "" }
  28. "FAIL #$id [$role] $desc -> $code ($ms ms) $err"
  29. }
  30. }
  31. function Set-Token([string]$id) {
  32. try {
  33. $resp = Invoke-RestMethod -Uri ($BASE + "/api/admin-auth/login-by-password") -Method Post -Headers @{ "Content-Type" = "application/json" } -Body (@{ phone = "13800138000"; password = "admin123" } | ConvertTo-Json -Compress) -TimeoutSec 20
  34. if ($resp.code -eq 200 -and $resp.data) {
  35. $script:token = $resp.data.token
  36. $script:results += [pscustomobject]@{ id = $id; role = "运营"; api = "/api/admin-auth/login-by-password"; desc = "管理端密码登录(种子账号)"; code = $resp.code; ms = 0; note = $resp.message; data = ("token=" + $script:token.Substring(0, 12) + "...") }
  37. "TOKEN_OK phone=13800138000"
  38. } else {
  39. $script:results += [pscustomobject]@{ id = $id; role = "运营"; api = "/api/admin-auth/login-by-password"; desc = "管理端密码登录(种子账号)"; code = $resp.code; ms = 0; note = $resp.message; data = "" }
  40. "TOKEN_FAIL: $($resp.message)"
  41. }
  42. } catch {
  43. "TOKEN_EX: $($_.Exception.Message)"
  44. }
  45. }
  46. # ===== 1. 登录 =====
  47. Set-Token "E2E-00"
  48. # ===== 2. 主链路 / 近期修复回归 =====
  49. Invoke-Case "P0-3" "运营" "方案生成规则列表(种子≥2条, BUG-C)" "/api/admin/plan-rules/list" $null
  50. Invoke-Case "P0-4" "运营" "报告解析中台类型列表(含gut_flora, BUG-D)" "/api/admin/report-parser/types" @{ page = 1; size = 100 }
  51. Invoke-Case "A-03" "运营" "方案管理列表 admin全量(不筛家庭, 无白屏根因)" "/api/guide/plans/family-list" @{ status = "" }
  52. Invoke-Case "TCH-11" "规划师" "成长计划列表(修复后不400, BUG-E)" "/api/growth/plan/list" @{ }
  53. Invoke-Case "A-02" "运营" "全局任务统计" "/api/admin/tasks/stats" $null
  54. Invoke-Case "A-05" "运营" "注册重复报告类型应400(幂等)" "/api/admin/report-parser/types/save" @{ typeId = "gut_flora"; displayName = "菌群检测" }
  55. Invoke-Case "A-16" "运营" "参数校验:空body删除知识库应400非500(BUG-K)" "/api/admin/knowledge-base/delete" @{ }
  56. # ===== 3. 顺带修复BUG回归 =====
  57. Invoke-Case "A-11" "运营" "创建勋章(自动badgeId, BUG-F)" "/api/badges/create" @{
  58. name = "BLACKBOX自测勋章"; description = "黑盒自测"; icon = "🏅"; category = "打卡"; level = "铜牌";
  59. rarity = "普通"; triggerType = "task_count"; threshold = 5; sortOrder = 1; expireDays = -1; isActive = 1
  60. }
  61. Invoke-Case "A-12" "运营" "新增供应商(字段契约映射, BUG-G)" "/api/admin/supplier/save" @{
  62. nickname = "BLACKBOX供应商"; phone = "13800009999"; realName = "黑盒测试"; vendorType = "product"; vendorStatus = "active"
  63. }
  64. Invoke-Case "BUG-H" "运营" "已发布活动提交审核应400提示非500" "/api/admin/activity/submit-review" @{ id = 38 }
  65. Invoke-Case "BUG-I" "运营" "查询知识库(契约对齐, id=1)" "/api/admin/knowledge-base/get" @{ id = 1 }
  66. # 知识库删除:先建再删(自建数据)
  67. $kbSave = Invoke-Case "A-14a" "运营" "新建知识条目(供删除用)" "/api/admin/knowledge-base/save" @{ title = "BLACKBOX自测知识"; content = "自测内容"; status = 1 }
  68. $kbId = $null
  69. try {
  70. $r2 = Invoke-RestMethod -Uri ($BASE + "/api/admin/knowledge-base/save") -Method Post -Headers @{ "Content-Type" = "application/json"; "Authorization" = "Bearer $script:token" } -Body (@{ title = "BLACKBOX自测知识" + [DateTime]::Now.Ticks; content = "自测内容"; status = 1 } | ConvertTo-Json) -TimeoutSec 15
  71. if ($r2.code -eq 200) { $kbId = $r2.data.id; "KB_CREATED id=$kbId" }
  72. } catch { "KB_CREATE_EX: $($_.Exception.Message)" }
  73. if ($kbId) { Invoke-Case "A-14b" "运营" "删除知识条目(自建, BUG-I)" "/api/admin/knowledge-base/delete" @{ id = $kbId } }
  74. # 文章创建(计时, BUG-J)
  75. $artTitle = "BLACKBOX自测文章" + ([DateTime]::Now.Ticks % 100000)
  76. Invoke-Case "A-08" "运营" "创建文章(1s内返回预期, BUG-J)" "/api/admin/articles/create" @{
  77. title = $artTitle; content = "这是一篇黑盒自测短文,验证创建接口响应耗时不超过10秒。"; summary = "自测";
  78. author = "admin"; status = "draft"; articleType = "normal"
  79. }
  80. # ===== 4. 汇总 =====
  81. "`n========== 自测汇总 =========="
  82. $script:results | Format-Table -AutoSize id, role, desc, code, ms, note | Out-String -Width 200
  83. $fail = $script:results | Where-Object { $_.code -ne 200 }
  84. if ($fail) { "FAILED ITEMS: $($fail.id -join ', ')" } else { "ALL 200 (无失败项)" }