test/shared/attendee-table-rows.test.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import {
attendeeLineRow,
groupAttendeeRows,
withPairBookings,
} from "#shared/attendee-table-rows.ts";
import { pairKey } from "#shared/keys.ts";
import { testAttendee } from "#test-utils/factories.ts";
import type { AttendeeRowListing } from "#types";
/** Listings in display order: Gala (3) before Workshop (7) before Zumba (9) */
const DISPLAY_ORDER: AttendeeRowListing[] = [
{ id: 3, name: "Gala" },
{ id: 7, name: "Workshop" },
{ id: 9, name: "Zumba" },
];
describe("attendeeLineRow", () => {
test("builds a one-listing row copying only the listing's id and name", () => {
const attendee = testAttendee({ id: 5 });
const row = attendeeLineRow(attendee, {
extra: "ignored",
id: 7,
name: "Workshop",
} as AttendeeRowListing);
expect(row.attendee).toBe(attendee);
expect(row.listings).toEqual([{ id: 7, name: "Workshop" }]);
});
});
describe("withPairBookings", () => {
const GALA = DISPLAY_ORDER[0]!;
const WORKSHOP = DISPLAY_ORDER[1]!;
test("gives each line the booking read for its person and listing", () => {
const bookings = new Map([
[pairKey(1, GALA.id), { checked_in: 1, quantity: 3 }],
[pairKey(1, WORKSHOP.id), { checked_in: 0, quantity: 2 }],
]);
const rows = withPairBookings(bookings)([
attendeeLineRow(testAttendee({ id: 1, quantity: 1 }), GALA),
attendeeLineRow(testAttendee({ id: 1, quantity: 2 }), WORKSHOP),
]);
expect(rows.map((row) => row.booking)).toEqual([
{ checked_in: 1, quantity: 3 },
{ checked_in: 0, quantity: 2 },
]);
});
test("throws for a line whose booking was never read", () => {
expect(() =>
withPairBookings(new Map())([
attendeeLineRow(testAttendee({ id: 4 }), GALA),
]),
).toThrow(`No booking read for ${pairKey(4, GALA.id)}`);
});
});
describe("groupAttendeeRows", () => {
test("merges one attendee's lines into a single row with every listing", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 1, listing_id: 7 }),
testAttendee({ id: 1, listing_id: 3 }),
],
DISPLAY_ORDER,
);
expect(rows.length).toBe(1);
expect(rows[0]!.listings).toEqual([
{ id: 3, name: "Gala" },
{ id: 7, name: "Workshop" },
]);
});
test("orders each row's listings by display order, not booking order", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 1, listing_id: 9 }),
testAttendee({ id: 1, listing_id: 7 }),
testAttendee({ id: 1, listing_id: 3 }),
],
DISPLAY_ORDER,
);
expect(rows[0]!.listings.map((l) => l.name)).toEqual([
"Gala",
"Workshop",
"Zumba",
]);
});
test("sums the quantity across an attendee's lines", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 1, listing_id: 3, quantity: 2 }),
testAttendee({ id: 1, listing_id: 7, quantity: 3 }),
],
DISPLAY_ORDER,
);
expect(rows[0]!.attendee.quantity).toBe(5);
});
test("keeps the first line's other attendee fields", () => {
const rows = groupAttendeeRows(
[
testAttendee({ date: "2026-03-01", id: 1, listing_id: 3 }),
testAttendee({ date: "2026-04-01", id: 1, listing_id: 7 }),
],
DISPLAY_ORDER,
);
expect(rows[0]!.attendee.date).toBe("2026-03-01");
});
test("lists a listing once even when the attendee has several lines on it", () => {
const rows = groupAttendeeRows(
[
testAttendee({ date: "2026-03-01", id: 1, listing_id: 3 }),
testAttendee({ date: "2026-03-02", id: 1, listing_id: 3 }),
],
DISPLAY_ORDER,
);
expect(rows[0]!.listings).toEqual([{ id: 3, name: "Gala" }]);
});
test("keeps distinct attendees on separate rows in first-seen order", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 2, listing_id: 7, name: "Bob" }),
testAttendee({ id: 1, listing_id: 3, name: "Alice" }),
testAttendee({ id: 2, listing_id: 3, name: "Bob" }),
],
DISPLAY_ORDER,
);
expect(rows.map((r) => r.attendee.id)).toEqual([2, 1]);
expect(rows[0]!.listings.map((l) => l.id)).toEqual([3, 7]);
expect(rows[1]!.listings.map((l) => l.id)).toEqual([3]);
});
test("drops a line whose listing is unknown but keeps the attendee's other lines", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 1, listing_id: 0 }),
testAttendee({ id: 1, listing_id: 3 }),
],
DISPLAY_ORDER,
);
expect(rows[0]!.listings).toEqual([{ id: 3, name: "Gala" }]);
});
test("omits an attendee whose every line has an unknown listing", () => {
const rows = groupAttendeeRows(
[
testAttendee({ id: 1, listing_id: 0 }),
testAttendee({ id: 2, listing_id: 3 }),
],
DISPLAY_ORDER,
);
expect(rows.map((r) => r.attendee.id)).toEqual([2]);
});
test("returns no rows for no lines", () => {
expect(groupAttendeeRows([], DISPLAY_ORDER)).toEqual([]);
});
});