Ctrl K
ComunidadGuías…

test/shared/attendee-table-rows.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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([]);
  });
});