tinyrelayfile
tinyrelay/scripts/chat-tables.test.mjs/

scripts/chat-tables.test.mjs raw
1import test from "node:test";
2import assert from "node:assert/strict";
3import { FakeNode, setup } from "./rooms.test.mjs";
4
5test("chat tables render semantic headers, alignment and uneven rows", () => {
6 const s = setup();
7 const body = s.rooms.chatMarkdown(new FakeNode("div"), "| Name | Notes | Score |\n| :--- | :---: | ---: |\n| Ada | **ready** | 10 |\n| Grace | `a|b` |\n| Alan | left");
8 const region = body.children[0], table = region.querySelector("table");
9 assert.equal(region.getAttribute("data-markdown-table"), "");
10 assert.equal(region.getAttribute("role"), "region");
11 assert.equal(region.getAttribute("aria-label"), "Table");
12 assert.equal(region.getAttribute("tabindex"), "0");
13 assert.deepEqual(table.querySelectorAll("th").map(cell => [cell.getAttribute("scope"), cell.getAttribute("data-align")]), [["col", "left"], ["col", "center"], ["col", "right"]]);
14 assert.equal(table.querySelectorAll("tbody tr").length, 3);
15 assert.equal(table.querySelectorAll("tbody tr")[1].children.length, 3);
16 assert.equal(table.querySelectorAll("tbody tr")[1].children[1].querySelector("code").textContent, "a|b");
17 assert.equal(table.querySelectorAll("tbody tr")[2].children[2].textContent, "");
18 assert.equal(table.querySelector("strong").textContent, "ready");
19});
20
21test("chat tables accept escaped pipes and keep inline content safe", () => {
22 const s = setup();
23 const body = s.rooms.chatMarkdown(new FakeNode("div"), "Label | Link\n--- | ---\nA \\| B | [go](javascript:alert(1)) <img>");
24 const table = body.querySelector("table");
25 assert.equal(table.querySelector("tbody td").textContent, "A | B");
26 assert.equal(table.querySelectorAll("a").length, 0);
27 assert.equal(table.textContent.includes("<img>"), true);
28});
29
30test("chat tables preserve single columns and distinguish escaped trailing pipes", () => {
31 const s = setup();
32 const body = s.rooms.chatMarkdown(new FakeNode("div"), "| Value |\n| --- |\n| `a\\|b` |");
33 assert.equal(body.querySelectorAll("table").length, 1);
34 assert.equal(body.querySelector("th").textContent, "Value");
35 assert.equal(body.querySelector("tbody code").textContent, "a|b");
36 const prose = s.rooms.chatMarkdown(new FakeNode("div"), "A \\\\| B\n| --- |");
37 assert.equal(prose.querySelectorAll("table").length, 0);
38});
39
40test("malformed tables and tables in fenced code remain prose or code", () => {
41 const s = setup();
42 const body = s.rooms.chatMarkdown(new FakeNode("div"), "| Header | Other\n| -- | ---\n\n```\n| A | B |\n| --- | --- |\n```");
43 assert.equal(body.querySelectorAll("[data-markdown-table]").length, 0);
44 assert.equal(body.querySelectorAll("pre").length, 1);
45 assert.equal(body.querySelector("p").textContent, "| Header | Other| -- | ---");
46 assert.equal(body.querySelector("pre").textContent.includes("| A | B |"), true);
47});
48
49test("rerendering edited chat content creates a fresh table node", () => {
50 const s = setup();
51 const body = new FakeNode("div");
52 s.rooms.chatMarkdown(body, "| Before | State |\n| --- | --- |\n| old | draft |");
53 assert.equal(body.querySelector("tbody td").textContent, "old");
54 body.replaceChildren();
55 s.rooms.chatMarkdown(body, "| After | State |\n| --- | --- |\n| new | sent |");
56 assert.equal(body.querySelector("th").textContent, "After");
57 assert.equal(body.querySelector("tbody td").textContent, "new");
58});
59
60test("tables stop before headings and preserve backtick and tilde fences", () => {
61 const s = setup();
62 for (const marker of ["```", " ~~~~"]) {
63 const body = s.rooms.chatMarkdown(new FakeNode("div"), "| Name | Value |\n| --- | --- |\n| one | two |\n" + marker + "text | example\n| A | B |\n|---|---|\n" + marker + "\n# Heading | text");
64 assert.equal(body.querySelectorAll("table").length, 1);
65 assert.equal(body.querySelector("th").getAttribute("data-align"), null);
66 assert.equal(body.querySelectorAll("tbody tr").length, 1);
67 assert.equal(body.querySelector("pre").textContent, "| A | B |\n|---|---|");
68 assert.equal(body.children.find(node => node.localName === "h1").textContent, "Heading | text");
69 }
70});

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs