import { describe, expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import { EventForm } from "../src/client/components/CustomForms.tsx";
import { YourOwn } from "../src/client/components/YourOwn.tsx";
import { EventRow } from "../src/client/components/EventRow.tsx";
import { Colophon } from "../src/client/components/Colophon.tsx";
import { GameMetaProvider } from "../src/client/state/gameMeta.tsx";
import {
asDisplayEvent,
CustomEvent,
type CustomEvents,
type CustomGames,
} from "../src/shared/custom.ts";
import { metaFor } from "../src/shared/games.ts";
import { clockFor } from "../src/shared/time.ts";
/**
* Static-render checks on the F13 surfaces.
*
* Not a substitute for using the thing, but they pin the two claims the feature
* makes to a reader: their event is marked as theirs, and the end date is
* allowed to be unknown.
*/
const AT = "2026-08-17T12:00:00.000Z";
const GAMES: CustomGames = {
"mygame:limbus-company": {
id: "mygame:limbus-company",
name: "Limbus Company",
hue: "#C74B50",
at: AT,
},
};
const OWN = CustomEvent.parse({
id: "myevent:k3f9qa2m01",
game: "mygame:limbus-company",
title: "Walpurgisnacht",
type: "banner",
summary: null,
startsAt: "2026-08-20T00:00:00.000Z",
startPrecision: "day",
endsAt: "2026-09-03T00:00:00.000Z",
endPrecision: "day",
at: AT,
updatedAt: AT,
});
const EVENTS: CustomEvents = { [OWN.id]: OWN };
function render(node: React.ReactElement): string {
return renderToStaticMarkup(
metaFor(id, GAMES)}>{node},
);
}
describe("YourOwn", () => {
const noop = () => {};
const props = {
games: GAMES,
events: EVENTS,
lanes: ["genshin", "mygame:limbus-company"],
onAddGame: noop,
onEditGame: noop,
onRemoveGame: () => ({ removed: true, blockedBy: 0 }),
onAddEvent: noop,
};
test("lists a reader's game with the events it holds", () => {
const html = render();
expect(html).toContain("Limbus Company");
expect(html).toContain("1 event");
expect(html).toContain("#C74B50");
});
test("shows a game with nothing in it rather than hiding it", () => {
// A game they just made has to appear before it holds anything, or adding
// one looks like it did nothing.
const html = render();
expect(html).toContain("no events yet");
});
});
describe("EventForm", () => {
test("offers an unknown end rather than demanding a date", () => {
// The whole point: a form that made the end mandatory would push the reader
// into inventing one, which is the failure the parsers are forbidden from.
const html = render(
{}}
onCancel={() => {}}
/>,
);
expect(html).toContain("I don't know when it ends");
});
test("puts the reader's own games at the top of the picker, and defaults to one", () => {
// Someone entering an event by hand is usually doing it because the game
// isn't tracked. Two of theirs to prove the group order, not just a swap.
const twoOfMine: CustomGames = {
...GAMES,
"mygame:silver-palace": {
id: "mygame:silver-palace",
name: "Silver Palace",
hue: "#5C7CE0",
at: AT,
},
};
const html = renderToStaticMarkup(
metaFor(id, twoOfMine)}>
{}}
onCancel={() => {}}
/>
,
);
// The game picker is the first select; the second is the event kind.
const picker = html.slice(0, html.indexOf(""));
const order = [...picker.matchAll(/