import assert from "node:assert/strict"; import test from "node:test"; import { EVENT_PAGE_SIZE, getEventLocationLabel, getPriceCeiling, parseEventCatalogParams, serializeEventCatalogParams, } from "../src/lib/event-catalog.ts"; import { getEventBrowseLabel, getEventRegistrationMessage, } from "../src/lib/event-ui.ts"; const now = Date.parse("2026-09-30T12:00:00.000Z"); function event(overrides = {}) { return { status: "published", event_type: "on_site", address: "", location: null, start_time: "2026-10-01T12:00:00.000Z", end_time: "2026-10-01T14:00:00.000Z", registration_start_date: "2026-09-29T12:00:00.000Z", registration_end_date: "2026-10-01T12:00:00.000Z", capacity: 20, registration_count: 8, ...overrides, }; } test("uses the agreed Persian status labels for completed, open, and upcoming events", () => { assert.equal(getEventBrowseLabel(event({ status: "completed" }), now), "برگزار شده"); assert.equal(getEventBrowseLabel(event(), now), "درحال برگزاری"); assert.equal( getEventBrowseLabel(event({ registration_start_date: "2026-10-01T12:00:00.000Z" }), now), "به‌زودی", ); assert.equal( getEventBrowseLabel(event({ capacity: 8 }), now), "به‌زودی", ); }); test("uses a distinct registration message for not started, closed, full, and completed events", () => { assert.equal( getEventRegistrationMessage(event({ registration_start_date: "2026-10-01T12:00:00.000Z" }), now), "ثبت‌نام هنوز آغاز نشده است", ); assert.equal( getEventRegistrationMessage(event({ registration_end_date: "2026-09-29T11:59:00.000Z" }), now), "زمان ثبت‌نام به پایان رسیده است", ); assert.equal( getEventRegistrationMessage(event({ capacity: 8 }), now), "ظرفیت ثبت‌نام تکمیل شده است", ); assert.equal( getEventRegistrationMessage(event({ status: "completed" }), now), "این رویداد برگزار شده است", ); }); test("rounds the global price maximum up to the next complete million", () => { assert.equal(getPriceCeiling(650000), 1000000); assert.equal(getPriceCeiling(4300000), 5000000); assert.equal(getPriceCeiling(5000000), 5000000); assert.equal(getPriceCeiling(0), 0); }); test("always provides a location label and applies the requested fallbacks", () => { assert.equal(getEventLocationLabel(event({ event_type: "online" })), "برگزاری آنلاین"); assert.equal(getEventLocationLabel(event({ event_type: "online", address: "گوگلمیت" })), "برگزاری آنلاین"); assert.equal(getEventLocationLabel(event()), "محل برگزاری اعلام نشده"); assert.equal(getEventLocationLabel(event({ address: "ساختمان دانشکده" })), "ساختمان دانشکده"); }); test("round-trips shareable catalog filters and defaults to 12 items per page", () => { const filters = parseEventCatalogParams(new URLSearchParams( "search=برنامه%20نویسی&state=upcoming&event_type=hybrid&date_from=2026-09-20&date_to=2026-09-30&price_min=100000&price_max=500000&page=3", ), 1000000); assert.deepEqual(filters, { search: "برنامه نویسی", state: "upcoming", eventType: "hybrid", dateFrom: "2026-09-20", dateTo: "2026-09-30", priceMin: 100000, priceMax: 500000, freeOnly: false, page: 3, }); assert.deepEqual( parseEventCatalogParams(serializeEventCatalogParams(filters, 1000000), 1000000), filters, ); assert.equal( serializeEventCatalogParams({ search: "", state: "all", eventType: "all", dateFrom: "", dateTo: "", priceMin: 0, priceMax: 1000000, freeOnly: false, page: 1, }, 1000000).toString(), "", ); assert.equal(EVENT_PAGE_SIZE, 12); }); test("omits price bounds from the URL when free-only is enabled", () => { const params = serializeEventCatalogParams({ search: "", state: "upcoming", eventType: "all", dateFrom: "", dateTo: "", priceMin: 350000, priceMax: 1000000, freeOnly: true, page: 1, }, 1000000); assert.equal(params.get("free_only"), "true"); assert.equal(params.has("price_min"), false); assert.equal(params.has("price_max"), false); }); test("ignores invalid or reversed query values and uses safe catalog defaults", () => { assert.deepEqual( parseEventCatalogParams(new URLSearchParams( "state=unknown&event_type=other&date_from=2026-10-02&date_to=2026-10-01&price_min=-1&price_max=nope&page=0", ), 500000), { search: "", state: "all", eventType: "all", dateFrom: "", dateTo: "", priceMin: 0, priceMax: 500000, freeOnly: false, page: 1, }, ); });