sendou.ink/app/components/match-page/utils.test.ts
Kalle 2b5b1b1948
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run
New match page (#3032)
2026-05-04 18:15:10 +03:00

142 lines
3.8 KiB
TypeScript

import { describe, expect, it, test } from "vitest";
import type { CommonUser } from "~/utils/kysely.server";
import { inferSubstitutions, resolveRoomPass } from "./utils";
function user(id: number): CommonUser {
return {
id,
username: `user${id}`,
discordId: `discord${id}`,
discordAvatar: null,
customUrl: null,
};
}
describe("inferSubstitutions", () => {
it("returns an empty array when rosters are unchanged", () => {
const rosters = {
alpha: [user(1), user(2), user(3), user(4)],
bravo: [user(5), user(6), user(7), user(8)],
};
expect(inferSubstitutions(rosters, rosters)).toEqual([]);
});
it("detects a single substitution on alpha", () => {
const previous = {
alpha: [user(1), user(2), user(3), user(4)],
bravo: [user(5), user(6), user(7), user(8)],
};
const current = {
alpha: [user(1), user(2), user(3), user(9)],
bravo: previous.bravo,
};
expect(inferSubstitutions(previous, current)).toEqual([
{ side: "ALPHA", playerOut: user(4), playerIn: user(9) },
]);
});
it("detects substitutions on both sides in the same map transition", () => {
const previous = {
alpha: [user(1), user(2)],
bravo: [user(3), user(4)],
};
const current = {
alpha: [user(1), user(10)],
bravo: [user(11), user(4)],
};
expect(inferSubstitutions(previous, current)).toEqual([
{ side: "ALPHA", playerOut: user(2), playerIn: user(10) },
{ side: "BRAVO", playerOut: user(3), playerIn: user(11) },
]);
});
it("pairs multiple substitutions on the same side by roster order", () => {
const previous = {
alpha: [user(1), user(2), user(3), user(4)],
bravo: [user(5), user(6)],
};
const current = {
alpha: [user(1), user(10), user(3), user(11)],
bravo: previous.bravo,
};
expect(inferSubstitutions(previous, current)).toEqual([
{ side: "ALPHA", playerOut: user(2), playerIn: user(10) },
{ side: "ALPHA", playerOut: user(4), playerIn: user(11) },
]);
});
it("ignores unpaired leavers when no new player joined", () => {
const previous = {
alpha: [user(1), user(2), user(3), user(4)],
bravo: [user(5), user(6)],
};
const current = {
alpha: [user(1), user(2), user(3)],
bravo: previous.bravo,
};
expect(inferSubstitutions(previous, current)).toEqual([]);
});
it("ignores unpaired joiners when no player left", () => {
const previous = {
alpha: [user(1), user(2), user(3)],
bravo: [user(5), user(6)],
};
const current = {
alpha: [user(1), user(2), user(3), user(9)],
bravo: previous.bravo,
};
expect(inferSubstitutions(previous, current)).toEqual([]);
});
it("treats players switching sides as separate substitutions on each side", () => {
const previous = {
alpha: [user(1), user(2)],
bravo: [user(3), user(4)],
};
const current = {
alpha: [user(3), user(4)],
bravo: [user(1), user(2)],
};
expect(inferSubstitutions(previous, current)).toEqual([
{ side: "ALPHA", playerOut: user(1), playerIn: user(3) },
{ side: "ALPHA", playerOut: user(2), playerIn: user(4) },
{ side: "BRAVO", playerOut: user(3), playerIn: user(1) },
{ side: "BRAVO", playerOut: user(4), playerIn: user(2) },
]);
});
});
describe("resolveRoomPass", () => {
test("returns a 4-digit password", () => {
const pass = resolveRoomPass(12345);
expect(pass).toMatch(/^\d{4}$/);
});
test("returns deterministic password for a given numeric seed", () => {
const pass1 = resolveRoomPass(12345);
const pass2 = resolveRoomPass(12345);
expect(pass1).toBe(pass2);
});
test("returns deterministic password for a given string seed", () => {
const pass1 = resolveRoomPass("test-seed");
const pass2 = resolveRoomPass("test-seed");
expect(pass1).toBe(pass2);
});
test("returns different passwords for different seeds", () => {
const pass1 = resolveRoomPass(1);
const pass2 = resolveRoomPass(2);
expect(pass1).not.toBe(pass2);
});
});