import { expect, test } from "@playwright/test"; import { encode } from "next-auth/jwt"; const SESSION_COOKIE_NAME = "authjs.session-token"; async function createSessionCookie(type: "regular" | "admin" | "agent_admin" = "regular") { const secret = process.env.AUTH_SECRET; if (!secret) { throw new Error("AUTH_SECRET 未配置,无法生成测试会话"); } const token = await encode({ secret, salt: SESSION_COOKIE_NAME, token: { sub: "product-planning-test-user", id: "product-planning-test-user", email: "product-planning-test@example.com", name: "Product Planning Test User", type, }, }); return `${SESSION_COOKIE_NAME}=${token}`; } test.describe.serial("/api/product-planning unauthorized", () => { test("guest cannot access reviews route", async ({ request }) => { const response = await request.get("/api/product-planning/taobao/reviews?id=1234567890&page=1"); expect(response.status()).toBe(401); const payload = await response.json(); expect(payload).toMatchObject({ error: "未授权,请先登录", }); }); test("guest cannot access template list route", async ({ request }) => { const response = await request.get("/api/product-planning/templates"); expect(response.status()).toBe(401); const payload = await response.json(); expect(payload).toMatchObject({ error: "未授权,请先登录", }); }); test("guest cannot access image analyze route", async ({ request }) => { const response = await request.post("/api/product-planning/analyze-image", { data: { itemId: "123", imageUrl: "https://example.com/demo.jpg", }, }); expect(response.status()).toBe(401); const payload = await response.json(); expect(payload).toMatchObject({ error: "未授权,请先登录", }); }); test("guest cannot access SKU analyze route", async ({ request }) => { const response = await request.post("/api/product-planning/analyze-sku", { data: { itemId: "123", platform: "taobao", skus: [{ name: "原木款", price: 199 }], }, }); expect(response.status()).toBe(401); const payload = await response.json(); expect(payload).toMatchObject({ error: "未授权,请先登录", }); }); }); test.describe.serial("/api/product-planning", () => { test("authenticated user gets 400 when reviews id is missing", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.get("/api/product-planning/taobao/reviews?page=1", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少商品ID参数", }); }); test("authenticated user gets 400 when QA itemId is missing", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.post("/api/product-planning/taobao/qa", { headers: { Cookie: cookie, }, data: { itemId: "", page: 1, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "请求参数不合法", }); }); test("authenticated user gets 400 when analyze rows are empty", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.post("/api/product-planning/analyze", { headers: { Cookie: cookie, }, data: { kind: "review", rows: [], }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "请求参数不合法或 rows 为空", }); }); test("authenticated user gets 400 when image analyze payload is invalid", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.post("/api/product-planning/analyze-image", { headers: { Cookie: cookie, }, data: { itemId: "", imageUrl: "not-a-url", }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "请求参数不合法", }); }); test("authenticated user gets 400 when SKU analyze payload is invalid", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.post("/api/product-planning/analyze-sku", { headers: { Cookie: cookie, }, data: { itemId: "", platform: "taobao", skus: [], }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "请求参数不合法或 skus 为空", }); }); test("authenticated user gets 400 when item id is missing for competitor item route", async ({ request, }) => { const cookie = await createSessionCookie(); const response = await request.get("/api/product-planning/taobao/item", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少商品ID参数", }); }); test("authenticated user gets 400 when item id is missing for JD item route", async ({ request, }) => { const cookie = await createSessionCookie(); const response = await request.get("/api/product-planning/jd/item", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少商品ID参数", }); }); test("authenticated user gets 400 when item id is missing for month-sale route", async ({ request, }) => { const cookie = await createSessionCookie(); const response = await request.get("/api/product-planning/taobao/month-sale", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少商品ID参数", }); }); test("authenticated user gets 400 when keyword insight q is missing", async ({ request }) => { const cookie = await createSessionCookie(); const response = await request.get("/api/product-planning/keyword-insight", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少关键词参数", }); }); test("regular user cannot upload shared templates", async ({ request }) => { const cookie = await createSessionCookie("regular"); const response = await request.post("/api/product-planning/templates", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(403); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "需要管理员权限", }); }); test("admin upload rejects missing template file", async ({ request }) => { const cookie = await createSessionCookie("admin"); const response = await request.post("/api/product-planning/templates", { headers: { Cookie: cookie, }, multipart: { categoryName: "换鞋凳", }, }); expect(response.status()).toBe(400); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "缺少模板文件", }); }); test("regular user cannot delete shared templates", async ({ request }) => { const cookie = await createSessionCookie("regular"); const response = await request.delete("/api/product-planning/templates/mock-template-id", { headers: { Cookie: cookie, }, }); expect(response.status()).toBe(403); const payload = await response.json(); expect(payload).toMatchObject({ success: false, error: "需要管理员权限", }); }); });