diff --git a/web/src/app/api/requests/[id]/pause/route.test.ts b/web/src/app/api/requests/[id]/pause/route.test.ts new file mode 100644 index 0000000..ad761f7 --- /dev/null +++ b/web/src/app/api/requests/[id]/pause/route.test.ts @@ -0,0 +1,47 @@ +import { describe, it, expect } from "vitest"; +import { POST } from "./route"; +import { prisma } from "@/lib/db"; +import type { Prisma } from "@prisma/client"; + +function req(id: string, paused: boolean) { + return new Request(`http://localhost/api/requests/${id}/pause`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ paused }), + }); +} + +async function seed(jobData: Prisma.JobCreateWithoutRequestInput) { + return prisma.request.create({ + data: { artist: "A", album: "B", status: "pending", job: { create: jobData } }, + include: { job: true }, + }); +} + +describe("per-item pause API", () => { + it("pauses a queued job", async () => { + const created = await seed({ state: "requested" }); + const res = await POST(req(created.id, true), { params: Promise.resolve({ id: created.id }) }); + expect(res.status).toBe(200); + const job = await prisma.job.findUnique({ where: { id: created.job!.id } }); + expect(job?.paused).toBe(true); + }); + + it("resumes a paused job", async () => { + const created = await seed({ state: "requested", paused: true }); + await POST(req(created.id, false), { params: Promise.resolve({ id: created.id }) }); + const job = await prisma.job.findUnique({ where: { id: created.job!.id } }); + expect(job?.paused).toBe(false); + }); + + it("rejects pausing an in-flight job", async () => { + const created = await seed({ state: "downloading" }); + const res = await POST(req(created.id, true), { params: Promise.resolve({ id: created.id }) }); + expect(res.status).toBe(400); + }); + + it("404s for a missing request", async () => { + const res = await POST(req("nope", true), { params: Promise.resolve({ id: "nope" }) }); + expect(res.status).toBe(404); + }); +}); diff --git a/web/src/app/api/requests/[id]/pause/route.ts b/web/src/app/api/requests/[id]/pause/route.ts new file mode 100644 index 0000000..f685b8d --- /dev/null +++ b/web/src/app/api/requests/[id]/pause/route.ts @@ -0,0 +1,26 @@ +import { prisma } from "@/lib/db"; + +export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) { + const { id } = await params; + + let body: { paused?: unknown }; + try { + body = (await request.json()) as { paused?: unknown }; + } catch { + return Response.json({ error: "invalid JSON" }, { status: 400 }); + } + if (typeof body.paused !== "boolean") { + return Response.json({ error: "paused must be a boolean" }, { status: 400 }); + } + + const req = await prisma.request.findUnique({ where: { id }, include: { job: true } }); + if (!req || !req.job) { + return Response.json({ error: "not found" }, { status: 404 }); + } + if (req.job.state !== "requested") { + return Response.json({ error: "only queued jobs can be paused" }, { status: 400 }); + } + + await prisma.job.update({ where: { id: req.job.id }, data: { paused: body.paused } }); + return Response.json({ ok: true, paused: body.paused }); +}