diff --git a/src/app/api/affiliates/offers/[id]/route.test.ts b/src/app/api/affiliates/offers/[id]/route.test.ts index a98e359a..5f8b9aee 100644 --- a/src/app/api/affiliates/offers/[id]/route.test.ts +++ b/src/app/api/affiliates/offers/[id]/route.test.ts @@ -198,6 +198,28 @@ describe("PATCH /api/affiliates/offers/[id] - product_url validation (#137)", () expect(body.error).toContain("string"); }); + it("rejects non-string title values before trimming", async () => { + const res = await PATCH( + makeRequest("offer-1", { title: { text: "New title" } }), + makeParams("offer-1") + ); + + expect(res.status).toBe(400); + const body = await res.json(); + expect(body.error).toBe("title must be a string"); + }); + + it("rejects non-string description values before trimming", async () => { + const res = await PATCH( + makeRequest("offer-1", { description: ["New description"] }), + makeParams("offer-1") + ); + + expect(res.status).toBe(400); + const body = await res.json(); + expect(body.error).toBe("description must be a string"); + }); + it("accepts valid https URL in product_url (#137)", async () => { // Mock the update chain to succeed mockFrom.mockReturnValue(chainable({ id: "offer-1", product_url: "https://example.com/product" })); diff --git a/src/app/api/affiliates/offers/[id]/route.ts b/src/app/api/affiliates/offers/[id]/route.ts index a53c3bd3..e2accf09 100644 --- a/src/app/api/affiliates/offers/[id]/route.ts +++ b/src/app/api/affiliates/offers/[id]/route.ts @@ -100,8 +100,18 @@ export async function PATCH( // Partial validation — only validate provided fields const updateData: Record = { updated_at: new Date().toISOString() }; - if (body.title !== undefined) updateData.title = body.title.trim(); - if (body.description !== undefined) updateData.description = body.description.trim(); + if (body.title !== undefined) { + if (typeof body.title !== "string") { + return NextResponse.json({ error: "title must be a string" }, { status: 400 }); + } + updateData.title = body.title.trim(); + } + if (body.description !== undefined) { + if (typeof body.description !== "string") { + return NextResponse.json({ error: "description must be a string" }, { status: 400 }); + } + updateData.description = body.description.trim(); + } if (body.product_url !== undefined) { if (body.product_url !== null && typeof body.product_url !== "string") { return NextResponse.json({ error: "product_url must be a string" }, { status: 400 });