Files
OpenFrontIO/tests/StatsColumns.test.ts
T
RyanandGitHub d76a0c4009 feat(client): configurable leaderboard and team stats columns (#4646)
## Description:

- rips out some duped code, making tables use the same layout, where the
only thing different is the row content.
- updated text to be emojis to save space
- updated columns to be as wide as they need to be
- updated cells to have left/right thin borders to read easier
- added more supported column types
- removed the + button to always show everyone, where the current player
is either at the bottom or in the top 5
- added a cogwheel to change options
- can select different options for each menu type (player/team stats)

<img width="582" height="630" alt="image"
src="https://github.com/user-attachments/assets/e54dc3d5-eb2c-4bab-8732-06bea68aec45"
/>

works fine on mobile, will probably need some future love though (has
h-scroll, so all options can be seen by scrolling):


## 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

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

w.o.n
2026-07-22 13:13:43 -07:00

50 lines
1.5 KiB
TypeScript

import {
COLUMN_DEFS,
columnById,
} from "../src/client/hud/layers/lib/StatsColumns";
import {
COLUMN_IDS,
DEFAULT_STATS_COLUMNS,
} from "../src/client/StatsConstants";
import { makeGameView, makePlayerView, stubConfig } from "./util/viewStubs";
describe("Stats column registry", () => {
it("has unique column ids", () => {
expect(new Set(COLUMN_IDS).size).toBe(COLUMN_DEFS.length);
expect(COLUMN_DEFS.map((column) => column.id)).toEqual(COLUMN_IDS);
});
it("columnById returns the matching def for every id", () => {
for (const def of COLUMN_DEFS) {
expect(columnById(def.id)).toBe(def);
}
});
it("defaults reference valid ids", () => {
for (const id of DEFAULT_STATS_COLUMNS) {
expect(COLUMN_IDS).toContain(id);
}
});
it("evaluates and renders every column", () => {
const game = makeGameView({
config: stubConfig({ maxTroops: () => 1_000 }),
});
const player = makePlayerView({ game });
for (const column of COLUMN_DEFS) {
const value = column.value(player, game);
expect(typeof value).toBe("number");
expect(typeof column.renderValue(value, game)).toBe("string");
}
});
it("renders zero owned percentage when no valid land remains", () => {
const game = makeGameView();
vi.spyOn(game, "numLandTiles").mockReturnValue(0);
vi.spyOn(game, "numTilesWithFallout").mockReturnValue(0);
expect(columnById("tiles").renderValue(1, game)).toBe("0.0%");
});
});