From ef5f036251324afe5afba9e972bc54ae7a63ba59 Mon Sep 17 00:00:00 2001 From: Miodec Date: Fri, 5 Jun 2026 19:13:19 +0200 Subject: [PATCH 1/3] chore: add test --- frontend/__tests__/test/events/stats.spec.ts | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/frontend/__tests__/test/events/stats.spec.ts b/frontend/__tests__/test/events/stats.spec.ts index a789dc635957..d7eea1a519f6 100644 --- a/frontend/__tests__/test/events/stats.spec.ts +++ b/frontend/__tests__/test/events/stats.spec.ts @@ -40,6 +40,7 @@ import { logTestEvent, resetTestEvents, getAllTestEvents, + cleanupData, __testing, } from "../../../src/ts/test/events/data"; import { @@ -559,6 +560,35 @@ describe("stats.ts", () => { expect(getKeypressSpacing()).toEqual([]); }); + + it("cleanupData drops post-end keydowns so the timing invariant holds", () => { + // The compareCompletedEvents check in test-logic.ts relies on: + // startToFirstKey + sum(keySpacing) + lastKeyToEnd ≈ testDuration + // In time mode the user often keeps typing during finish()'s fade + // animation. Without filtering, post-end keydowns inflate keySpacing + // while getLastKeypressToEndMs clamps the negative diff to 0, breaking + // the invariant. finish() calls cleanupData() before the check — + // that's the centralised filter; this test exercises the same path. + (Config as { mode: string }).mode = "time"; + logTestEvent("timer", 0, timer("start", 0)); + logTestEvent("keydown", 500, keyDown()); + logTestEvent("keyup", 580, keyUp()); + logTestEvent("keydown", 700, keyDown()); + logTestEvent("keyup", 780, keyUp()); + logTestEvent("timer", 1000, timer("step", 1)); + logTestEvent("timer", 1000, timer("end", 1)); + // user keeps typing through the fade + logTestEvent("keydown", 1120, keyDown()); + logTestEvent("keyup", 1170, keyUp()); + + cleanupData(); + + const sumSpacing = getKeypressSpacing().reduce((a, b) => a + b, 0); + const total = + getStartToFirstKeypressMs() + sumSpacing + getLastKeypressToEndMs(); + + expect(Math.abs(getTestDurationMs() - total)).toBeLessThan(100); + }); }); describe("getKeypressOverlap", () => { From 4b8fc7648e2696c3bc6d27055b9f3ee0532ba072 Mon Sep 17 00:00:00 2001 From: Miodec Date: Fri, 5 Jun 2026 19:29:49 +0200 Subject: [PATCH 2/3] chore: ignore some keys --- frontend/src/ts/test/test-logic.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index a4ab1ccd2848..136238407f09 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -931,9 +931,19 @@ function compareCompletedEvents( const mismatchedKeys: string[] = []; const ceKeys = Object.keys(ce) as (keyof typeof ce)[]; for (const key of ceKeys) { + if ( + key === "keyDuration" || + key === "keySpacing" || + key === "afkDuration" || + key === "chartData" + ) { + continue; + } + let val1 = ce[key]; let val2 = ce2[key]; + //@ts-expect-error asdf if (key === "keyDuration" || key === "keySpacing") { const a = (val1 as number[]).map((v) => Numbers.roundTo2(v)); const b = (val2 as number[]).map((v) => Numbers.roundTo2(v)); @@ -1034,6 +1044,7 @@ function compareCompletedEvents( // }; // } + //@ts-expect-error asdf if (key === "chartData") { const v1 = val1 as CompletedEvent["chartData"]; const v2 = val2 as CompletedEvent["chartData"]; From 1b508b117f62d8adbf4977ba65f5412800dd2b68 Mon Sep 17 00:00:00 2001 From: Miodec Date: Fri, 5 Jun 2026 19:30:29 +0200 Subject: [PATCH 3/3] chore: bump version --- frontend/src/ts/test/test-logic.ts | 2 +- packages/contracts/src/results.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 136238407f09..31c0d30c113d 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -1294,7 +1294,7 @@ function compareCompletedEvents( difficulty: ce.difficulty, duration: ce.testDuration, funboxes: getActiveFunboxNames().join(","), - version: 7, + version: 8, // ce: ce as Record, // ce2: ce2 as Record, }, diff --git a/packages/contracts/src/results.ts b/packages/contracts/src/results.ts index a260e4de41af..45d71741aa92 100644 --- a/packages/contracts/src/results.ts +++ b/packages/contracts/src/results.ts @@ -75,7 +75,7 @@ export const ReportCompletedEventMismatchRequestSchema = z.object({ difficulty: DifficultySchema.optional(), duration: z.number().max(200).optional(), funboxes: z.string().max(100).optional(), - version: z.literal(7), + version: z.literal(8), // ce: z.record(z.unknown()), // ce2: z.record(z.unknown()), });