184 lines
4.3 KiB
TypeScript
184 lines
4.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
assertPeopleSerializable,
|
|
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 });
|
|
expect(
|
|
normalizePeopleListInput({ offset: 999_999 }, ["id"], "id").offset,
|
|
).toBe(10_000);
|
|
});
|
|
|
|
it("wraps rows already sorted and paged by the adapter", () => {
|
|
const input = normalizePeopleListInput(
|
|
{ pageSize: 2, offset: 1, sort: "username", order: "asc" },
|
|
["id", "username"],
|
|
"id",
|
|
);
|
|
const page = createPeoplePage(
|
|
[
|
|
{ id: 3, username: "alice" },
|
|
{ id: 1, username: "Alice" },
|
|
],
|
|
4,
|
|
input,
|
|
);
|
|
|
|
expect(page).toEqual({
|
|
items: [
|
|
{ id: 3, username: "alice" },
|
|
{ id: 1, 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: [],
|
|
watched: false,
|
|
permission: {
|
|
rankName: "Moderator",
|
|
ranks: [{ id: 5, name: "Moderator" }],
|
|
},
|
|
};
|
|
|
|
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: [],
|
|
watched: false,
|
|
permission: {
|
|
rankName: "Moderator",
|
|
ranks: [{ id: 5, name: "Moderator" }],
|
|
},
|
|
});
|
|
});
|
|
|
|
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",
|
|
]);
|
|
});
|
|
|
|
it("rejects corrupt identifiers and non-serializable date values", () => {
|
|
expect(() =>
|
|
normalizePeopleUser(
|
|
{ ...rawUser, id: 0 },
|
|
{ includeMail: false, includeIp: false },
|
|
),
|
|
).toThrow();
|
|
expect(() => peopleUserHref(Number.MAX_SAFE_INTEGER + 1)).toThrow();
|
|
expect(() => peopleGuildHref(-4)).toThrow();
|
|
expect(() => toPeopleIsoDate("not-a-date")).toThrow();
|
|
expect(() =>
|
|
assertPeopleSerializable({
|
|
id: 7,
|
|
userId: 0,
|
|
href: "/ase/people/users/7",
|
|
}),
|
|
).toThrow();
|
|
});
|
|
});
|