Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions frontend/__tests__/test/events/stats.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
logTestEvent,
resetTestEvents,
getAllTestEvents,
cleanupData,
__testing,
} from "../../../src/ts/test/events/data";
import {
Expand Down Expand Up @@ -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", () => {
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/ts/test/test-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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"];
Expand Down Expand Up @@ -1283,7 +1294,7 @@ function compareCompletedEvents(
difficulty: ce.difficulty,
duration: ce.testDuration,
funboxes: getActiveFunboxNames().join(","),
version: 7,
version: 8,
// ce: ce as Record<string, unknown>,
// ce2: ce2 as Record<string, unknown>,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/src/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
});
Expand Down
Loading