feat: read and write the mairie status carried by CATEGORIES
Two pure modules: statut-mairie.js (string[] -> string[] status logic) and ics-categories.js, which rewrites CATEGORIES in an iCalendar resource behind a structural guard: nothing is written if anything but CATEGORIES changed.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
jourParis,
|
||||
lireStatut,
|
||||
poserIgnore,
|
||||
poserSoumis,
|
||||
retirerStatut,
|
||||
} from "./extension/statut-mairie.js";
|
||||
|
||||
describe("lireStatut", () => {
|
||||
test("aucune catégorie → aucun", () => {
|
||||
expect(lireStatut([])).toEqual({ type: "aucun" });
|
||||
});
|
||||
|
||||
test("tag ignoré", () => {
|
||||
expect(lireStatut(["mairie:ignoré"])).toEqual({ type: "ignoré" });
|
||||
});
|
||||
|
||||
test("tag soumis avec date", () => {
|
||||
expect(lireStatut(["mairie:soumis:2026-08-13"])).toEqual({
|
||||
type: "soumis",
|
||||
jour: "2026-08-13",
|
||||
});
|
||||
});
|
||||
|
||||
test("les catégories des bénévoles n'interfèrent pas", () => {
|
||||
expect(lireStatut(["Concert", "mairie:ignoré"])).toEqual({ type: "ignoré" });
|
||||
expect(lireStatut(["Concert", "Jazz"])).toEqual({ type: "aucun" });
|
||||
});
|
||||
|
||||
test("tag mairie: inconnu → aucun, sans exception", () => {
|
||||
expect(lireStatut(["mairie:bidule"])).toEqual({ type: "aucun" });
|
||||
});
|
||||
|
||||
test("plusieurs tags reconnus → le dernier l'emporte", () => {
|
||||
expect(lireStatut(["mairie:ignoré", "mairie:soumis:2026-08-13"])).toEqual({
|
||||
type: "soumis",
|
||||
jour: "2026-08-13",
|
||||
});
|
||||
expect(lireStatut(["mairie:soumis:2026-08-13", "mairie:ignoré"])).toEqual({
|
||||
type: "ignoré",
|
||||
});
|
||||
});
|
||||
|
||||
test("tag écrit en Unicode décomposé (NFD) → reconnu quand même", () => {
|
||||
const decompose = "mairie:ignoré".normalize("NFD");
|
||||
expect(decompose).not.toBe("mairie:ignoré");
|
||||
expect(lireStatut([decompose])).toEqual({ type: "ignoré" });
|
||||
});
|
||||
|
||||
test("le tag posé est en forme normalisée (NFC)", () => {
|
||||
expect(poserIgnore([])[0]).toBe("mairie:ignoré".normalize("NFC"));
|
||||
});
|
||||
|
||||
test("soumis sans date ou date malformée → jour null", () => {
|
||||
expect(lireStatut(["mairie:soumis"])).toEqual({ type: "soumis", jour: null });
|
||||
expect(lireStatut(["mairie:soumis:hier"])).toEqual({ type: "soumis", jour: null });
|
||||
});
|
||||
});
|
||||
|
||||
describe("poser / retirer", () => {
|
||||
test("poserSoumis remplace le tag existant, préserve ordre et casse des autres", () => {
|
||||
expect(poserSoumis(["Concert", "mairie:ignoré"], "2026-08-13")).toEqual([
|
||||
"Concert",
|
||||
"mairie:soumis:2026-08-13",
|
||||
]);
|
||||
});
|
||||
|
||||
test("poserIgnore deux fois → pas de doublon", () => {
|
||||
expect(poserIgnore(poserIgnore([]))).toEqual(["mairie:ignoré"]);
|
||||
});
|
||||
|
||||
test("poserIgnore sur une liste vide", () => {
|
||||
expect(poserIgnore([])).toEqual(["mairie:ignoré"]);
|
||||
});
|
||||
|
||||
test("poser* écrase même un tag mairie: inconnu", () => {
|
||||
expect(poserIgnore(["Concert", "mairie:bidule"])).toEqual(["Concert", "mairie:ignoré"]);
|
||||
});
|
||||
|
||||
test("retirerStatut enlève le tag et laisse le reste", () => {
|
||||
expect(retirerStatut(["Concert", "mairie:soumis:2026-08-13"])).toEqual(["Concert"]);
|
||||
});
|
||||
|
||||
test("retirerStatut sur une liste sans tag → inchangée", () => {
|
||||
expect(retirerStatut(["Concert", "Jazz"])).toEqual(["Concert", "Jazz"]);
|
||||
});
|
||||
|
||||
test("les entrées ne sont jamais mutées", () => {
|
||||
const categories = ["Concert", "mairie:ignoré"];
|
||||
poserSoumis(categories, "2026-08-13");
|
||||
poserIgnore(categories);
|
||||
retirerStatut(categories);
|
||||
expect(categories).toEqual(["Concert", "mairie:ignoré"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("jourParis", () => {
|
||||
test("23h30 UTC le 31/12 → déjà le 1er janvier à Paris (+01:00)", () => {
|
||||
expect(jourParis(new Date("2025-12-31T23:30:00Z"))).toBe("2026-01-01");
|
||||
});
|
||||
|
||||
test("22h30 UTC en août → déjà le lendemain à Paris (+02:00)", () => {
|
||||
expect(jourParis(new Date("2026-08-13T22:30:00Z"))).toBe("2026-08-14");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user