Files
ben-to/scripts/recipes/sprites.unit.test.ts
2026-07-21 16:50:58 +02:00

161 lines
5.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import {
aliasToIconPx,
buildIngredientCoverSprite,
findAliasForIconPx,
foldAccents,
INGREDIENT_SPRITE_CELL,
isPreferredVariantAlias,
normalizeIngredientAliasKey,
parseIngredientSpritesBentext,
resolveIconPxForIngredientName
} from "./sprites.mjs";
describe("parseIngredientSpritesBentext", () => {
it("parse les blocs --- avec coordonnées et alias (| = synonymes)", () => {
const raw = `2 0
eau|vinaigre de riz|Vinaigre blanc
---
0 4
carnet
---
8 1
fromage
`;
const { byAlias, preferredAliases, csv } = parseIngredientSpritesBentext(raw);
// eau → (0, 64) ; carnet → (128, 0) ; fromage → (32, 256) — ligne 8 = preferred
expect(byAlias.eau).toEqual({ x: 0, y: 64, X: 0, Y: 64 });
expect(byAlias["vinaigre de riz"]).toEqual({ x: 0, y: 64, X: 0, Y: 64 });
expect(byAlias["vinaigre blanc"]).toEqual({ x: 0, y: 64, X: 0, Y: 64 });
expect(byAlias.carnet).toEqual({ x: 128, y: 0, X: 128, Y: 0 });
expect(byAlias.fromage).toEqual({ x: 32, y: 256, X: 32, Y: 256 });
expect(preferredAliases.has("fromage")).toBe(true);
expect(preferredAliases.has("eau")).toBe(false);
expect(preferredAliases.has("carnet")).toBe(false);
expect(csv).toContain("carnet");
expect(csv).toContain("fromage");
});
it("ignore un bloc sans coordonnées valides", () => {
const raw = `not_a_coord
eau
---
0 0
couvert
`;
const { byAlias } = parseIngredientSpritesBentext(raw);
expect(byAlias.eau).toBeUndefined();
expect(byAlias.couvert).toEqual({ x: 0, y: 0, X: 0, Y: 0 });
});
it("conserve la première définition en cas de conflit dalias", () => {
const raw = `0 0
eau
---
1 0
eau
`;
const { byAlias } = parseIngredientSpritesBentext(raw);
expect(byAlias.eau).toEqual({ x: 0, y: 0, X: 0, Y: 0 });
});
it("retire le BOM et tolère CRLF entre blocs", () => {
const raw = "\uFEFF0 0\r\ncouvert\r\n---\r\n0 1\r\nassiette\r\n";
const { byAlias } = parseIngredientSpritesBentext(raw);
expect(byAlias.couvert).toBeDefined();
expect(byAlias.assiette).toBeDefined();
});
});
describe("resolveIconPxForIngredientName", () => {
const byAlias = {
riz: { x: 0, y: 0 },
"riz gluant": { x: 32, y: 0 },
avocat: { x: 64, y: 0 }
};
it("trouve lalias direct", () => {
expect(resolveIconPxForIngredientName("riz", byAlias)).toEqual({ x: 0, y: 0 });
});
it("recherche sans accents", () => {
expect(resolveIconPxForIngredientName("AVOCAT", byAlias)).toEqual({ x: 64, y: 0 });
});
it("retombe sur lalias le plus long en inclusion", () => {
expect(resolveIconPxForIngredientName("Riz gluant blanc", byAlias)).toEqual({ x: 32, y: 0 });
});
it("retourne null si pas de correspondance", () => {
expect(resolveIconPxForIngredientName("introuvable", byAlias)).toBeNull();
});
it("gère un nom composé avec / ou et (segments)", () => {
const local = { "eau": { x: 0, y: 0 }, "sel": { x: 32, y: 0 } };
expect(resolveIconPxForIngredientName("Sel / eau", local)).toEqual({ x: 32, y: 0 });
});
});
describe("aliasToIconPx", () => {
it("lit les coordonnées (x, y) ou (X, Y)", () => {
expect(aliasToIconPx({ a: { x: 1, y: 2 } }, "a")).toEqual({ x: 1, y: 2 });
expect(aliasToIconPx({ a: { X: 3, Y: 4 } }, "a")).toEqual({ x: 3, y: 4 });
});
it("retourne null si alias ou coords absentes", () => {
expect(aliasToIconPx({}, "x")).toBeNull();
expect(aliasToIconPx({ a: { x: "a", y: 2 } }, "a")).toBeNull();
});
});
describe("findAliasForIconPx", () => {
it("renvoie lalias correspondant aux coordonnées exactes", () => {
const byAlias = { a: { x: 0, y: 0 }, b: { x: 32, y: 0 } };
expect(findAliasForIconPx(byAlias, { x: 32, y: 0 })).toBe("b");
expect(findAliasForIconPx(byAlias, { x: 100, y: 0 })).toBeNull();
});
});
describe("isPreferredVariantAlias", () => {
it("matche case-insensitive et tolère un set vide", () => {
const preferred = new Set(["fromage", "tomate"]);
expect(isPreferredVariantAlias(preferred, "Fromage")).toBe(true);
expect(isPreferredVariantAlias(preferred, "autre")).toBe(false);
expect(isPreferredVariantAlias(new Set(), "fromage")).toBe(false);
expect(isPreferredVariantAlias(preferred, "")).toBe(false);
});
});
describe("buildIngredientCoverSprite", () => {
const sheet = { width: 512, height: 1024 };
it("renvoie null si coords ou sheet invalides", () => {
expect(buildIngredientCoverSprite(null, sheet)).toBeNull();
expect(buildIngredientCoverSprite({ x: 0, y: 0 }, null)).toBeNull();
});
it("calcule col/row depuis les pixels et fige sheet/cell", () => {
const result = buildIngredientCoverSprite({ x: 64, y: 256 }, sheet);
expect(result).toEqual({
sheet: "/ingredients.png",
col: 2,
row: 8,
cell: INGREDIENT_SPRITE_CELL,
sheetWidth: 512,
sheetHeight: 1024
});
});
});
describe("normalizeIngredientAliasKey & foldAccents", () => {
it("normalise espaces et casse", () => {
expect(normalizeIngredientAliasKey(" Riz gluant ")).toBe("riz gluant");
});
it("plie les accents", () => {
expect(foldAccents("Crème pâtissière")).toBe("creme patissiere");
});
});