From 8e6b975e02658216311b56728e02afa81f25be85 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 9 May 2026 11:28:27 +0300 Subject: [PATCH] Fix tournament match pages with BYE not responding 404 Closes #3052 This also fixes these BYE matches having a tournament match chat --- .../TournamentMatchRepository.server.ts | 8 +++++++ .../routes/to.$id.matches.$mid.test.ts | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/app/features/tournament-match/TournamentMatchRepository.server.ts b/app/features/tournament-match/TournamentMatchRepository.server.ts index 24f230816..757eebb18 100644 --- a/app/features/tournament-match/TournamentMatchRepository.server.ts +++ b/app/features/tournament-match/TournamentMatchRepository.server.ts @@ -80,10 +80,18 @@ export async function findMatchById(id: number) { return { ...row, + opponentOne: normalizeOpponent(row.opponentOne), + opponentTwo: normalizeOpponent(row.opponentTwo), bestOf: row.roundMaps.count, }; } +// Kysely's ParseJSONResultsPlugin only parses strings starting with `[` or `{`, +// so the JSON `null` stored for BYE opponents survives as the literal text "null". +function normalizeOpponent(value: T): T | null { + return (value as unknown) === "null" ? null : value; +} + export function findResultById(id: number) { return db .selectFrom("TournamentMatchGameResult") diff --git a/app/features/tournament-match/routes/to.$id.matches.$mid.test.ts b/app/features/tournament-match/routes/to.$id.matches.$mid.test.ts index f2324a934..3ad2b1bca 100644 --- a/app/features/tournament-match/routes/to.$id.matches.$mid.test.ts +++ b/app/features/tournament-match/routes/to.$id.matches.$mid.test.ts @@ -6,6 +6,7 @@ vi.mock("~/features/chat/ChatSystemMessage.server", () => ({ setMetadata: vi.fn(), })); +import { db } from "~/db/sql"; import type { adminActionSchema } from "~/features/tournament/tournament-schemas.server"; import { dbInsertTournament, @@ -246,4 +247,26 @@ describe("Tournament match page", () => { expect(res).toBe(null); }); }); + + describe("BYE matches", () => { + it("should 404 when accessing a BYE match", async () => { + await db + .updateTable("TournamentMatch") + .set({ opponentTwo: JSON.stringify(null) }) + .where("id", "=", 1) + .execute(); + + await expect(loadMatchData()).rejects.toThrow("404"); + }); + + it("should not 404 when an opponent is a TBD placeholder waiting for an earlier match", async () => { + await db + .updateTable("TournamentMatch") + .set({ opponentTwo: JSON.stringify({ id: null }) }) + .where("id", "=", 1) + .execute(); + + await expect(loadMatchData()).resolves.toBeDefined(); + }); + }); });