feat(characters): use local character catalog

This commit is contained in:
2026-07-17 16:03:18 +08:00
parent a210a98d98
commit b3ebd5cf3b
96 changed files with 1023 additions and 522 deletions
@@ -0,0 +1,47 @@
import { existsSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import {
CHARACTERS,
DEFAULT_CHARACTER,
getCharacterById,
getCharacterBySlug,
} from "@/data/constants/character";
describe("local character catalog", () => {
it("contains immutable and uniquely addressable character profiles", () => {
expect(CHARACTERS.map((character) => character.slug)).toEqual([
"elio",
"maya",
"nayeli",
]);
expect(new Set(CHARACTERS.map((character) => character.id)).size).toBe(
CHARACTERS.length,
);
expect(Object.isFrozen(CHARACTERS)).toBe(true);
expect(Object.isFrozen(DEFAULT_CHARACTER)).toBe(true);
expect(Object.isFrozen(DEFAULT_CHARACTER.assets)).toBe(true);
expect(Object.isFrozen(DEFAULT_CHARACTER.copy)).toBe(true);
});
it("resolves characters by id and normalized slug", () => {
expect(getCharacterById("character_maya")?.displayName).toBe("Maya Tan");
expect(getCharacterBySlug(" NAYELI ")?.displayName).toBe(
"Nayeli Cervantes",
);
expect(getCharacterById("missing")).toBeNull();
expect(getCharacterBySlug("missing")).toBeNull();
});
it("references local assets that exist under public", () => {
for (const character of CHARACTERS) {
for (const assetPath of Object.values(character.assets)) {
expect(
existsSync(join(process.cwd(), "public", assetPath)),
assetPath,
).toBe(true);
}
}
});
});