import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const root = new URL("../", import.meta.url); const route = readFileSync(new URL("src/app/api/admin/payments/route.ts", root), "utf8"); const packagesRoute = readFileSync(new URL("src/app/api/admin/packages/route.ts", root), "utf8"); const page = readFileSync(new URL("src/app/admin/payments/page.tsx", root), "utf8"); const packagesPage = readFileSync(new URL("src/app/admin/packages/page.tsx", root), "utf8"); const management = readFileSync(new URL("src/components/admin/payment-management.tsx", root), "utf8"); const migration = readFileSync(new URL("supabase/migrations/20260727030000_payment_admin_stats.sql", root), "utf8"); test("支付后台接口只允许管理员并查询平台订单", () => { assert.match(route, /requireAdminSession\("read"\)/); assert.doesNotMatch(route, /isAdminUser\(user\)/); assert.match(route, /from\("payment_orders"\)/); assert.match(route, /auth\.admin\.getUserById/); assert.match(route, /payment_packages\(name\)/); assert.match(route, /order_no|orderNo/); assert.doesNotMatch(route, /SUPABASE_SERVICE_ROLE_KEY/); assert.doesNotMatch(route, /raw_notify_payload/); }); test("支付接口包含筛选、统计和分页契约", () => { for (const field of ["status", "from", "to", "limit", "offset"]) assert.match(route, new RegExp(field)); for (const field of ["totalOrders", "paidOrders", "pendingOrders", "failedExpiredOrders", "paidAmountCents", "grantedCredits"]) assert.match(route, new RegExp(field)); assert.match(route, /max\(100\)/); assert.match(route, /count: "exact"/); assert.match(route, /hasMore/); assert.match(migration, /get_payment_order_stats/); assert.match(migration, /status = 'paid'/); }); test("统一支付管理页面使用 Ant Design 与 Refine 并保留支付数据合同", () => { assert.match(page, /PaymentManagement/); for (const component of ["List", "Card", "Table", "Form", "Tag", "Alert", "Statistic"]) { assert.match(management, new RegExp(`\\b${component}\\b`)); } assert.match(management, /\/api\/admin\/payments/); assert.match(management, /\/api\/admin\/packages/); for (const field of ["orderNo", "userEmail", "packageName", "moneyCents", "credits", "status", "epayTradeNo", "createdAt", "paidAt"]) { assert.match(management, new RegExp(field)); } assert.match(management, /paymentLoading/); assert.match(management, /paymentError/); assert.match(management, /pagination=\{\{/); assert.doesNotMatch(management, /standalone-page|admin-header|admin-section/); }); test("套餐列表、Modal 与新增编辑停用操作收敛到支付管理页", () => { assert.match(management, /\}>/); assert.doesNotMatch(management, / { assert.match(packagesPage, /import \{ redirect \} from "next\/navigation"/); assert.match(packagesPage, /redirect\("\/admin\/payments"\)/); assert.doesNotMatch(packagesPage, /use client|