import assert from "node:assert/strict"; import test from "node:test"; function createRegistrationApi() { const seats = new Map([["CTDL01", 1], ["KTPM01", 0], ["PTTK01", 2]]); const completedPrerequisite = new Set(["SV01", "SV02"]); const enrolled = new Set(); return async function handle(request) { const path = new URL(request.url).pathname; if (path !== "/registrations") return Response.json({ code: "NOT_FOUND" }, { status: 404 }); if (request.method !== "POST") { return Response.json({ code: "METHOD_NOT_ALLOWED" }, { status: 405, headers: { Allow: "POST" } }); } let body; try { body = await request.json(); } catch { return Response.json({ code: "INVALID_JSON" }, { status: 400 }); } const { studentId, courseId } = body ?? {}; if (typeof studentId !== "string" || !studentId.trim() || typeof courseId !== "string" || !courseId.trim()) { return Response.json({ code: "INVALID_INPUT" }, { status: 400 }); } if (!seats.has(courseId)) { return Response.json({ code: "COURSE_NOT_FOUND" }, { status: 404 }); } const key = JSON.stringify([studentId, courseId]); if (enrolled.has(key)) { return Response.json({ code: "ALREADY_ENROLLED" }, { status: 409 }); } if (!completedPrerequisite.has(studentId)) { return Response.json({ code: "MISSING_PREREQUISITE" }, { status: 409 }); } const remaining = seats.get(courseId); if (remaining === 0) { return Response.json({ code: "COURSE_FULL" }, { status: 409 }); } enrolled.add(key); seats.set(courseId, remaining - 1); return Response.json({ studentId, courseId, remainingSeats: remaining - 1 }, { status: 201 }); }; } function post(body) { return new Request("https://example.test/registrations", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }); } test("201 trả dữ liệu đăng ký và số chỗ còn lại", async () => { const api = createRegistrationApi(); const response = await api(post({ studentId: "SV01", courseId: "CTDL01" })); assert.equal(response.status, 201); assert.match(response.headers.get("Content-Type"), /^application\/json/); assert.deepEqual(await response.json(), { studentId: "SV01", courseId: "CTDL01", remainingSeats: 0 }); }); test("400 cho dữ liệu thiếu và 404 cho mã lớp sai", async () => { const api = createRegistrationApi(); for (const [body, status, code] of [ [{ courseId: "CTDL01" }, 400, "INVALID_INPUT"], [{ studentId: "SV01", courseId: "SAI" }, 404, "COURSE_NOT_FOUND"] ]) { const response = await api(post(body)); assert.equal(response.status, status); assert.deepEqual(await response.json(), { code }); } }); test("409 trả đúng lý do và không làm mất chỗ", async () => { const api = createRegistrationApi(); const denied = await api(post({ studentId: "SV03", courseId: "CTDL01" })); assert.equal(denied.status, 409); assert.deepEqual(await denied.json(), { code: "MISSING_PREREQUISITE" }); const accepted = await api(post({ studentId: "SV01", courseId: "CTDL01" })); assert.equal(accepted.status, 201); assert.equal((await accepted.json()).remainingSeats, 0); }); test("phân biệt đăng ký trùng với lớp đầy", async () => { const api = createRegistrationApi(); assert.equal((await api(post({ studentId: "SV01", courseId: "CTDL01" }))).status, 201); const duplicate = await api(post({ studentId: "SV01", courseId: "CTDL01" })); assert.equal(duplicate.status, 409); assert.deepEqual(await duplicate.json(), { code: "ALREADY_ENROLLED" }); const full = await api(post({ studentId: "SV02", courseId: "CTDL01" })); assert.equal(full.status, 409); assert.deepEqual(await full.json(), { code: "COURSE_FULL" }); });