import { setupIDBShim, EventHook } from "@/testing"; import { initDB, loadSets, Database, Card } from "@/mlpccg"; import { PackBuilder, spanByRarity, Cube, Session, DraftOptions } from "@/mlpccg/draft"; setupIDBShim(); const testSessionOptions: DraftOptions = { type: "booster-draft", source: "set", set: "FF", packs: 2, players: 4, spacing: "evenly" }; describe("mlpccg/draft", () => { beforeAll(async () => { jest.setTimeout(15000); await initDB(); await loadSets(); }); test("Set booster packs are generated correctly", async () => { expect(Database).toBeTruthy(); const builder = await PackBuilder.fromSet("FF"); const pack = builder.buildPack(); // Check pack size expect(pack).toHaveLength(12); const rarities = spanByRarity(pack); // Check pack distribution expect(rarities["R"]).toHaveLength(1); expect(rarities["U"]).toHaveLength(3); }); test("Cube can load a newline separated card list", async () => { expect(Database).toBeTruthy(); const cubeCards = ["ff10", "ff11", "ff12", "ff13", "ff14", "ff15"]; const cubeList = cubeCards.join("\n"); const cube = await Cube.fromList(cubeList); const builder = new PackBuilder(cube.schema()); const pack = builder.buildPack(); // Pack size should only be 6, since there are not enough cards for a 12 cards pack expect(pack).toHaveLength(6); // Make sure pack has ALL the cards from the pool, no duplicates const sortedPack = pack.map(c => c.ID).sort(); expect(sortedPack).toEqual(cubeCards); }); test("A session can be initialized", async () => { expect(Database).toBeTruthy(); const session = await Session.create(testSessionOptions); const hook = new EventHook(); hook.hookEmitter(session, "start", "session-start"); session.assign(["test1", "test2"], () => { // Do nothing }); session.start(); await hook.expect("session-start"); }); test("Players receive pick events and can pick cards", async () => { expect(Database).toBeTruthy(); const session = await Session.create(testSessionOptions); const hook = new EventHook(); hook.hookEmitter(session, "start", "session-start"); hook.hookEmitter(session, "next-pack", "session-new-pack"); hook.hookEmitter(session, "next-pick", "session-new-pick"); hook.hookEmitter(session, "player-pick", "session-picked"); hook.hookEmitter(session, "draft-over", "session-done"); session.assign(["test1", "test2"], (name, player) => { player.on("available-picks", cards => { // setTimeout hack to avoid handlers being called before the rest of the code setTimeout(() => player.pick(cards[0].ID), 0); }); }); session.start(); await hook.expect("session-start"); for (let i = 0; i < testSessionOptions.packs; i++) { await hook.expect("session-new-pack"); for (let j = 0; j < 12; j++) { for (let p = 0; p < testSessionOptions.players; p++) { await hook.expect("session-picked"); } if (i < testSessionOptions.packs - 1) { await hook.expect("session-new-pick"); } } } await hook.expect("session-done"); }); test("Sessions can load and draft I8PCube files", async () => { expect(Database).toBeTruthy(); const session = await Session.create({ type: "booster-draft", source: "i8pcube", url: "https://mcg.zyg.ovh/cubes/hamchacube.json", packs: 4, players: 4, spacing: "evenly" }); const hook = new EventHook(); hook.hookEmitter(session, "start", "session-start"); session.assign(["test1"], (_, player) => { hook.hookEmitter(player, "available-picks", "got-cards"); }); session.start(); await hook.expect("session-start"); await hook.expect("got-cards", 1000, (cards: Card[]) => { expect(cards).toHaveLength(12); // Check for 2 or more multicolor cards const multicolor = cards.filter( c => c.Element.length > 1 || (c.Requirement && Object.keys(c.Requirement).length > 1) ); expect(multicolor.length).toBeGreaterThanOrEqual(2); // Check for 2 or more entry cards const entry = cards.filter( c => !c.Requirement || c.Requirement.length < 1 ); expect(entry.length).toBeGreaterThanOrEqual(2); }); }); });