import assert from "node:assert/strict"; import { dirname, join } from "node:path"; import { test } from "node:test"; import { fileURLToPath } from "node:url"; import * as ejs from "ejs"; const dataTable = join(dirname(fileURLToPath(import.meta.url)), "..", "views", "partials", "data-table.ejs"); const render = (data: Record = {}): Promise => ejs.renderFile(dataTable, data); const flat = (s: string): string => s.replace(/>\s+<").replace(/\s+/g, " ").trim(); const config = { caption: "People in the directory", selectable: true, actions: true, columns: [ { label: "Name", sortable: true, sort: "asc", href: "?sort=name&dir=desc" }, // active ascending { label: "Email", sortable: true, href: "?sort=email&dir=asc" }, // sortable, inactive { label: "Team" }, // not sortable { label: "Status" }, { label: "Detail" }, ], rows: [ { name: "Mara Delgado", cells: [ { user: { name: "Mara Delgado", initials: "MD" } }, { text: "mara@x.io", className: "cell-muted cell-mono" }, { text: "Engineering", className: "cell-muted" }, { badge: { tone: "pos", label: "Active" } }, { html: 'open' }, ], actions: [ { label: "Edit", icon: "i-edit", href: "/people/1/edit" }, { label: "Delete", icon: "i-trash", danger: true, separatorBefore: true }, ], }, ], }; test("data-table renders sortable headers, row-select, typed cells, badges and kebab actions", async () => { const html = flat(await render(config)); assert.match(html, /
People in the directory<\/caption>/); // Row-select: header select-all + per-row checkbox with a descriptive label. assert.match(html, /
<\/th>/); assert.match(html, /<\/td>/); // Sortable header — active ascending: aria-sort + link + up icon (& escaped in href). assert.match(html, /Name <\/svg><\/a><\/th>/); // Sortable header — inactive: no aria-sort, neutral sort icon. assert.match(html, /Email <\/svg><\/a><\/th>/); // Non-sortable header — plain text, no button/link. assert.match(html, /Team<\/th>/); // Actions header. assert.match(html, /Actions<\/span><\/th>/); // Typed cells: user identifies the row → ; classed text, badge tone, raw html. assert.match(html, /mara@x.io<\/td>/); assert.match(html, /Engineering<\/td>/); assert.match(html, /<\/span>Active<\/span><\/td>/); assert.match(html, /open<\/a><\/td>/); // Kebab row actions: link item, danger button, separator. assert.match(html, /