import { afterEach, expect, test, vi } from "vitest"; import { POST } from "../../../app/api/orders/route"; afterEach(() => { vi.unstubAllEnvs(); vi.unstubAllGlobals(); }); test("proxies order creation to the backend and returns normalized success data", async () => { vi.stubEnv("BACKEND_BASE_URL", "http://backend.test/api/v1"); const fetchMock = vi.fn().mockResolvedValue( new Response( JSON.stringify({ order_id: 77, workflow_id: "wf-77", status: "created", }), { status: 201, headers: { "content-type": "application/json", }, }, ), ); vi.stubGlobal("fetch", fetchMock); const request = new Request("http://localhost/api/orders", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ customer_level: "mid", service_mode: "semi_pro", model_id: 101, garment_asset_id: 303, scene_ref_asset_id: 404, }), }); const response = await POST(request); const payload = await response.json(); expect(response.status).toBe(201); expect(payload).toEqual({ mode: "proxy", data: { orderId: 77, workflowId: "wf-77", status: "created", }, }); expect(fetchMock).toHaveBeenCalledWith( "http://backend.test/api/v1/orders", expect.objectContaining({ method: "POST", }), ); }); test("rejects invalid order creation payloads before proxying", async () => { const fetchMock = vi.fn(); vi.stubGlobal("fetch", fetchMock); const request = new Request("http://localhost/api/orders", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ customer_level: "low", service_mode: "semi_pro", model_id: 101, garment_asset_id: 303, scene_ref_asset_id: 404, }), }); const response = await POST(request); const payload = await response.json(); expect(response.status).toBe(400); expect(payload).toMatchObject({ error: "VALIDATION_ERROR", }); expect(fetchMock).not.toHaveBeenCalled(); }); test("rejects malformed JSON before validation or proxying", async () => { const fetchMock = vi.fn(); vi.stubGlobal("fetch", fetchMock); const request = new Request("http://localhost/api/orders", { method: "POST", headers: { "content-type": "application/json", }, body: "{bad json", }); const response = await POST(request); const payload = await response.json(); expect(response.status).toBe(400); expect(payload).toEqual({ error: "INVALID_JSON", message: "请求体必须是合法 JSON。", }); expect(fetchMock).not.toHaveBeenCalled(); }); test("normalizes upstream validation errors from the backend", async () => { vi.stubEnv("BACKEND_BASE_URL", "http://backend.test/api/v1"); const fetchMock = vi.fn().mockResolvedValue( new Response( JSON.stringify({ detail: "scene_ref_asset_id is invalid", }), { status: 422, headers: { "content-type": "application/json", }, }, ), ); vi.stubGlobal("fetch", fetchMock); const request = new Request("http://localhost/api/orders", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ customer_level: "mid", service_mode: "semi_pro", model_id: 101, garment_asset_id: 303, scene_ref_asset_id: 404, }), }); const response = await POST(request); const payload = await response.json(); expect(response.status).toBe(400); expect(payload).toEqual({ error: "VALIDATION_ERROR", message: "scene_ref_asset_id is invalid", details: { detail: "scene_ref_asset_id is invalid", }, }); }); test("accepts order creation payloads without a scene asset id", async () => { vi.stubEnv("BACKEND_BASE_URL", "http://backend.test/api/v1"); const fetchMock = vi.fn().mockResolvedValue( new Response( JSON.stringify({ order_id: 88, workflow_id: "wf-88", status: "created", }), { status: 201, headers: { "content-type": "application/json", }, }, ), ); vi.stubGlobal("fetch", fetchMock); const request = new Request("http://localhost/api/orders", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ customer_level: "low", service_mode: "auto_basic", model_id: 101, garment_asset_id: 303, }), }); const response = await POST(request); const payload = await response.json(); expect(response.status).toBe(201); expect(payload).toEqual({ mode: "proxy", data: { orderId: 88, workflowId: "wf-88", status: "created", }, }); expect(fetchMock).toHaveBeenCalledWith( "http://backend.test/api/v1/orders", expect.objectContaining({ method: "POST", body: JSON.stringify({ customer_level: "low", service_mode: "auto_basic", model_id: 101, garment_asset_id: 303, }), }), ); });