From a4de8dfda6ce21b0181d9bf8415a2d7f52f9afbb Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 14 Jul 2025 15:32:09 +0200 Subject: [PATCH] impr(leaderboard): daily mode/language buttons based on backend configuration (@fehmer) (#6713) Co-authored-by: Miodec --- .../api/controllers/leaderboard.spec.ts | 41 +- backend/src/api/controllers/leaderboard.ts | 8 + frontend/src/html/pages/leaderboards.html | 8 +- frontend/src/styles/leaderboards.scss | 5 +- frontend/src/ts/ape/server-configuration.ts | 6 + frontend/src/ts/pages/leaderboards.ts | 368 ++++++++++++++---- packages/contracts/src/leaderboards.ts | 2 + 7 files changed, 326 insertions(+), 112 deletions(-) diff --git a/backend/__tests__/api/controllers/leaderboard.spec.ts b/backend/__tests__/api/controllers/leaderboard.spec.ts index c290f54b5..5cae0e151 100644 --- a/backend/__tests__/api/controllers/leaderboard.spec.ts +++ b/backend/__tests__/api/controllers/leaderboard.spec.ts @@ -139,28 +139,29 @@ describe("Loaderboard Controller", () => { ); }); - it("should get for mode", async () => { - getLeaderboardMock.mockResolvedValue([]); - for (const mode of ["time", "words", "quote", "zen", "custom"]) { - const response = await mockApp - .get("/leaderboards") - .query({ language: "english", mode, mode2: "custom" }); - expect(response.status, "for mode " + mode).toEqual(200); - } + describe("should get for modes", async () => { + beforeEach(() => { + getLeaderboardMock.mockResolvedValue([]); + }); + + const testCases = [ + { mode: "time", mode2: "15", language: "english", expectStatus: 200 }, + { mode: "time", mode2: "60", language: "english", expectStatus: 200 }, + { mode: "time", mode2: "30", language: "english", expectStatus: 404 }, + { mode: "words", mode2: "15", language: "english", expectStatus: 404 }, + { mode: "time", mode2: "15", language: "spanish", expectStatus: 404 }, + ]; + it.for(testCases)( + `expect $expectStatus for mode $mode, mode2 $mode2, lang $language`, + async ({ mode, mode2, language, expectStatus }) => { + await mockApp + .get("/leaderboards") + .query({ language, mode, mode2 }) + .expect(expectStatus); + } + ); }); - it("should get for mode2", async () => { - getLeaderboardMock.mockResolvedValue([]); - for (const mode2 of allModes) { - const response = await mockApp.get("/leaderboards").query({ - language: "english", - mode: "words", - mode2, - }); - - expect(response.status, "for mode2 " + mode2).toEqual(200); - } - }); it("fails for missing query", async () => { const { body } = await mockApp.get("/leaderboards").expect(422); diff --git a/backend/src/api/controllers/leaderboard.ts b/backend/src/api/controllers/leaderboard.ts index b789e7780..ffa9b3746 100644 --- a/backend/src/api/controllers/leaderboard.ts +++ b/backend/src/api/controllers/leaderboard.ts @@ -32,6 +32,14 @@ export async function getLeaderboard( ): Promise { const { language, mode, mode2, page, pageSize } = req.query; + if ( + mode !== "time" || + (mode2 !== "15" && mode2 !== "60") || + language !== "english" + ) { + throw new MonkeyError(404, "There is no leaderboard for this mode"); + } + const leaderboard = await LeaderboardsDAL.get( mode, mode2, diff --git a/frontend/src/html/pages/leaderboards.html b/frontend/src/html/pages/leaderboards.html index 5e2344733..d1b7b86f8 100644 --- a/frontend/src/html/pages/leaderboards.html +++ b/frontend/src/html/pages/leaderboards.html @@ -156,7 +156,7 @@ -
+
-