Skip to content

Commit 3b774f6

Browse files
authored
refactor(e2e): parse the fuzz summary table with the mdast GFM table stack (#566)
1 parent 36a6cf0 commit 3b774f6

1 file changed

Lines changed: 19 additions & 36 deletions

File tree

‎test/e2e/fuzz.ts‎

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
*/
1313

1414
import { parseArgs } from "node:util";
15+
import { fromMarkdown } from "mdast-util-from-markdown";
16+
import { gfmTableFromMarkdown } from "mdast-util-gfm-table";
17+
import { gfmTable } from "micromark-extension-gfm-table";
1518
import { canonicalDocument } from "../../src/engine/canonical.js";
1619
import { describeRemoval } from "../../src/engine/layers.js";
1720
import { MAX_RETRIES } from "../../src/github/api.js";
@@ -292,51 +295,31 @@ const REQUIRED_CLASSES: Record<WitnessSection, MutationClass[]> = {
292295
};
293296

294297
/**
295-
* A pipe is a delimiter only after an EVEN run of backslashes: the engine escapes cells with
296-
* backslash-then-pipe (markdownCell, src/report/markdown.ts); under HOSTILE_NAMES a broken escape changes a row's separator count.
298+
* The engine escapes a cell's pipes and backslashes (markdownCell, src/report/markdown.ts), so under HOSTILE_NAMES a
299+
* broken escape surfaces as a row whose cell count differs from the header's; the GFM grammar reads the table as
300+
* GitHub renders it, and a malformed delimiter row leaves no table at all.
297301
*/
298302
function summaryTableProblems(summary: string, expectedRows: number): string[] {
299-
const lines = summary.split("\n").map((line) => line.trim());
300-
const start = lines.findIndex((line) => line.startsWith("|"));
301-
if (start === -1) {
302-
// A completed run renders the header and separator even with zero data rows, so absence is an error at any expectedRows.
303+
const tree = fromMarkdown(summary, {
304+
extensions: [gfmTable()],
305+
mdastExtensions: [gfmTableFromMarkdown()],
306+
});
307+
const table = tree.children.find((node) => node.type === "table");
308+
if (table === undefined) {
309+
// A completed run renders the header and delimiter row even with zero data rows, so absence is an error at any expectedRows.
303310
return ["summary carries no markdown table"];
304311
}
305-
const table: string[] = [];
306-
for (let i = start; i < lines.length && lines[i]?.startsWith("|"); i++) {
307-
table.push(lines[i] as string);
308-
}
309-
const separators = (row: string): number => {
310-
let count = 0;
311-
let backslashes = 0;
312-
for (const ch of row) {
313-
if (ch === "\\") {
314-
backslashes++;
315-
continue;
316-
}
317-
if (ch === "|" && backslashes % 2 === 0) {
318-
count++;
319-
}
320-
backslashes = 0;
321-
}
322-
return count;
323-
};
312+
const [width = 0, ...rowWidths] = table.children.map((row) => row.children.length);
324313
const problems: string[] = [];
325-
if (table.length < 2 + expectedRows) {
314+
if (rowWidths.length < expectedRows) {
326315
problems.push(
327-
`summary table has ${table.length} row(s), expected a header + separator + at least ${expectedRows} data row(s)`,
316+
`summary table has ${rowWidths.length} data row(s), expected at least ${expectedRows}`,
328317
);
329318
}
330-
// The loose "any of -:| whitespace" form would accept an empty separator cell.
331-
const separatorCells = (table[1] ?? "").split("|").slice(1, -1);
332-
if (separatorCells.length === 0 || !separatorCells.every((cell) => /^\s*:?-+:?\s*$/.test(cell))) {
333-
problems.push(`summary table separator row is malformed: "${table[1] ?? "(absent)"}"`);
334-
}
335-
const headerCount = separators(table[0] ?? "");
336-
for (const [index, row] of table.entries()) {
337-
if (separators(row) !== headerCount) {
319+
for (const [index, cells] of rowWidths.entries()) {
320+
if (cells !== width) {
338321
problems.push(
339-
`summary table row ${index} has ${separators(row)} cell separator(s), the header has ${headerCount} - a broken pipe escape?`,
322+
`summary table data row ${index + 1} has ${cells} cell(s), the header has ${width} - a broken pipe escape?`,
340323
);
341324
break;
342325
}

0 commit comments

Comments
 (0)