feat(housekeeping): model people workflows

This commit is contained in:
Simo committed 2026-08-29 01:17:51 +02:00
1 parent c325c53774
commit e3f8b51d31
13 files changed
+3736

No files matched your search

@@ -0,0 +1,153 @@
import { describe, expect, it } from "vitest";
import {
createPeoplePage,
normalizePeopleListInput,
normalizePeopleUser,
type PeopleUserDetail,
peopleCfhHref,
peopleGuildHref,
peopleHelpTicketHref,
peopleTicketHref,
peopleUserHref,
toPeopleIsoDate,
} from "./models";
describe("People list normalization", () => {
it("clamps adversarial page size and offset values and bounds search text", () => {
expect(
normalizePeopleListInput(
{
pageSize: 99_999,
offset: -50,
search: ` alice\u0000${"x".repeat(300)} `,
sort: "not-a-column",
order: "sideways",
},
["id", "username"],
"username",
),
).toEqual({
pageSize: 100,
offset: 0,
search: `alicex${"x".repeat(122)}`,
sort: "username",
order: "asc",
});
expect(
normalizePeopleListInput(
{ pageSize: Number.NaN, offset: Number.POSITIVE_INFINITY },
["id"],
"id",
),
).toMatchObject({ pageSize: 20, offset: 0 });
});
it("sorts a page deterministically with an id tie breaker", () => {
const input = normalizePeopleListInput(
{ pageSize: 2, offset: 1, sort: "username", order: "asc" },
["id", "username"],
"id",
);
const page = createPeoplePage(
[
{ id: 4, username: "Bob" },
{ id: 3, username: "alice" },
{ id: 1, username: "Alice" },
{ id: 2, username: "alice" },
],
4,
input,
(row) => row.username,
);
expect(page).toEqual({
items: [
{ id: 2, username: "alice" },
{ id: 3, username: "alice" },
],
total: 4,
pageSize: 2,
offset: 1,
});
});
});
describe("People canonical models", () => {
const rawUser = {
id: 7n,
username: "Alice",
rank: "5",
online: "1",
mail: "[email protected]",
ipCurrent: "203.0.113.9",
bannedUntil: "1700000000",
};
it("projects mail and current IP independently and never substitutes a redaction", () => {
expect(
normalizePeopleUser(rawUser, { includeMail: false, includeIp: false }),
).toEqual({
id: 7,
username: "Alice",
rank: 5,
online: true,
mail: null,
ipCurrent: null,
bannedUntil: 1_700_000_000,
href: "/ase/people/users/7",
});
expect(
normalizePeopleUser(rawUser, { includeMail: true, includeIp: false }),
).toMatchObject({ mail: "[email protected]", ipCurrent: null });
expect(
normalizePeopleUser(rawUser, { includeMail: false, includeIp: true }),
).toMatchObject({ mail: null, ipCurrent: "203.0.113.9" });
});
it("normalizes BigInt and Date values to JSON-safe DTO primitives", () => {
const detail: PeopleUserDetail = {
...normalizePeopleUser(rawUser, {
includeMail: true,
includeIp: true,
}),
motto: "Hello",
look: "hd-180-1",
accountCreated: toPeopleIsoDate(new Date("2026-08-29T10:20:30.000Z")),
lastLogin: toPeopleIsoDate(1_700_000_000),
sanctions: [],
};
expect(JSON.parse(JSON.stringify(detail))).toEqual({
id: 7,
username: "Alice",
rank: 5,
online: true,
mail: "[email protected]",
ipCurrent: "203.0.113.9",
bannedUntil: 1_700_000_000,
href: "/ase/people/users/7",
motto: "Hello",
look: "hd-180-1",
accountCreated: "2026-08-29T10:20:30.000Z",
lastLogin: "2023-11-14T22:13:20.000Z",
sanctions: [],
});
});
it("builds canonical People entity links only", () => {
expect([
peopleUserHref(4),
peopleGuildHref(5),
peopleTicketHref(6),
peopleHelpTicketHref(7),
peopleCfhHref(8),
]).toEqual([
"/ase/people/users/4",
"/ase/people/community/guilds/5",
"/ase/people/support/tickets/6",
"/ase/people/support/help-tickets/7",
"/ase/people/moderation/cfh/8",
]);
});
});