diff --git a/dist/index.js b/dist/index.js index 4bc2c64..2319ae8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -27782,16 +27782,36 @@ function buildMarkdown(title, reports) { lines.push("", ""); } } - lines.push("### All tests", ""); - lines.push("| Status | Test | Time |"); - lines.push("|--------|------|------|"); - for (const c of all) { - const icon = statusIcon(c.status); - const name = c.classname ? `${c.classname} \u203A ${c.name}` : c.name; - lines.push(`| ${icon} | ${escapeMd(name)} | ${c.time.toFixed(3)}s |`); + if (failed === 0) { + lines.push("### All tests", ""); + lines.push("| Class | Tests | Time |"); + lines.push("|-------|-------|------|"); + for (const { classname, count, time } of groupByClass(all)) { + lines.push(`| ${escapeMd(classname)} | ${count} | ${time.toFixed(3)}s |`); + } + } else { + lines.push("### All tests", ""); + lines.push("| Status | Test | Time |"); + lines.push("|--------|------|------|"); + for (const c of all) { + const icon = statusIcon(c.status); + const name = c.classname ? `${c.classname} \u203A ${c.name}` : c.name; + lines.push(`| ${icon} | ${escapeMd(name)} | ${c.time.toFixed(3)}s |`); + } } return lines.join("\n") + "\n"; } +function groupByClass(cases) { + const groups = /* @__PURE__ */ new Map(); + for (const c of cases) { + const key = c.classname || c.name; + const g = groups.get(key) ?? { count: 0, time: 0 }; + g.count += 1; + g.time += c.time; + groups.set(key, g); + } + return [...groups.entries()].map(([classname, g]) => ({ classname, ...g })).sort((a, b) => a.classname.localeCompare(b.classname)); +} function statusIcon(s) { switch (s) { case "passed": diff --git a/src/main.test.ts b/src/main.test.ts index 0242000..645ed8a 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -90,6 +90,15 @@ test("buildMarkdown: summarizes mixed results with failure detail blocks", () => assert.match(md, /\|\s*:fast_forward:\s*\|/); }); +test("buildMarkdown: collapses to a per-class summary when everything passes", () => { + const xml = fs.readFileSync(path.join(fixtures, "passing.xml"), "utf8"); + const cases = parseJunitXml(xml); + const md = buildMarkdown("Unit tests", [{ file: "passing.xml", cases }]); + assert.match(md, /### All tests/); + assert.match(md, /\| Class \| Tests \| Time \|/); + assert.doesNotMatch(md, /:white_check_mark:/); +}); + test("run: end-to-end over fixtures produces summary, outputs, and annotations", async () => { const outputs: Record = {}; const logLines: string[] = []; diff --git a/src/main.ts b/src/main.ts index 567f50b..ea8bfe8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -199,17 +199,42 @@ export function buildMarkdown(title: string, reports: ParsedReport[]): string { } } - lines.push("### All tests", ""); - lines.push("| Status | Test | Time |"); - lines.push("|--------|------|------|"); - for (const c of all) { - const icon = statusIcon(c.status); - const name = c.classname ? `${c.classname} › ${c.name}` : c.name; - lines.push(`| ${icon} | ${escapeMd(name)} | ${c.time.toFixed(3)}s |`); + if (failed === 0) { + lines.push("### All tests", ""); + lines.push("| Class | Tests | Time |"); + lines.push("|-------|-------|------|"); + for (const { classname, count, time } of groupByClass(all)) { + lines.push(`| ${escapeMd(classname)} | ${count} | ${time.toFixed(3)}s |`); + } + } else { + lines.push("### All tests", ""); + lines.push("| Status | Test | Time |"); + lines.push("|--------|------|------|"); + for (const c of all) { + const icon = statusIcon(c.status); + const name = c.classname ? `${c.classname} › ${c.name}` : c.name; + lines.push(`| ${icon} | ${escapeMd(name)} | ${c.time.toFixed(3)}s |`); + } } return lines.join("\n") + "\n"; } +function groupByClass( + cases: TestCase[], +): { classname: string; count: number; time: number }[] { + const groups = new Map(); + for (const c of cases) { + const key = c.classname || c.name; + const g = groups.get(key) ?? { count: 0, time: 0 }; + g.count += 1; + g.time += c.time; + groups.set(key, g); + } + return [...groups.entries()] + .map(([classname, g]) => ({ classname, ...g })) + .sort((a, b) => a.classname.localeCompare(b.classname)); +} + function statusIcon(s: TestCase["status"]): string { switch (s) { case "passed":