Files
buzz-sheet/lib/guides/extra-sheet.test.ts
T
gunshiz 5aa0ae80c1
CI / Verify (push) Successful in 1m28s
CI / Build immutable images and deploy (push) Successful in 2m5s
feat : update
2026-09-05 18:15:06 +07:00

106 lines
4.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
addExtraSheetColumn,
addExtraSheetRow,
createExtraSheet,
deleteExtraSheetColumn,
deleteExtraSheetRow,
extraSheetSchema,
extraSheetToMatrix,
matrixToExtraSheet,
moveExtraSheetColumn,
moveExtraSheetRow,
normalizeExtraSheetRichText,
updateExtraSheetCell,
} from "@/lib/guides/extra-sheet";
function idFactory() {
let index = 0;
return (prefix: string) => `${prefix}-${++index}`;
}
describe("Extra sheet", () => {
it("creates a valid two-by-two sheet", () => {
const sheet = createExtraSheet(idFactory());
expect(extraSheetSchema.safeParse(sheet).success).toBe(true);
expect(sheet.columns.map((column) => column.label)).toEqual(["คอลัมน์ 1", "คอลัมน์ 2"]);
expect(extraSheetToMatrix(sheet)).toEqual([
[{ value: "" }, { value: "" }],
[{ value: "" }, { value: "" }],
]);
});
it("preserves cell identity while rows and columns move", () => {
const createId = idFactory();
const sheet = createExtraSheet(createId);
const firstColumnId = sheet.columns[0].id;
const secondColumnId = sheet.columns[1].id;
sheet.rows[0].cells[firstColumnId] = "A";
sheet.rows[0].cells[secondColumnId] = "B";
sheet.rows[1].cells[firstColumnId] = "C";
const moved = moveExtraSheetRow(moveExtraSheetColumn(sheet, 0, 1), 0, 1);
expect(extraSheetToMatrix(moved)).toEqual([
[{ value: "" }, { value: "C" }],
[{ value: "B" }, { value: "A" }],
]);
});
it("adds and removes rows and columns without orphaned cells", () => {
const createId = idFactory();
const initial = createExtraSheet(createId);
const columnId = createId("column");
const expanded = addExtraSheetRow(
addExtraSheetColumn(initial, "Notes", columnId),
createId("row"),
);
expect(expanded.rows).toHaveLength(3);
expect(expanded.rows.every((row) => row.cells[columnId] === "")).toBe(true);
const reduced = deleteExtraSheetColumn(expanded, 2);
expect(reduced.rows.every((row) => !(columnId in row.cells))).toBe(true);
expect(deleteExtraSheetRow(reduced, 2).rows).toHaveLength(2);
});
it("expands rows and columns when a pasted matrix is larger", () => {
const createId = idFactory();
const initial = createExtraSheet(createId);
const expanded = matrixToExtraSheet(initial, [
[{ value: "1" }, { value: "2" }, { value: "3" }],
[{ value: "4" }, { value: "5" }, { value: "6" }],
[{ value: "7" }, { value: "8" }, { value: "=1+1" }],
], createId);
expect(expanded.columns).toHaveLength(3);
expect(expanded.rows).toHaveLength(3);
expect(extraSheetToMatrix(expanded)[2][2]?.value).toBe("=1+1");
expect(extraSheetSchema.safeParse(expanded).success).toBe(true);
});
it("rejects duplicate labels and cells for missing columns", () => {
const sheet = createExtraSheet(idFactory());
sheet.columns[1].label = sheet.columns[0].label.toUpperCase();
sheet.rows[0].cells.missing = "orphan";
const result = extraSheetSchema.safeParse(sheet);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error.issues.map((issue) => issue.message)).toContain("ชื่อคอลัมน์ต้องไม่ซ้ำกัน");
expect(result.error.issues.map((issue) => issue.message)).toContain("ไม่พบคอลัมน์ของเซลล์นี้");
}
});
it("updates and sanitizes rich-text cells while preserving legacy text", () => {
const initial = createExtraSheet(idFactory());
const updated = updateExtraSheetCell(initial, 0, 0, "legacy\ntext");
const columnId = updated.columns[0].id;
expect(normalizeExtraSheetRichText(updated).rows[0].cells[columnId]).toBe(
"<p>legacy<br>text</p>",
);
const unsafe = updateExtraSheetCell(updated, 0, 0, "<p><strong>safe</strong><script>bad()</script></p>");
expect(normalizeExtraSheetRichText(unsafe).rows[0].cells[columnId]).toBe(
"<p><strong>safe</strong></p>",
);
});
});