import { describe, it, expect } from "vitest"; import { reorderRows } from "./reorderRows"; // Minimal row: the two fields `reorderRows` reads, plus a name to assert on. interface Row { name: string; is_parent?: boolean; depth?: number; } const leaf = (name: string, depth: number): Row => ({ name, is_parent: false, depth }); const sub = (name: string, depth: number): Row => ({ name, is_parent: true, depth }); const names = (rows: Row[]) => rows.map((r) => r.name); // Two levels, depth-first: a root group whose leaves sit before AND after a // sibling sub-group, then a lone root leaf. // Finances // Cadeaux // Impôts (sub-group) // Fédéral // Provincial // Retrait cash <- follows the sibling sub-group "Impôts" // Divers (root leaf) <- follows the root group "Finances" const TWO_LEVELS: Row[] = [ sub("Finances", 0), leaf("Cadeaux", 1), sub("Impôts", 1), leaf("Fédéral", 2), leaf("Provincial", 2), leaf("Retrait cash", 1), leaf("Divers", 0), ]; // Three levels, as the Compare report tree allows (depth is not capped at 2). // A // A1 (sub-group) // A1a (sub-group) // x // y <- follows the sibling sub-group "A1a" // z <- follows the sibling sub-group "A1" const THREE_LEVELS: Row[] = [ sub("A", 0), sub("A1", 1), sub("A1a", 2), leaf("x", 3), leaf("y", 2), leaf("z", 1), ]; describe("reorderRows — subtotals at the bottom (issue #424)", () => { it("two levels: a leaf that follows a sibling sub-group stays outside its block", () => { expect(names(reorderRows(TWO_LEVELS, false))).toEqual([ "Cadeaux", "Fédéral", "Provincial", "Impôts", "Retrait cash", "Finances", "Divers", ]); }); it("three levels: each subtotal follows its own rows only", () => { expect(names(reorderRows(THREE_LEVELS, false))).toEqual(["x", "A1a", "y", "A1", "z", "A"]); }); it("consecutive sibling sub-groups each close on their own leaves", () => { const rows: Row[] = [ sub("Revenus", 0), leaf("Autres", 1), sub("Emploi", 1), leaf("Paie", 2), sub("Gouv", 1), leaf("Alloc", 2), ]; expect(names(reorderRows(rows, false))).toEqual(["Autres", "Paie", "Emploi", "Alloc", "Gouv", "Revenus"]); }); it("keeps every row exactly once", () => { const out = reorderRows(TWO_LEVELS, false); expect(out).toHaveLength(TWO_LEVELS.length); expect(new Set(out)).toEqual(new Set(TWO_LEVELS)); }); }); describe("reorderRows — subtotals on top", () => { it("returns the list unchanged", () => { expect(reorderRows(TWO_LEVELS, true)).toBe(TWO_LEVELS); expect(reorderRows(THREE_LEVELS, true)).toBe(THREE_LEVELS); }); });