import assert from "node:assert/strict"; import test from "node:test"; import { getEventCardState, getEventRegistrationState, classifyRegistrationError, getPaymentOutcome, getRegistrationOutcome, getEventPath, } from "../src/lib/event-ui.ts"; const now = Date.parse("2026-09-29T12:00:00.000Z"); function event(overrides = {}) { return { status: "published", start_time: "2026-10-01T12:00:00.000Z", end_time: "2026-10-01T14:00:00.000Z", registration_start_date: null, registration_end_date: "2026-09-30T12:00:00.000Z", capacity: 20, registration_count: 8, ...overrides, }; } test("treats a missing capacity as unlimited", () => { assert.deepEqual( getEventRegistrationState(event({ capacity: null }), now), { state: "open", remaining: null }, ); }); test("marks an event full when confirmed registrations reach capacity", () => { assert.deepEqual( getEventRegistrationState(event({ capacity: 8 }), now), { state: "full", remaining: 0 }, ); }); test("uses inclusive registration window boundaries like the backend", () => { assert.equal( getEventRegistrationState(event({ registration_start_date: new Date(now).toISOString() }), now).state, "open", ); assert.equal( getEventRegistrationState(event({ registration_end_date: new Date(now).toISOString() }), now).state, "open", ); }); test("distinguishes unpublished, not-yet-open, and ended registration", () => { assert.equal(getEventRegistrationState(event({ status: "completed" }), now).state, "unavailable"); assert.equal( getEventRegistrationState(event({ registration_start_date: "2026-09-30T12:00:00.000Z" }), now).state, "not_started", ); assert.equal( getEventRegistrationState(event({ registration_end_date: "2026-09-29T11:59:59.000Z" }), now).state, "closed", ); }); test("prioritizes an elapsed registration deadline over a future opening date", () => { assert.equal( getEventRegistrationState(event({ registration_start_date: "2026-09-30T12:00:00.000Z", registration_end_date: "2026-09-28T12:00:00.000Z", }), now).state, "closed", ); }); test("labels completed events separately from registration availability", () => { assert.equal(getEventCardState(event({ status: "completed" }), now), "past"); assert.equal(getEventCardState(event(), now), "upcoming"); assert.equal(getEventCardState(event({ capacity: 8 }), now), "full"); }); test("classifies backend registration errors including Persian duplicate responses", () => { assert.equal(classifyRegistrationError("شما قبلا در این ایونت ثبت‌نام کرده‌اید."), "already_registered"); assert.equal(classifyRegistrationError("زمان ثبت‌نام هنوز آغاز نشده است"), "not_started"); assert.equal(classifyRegistrationError("مهلت ثبت‌نام به پایان رسیده‌است"), "closed"); assert.equal(classifyRegistrationError("ظرفیت شرکت‌کنندگان تکمیل است"), "full"); assert.equal(classifyRegistrationError("network error"), "unknown"); }); test("keeps callback outcomes distinct and never treats unknown as paid", () => { assert.equal(getPaymentOutcome("success"), "paid"); assert.equal(getPaymentOutcome("canceled"), "canceled"); assert.equal(getPaymentOutcome("failed"), "failed"); assert.equal(getPaymentOutcome("pending"), "pending"); assert.equal(getPaymentOutcome("unexpected"), "unknown"); }); test("distinguishes confirmed, pending, canceled, and unknown registrations", () => { assert.equal(getRegistrationOutcome("confirmed"), "confirmed"); assert.equal(getRegistrationOutcome("attended"), "confirmed"); assert.equal(getRegistrationOutcome("pending"), "pending"); assert.equal(getRegistrationOutcome("cancelled"), "canceled"); assert.equal(getRegistrationOutcome("other"), "unknown"); }); test("uses the event id as a detail route when the event has no slug", () => { assert.equal(getEventPath({ id: 42, slug: "" }), "/events/42"); assert.equal(getEventPath({ id: 42, slug: " " }), "/events/42"); assert.equal(getEventPath({ id: 42, slug: "event-title" }), "/events/event-title"); });