Files
OpenFrontIO/tests/StatsSchema.test.ts
T
Ryan f32994fbc7 Account Modal Bugfix (#3687)
## Description:

Fix null stat values from LEFT JOIN causing Zod validation failure on
player profiles

https://github.com/openfrontio/infra/pull/316 switched playerStats from
innerJoin to leftJoin so that sessions with no stats row (games that
ended instantly on spawn) are still counted in wins/losses/total.


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
2026-04-15 15:14:11 -07:00

78 lines
2.0 KiB
TypeScript

import { PlayerStatsLeafSchema } from "../src/core/ApiSchemas";
import { PlayerStatsSchema } from "../src/core/StatsSchemas";
function testPlayerSchema(
json: string,
expectSuccess = true,
expectThrow = false,
): void {
const parse = () => {
const raw = JSON.parse(json);
const result = PlayerStatsSchema.safeParse(raw);
return result.success;
};
if (expectSuccess) {
// Expect success
expect(parse()).toBeTruthy();
} else if (!expectThrow) {
// Expect failure
expect(parse()).toBeFalsy();
} else {
// Expect throw
expect(parse).toThrow();
}
}
describe("StatsSchema", () => {
test("Parse empty", () => {
testPlayerSchema("{}");
});
test("Parse partial", () => {
testPlayerSchema('{"units":{"port":["0","0","0","1"]}}');
});
test("Parse invalid", () => {
testPlayerSchema("[]", false);
testPlayerSchema("null", false);
testPlayerSchema('"null"', false);
testPlayerSchema('"undefined"', false);
});
test("Parse failure", () => {
testPlayerSchema("", false, true);
testPlayerSchema("undefined", false, true);
testPlayerSchema("{", false, true);
testPlayerSchema("{}}", false, true);
});
test("null array elements coerce to 0n (LEFT JOIN rows with no stats)", () => {
// Postgres SUM() over all-NULL rows returns NULL. These should parse as 0n.
testPlayerSchema(
'{"attacks":[null,null,null],"betrayals":null,"gold":[null,null,null,null,null,null]}',
);
});
});
describe("PlayerStatsLeafSchema", () => {
test("null stat values coerce to 0n", () => {
const result = PlayerStatsLeafSchema.safeParse({
wins: "0",
losses: "1",
total: "1",
stats: { attacks: [null, null, null], betrayals: null },
});
expect(result.success).toBe(true);
});
test("missing required field (wins) still fails — undefined is not coerced", () => {
const result = PlayerStatsLeafSchema.safeParse({
losses: "1",
total: "1",
stats: {},
});
expect(result.success).toBe(false);
});
});