@swarmdo/cli 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,182 @@
1
+ /**
2
+ * testreport.ts — parse JUnit-XML / TAP test results into a compact failure
3
+ * digest. The missing front-half of the test→fix loop: an agent runs the suite,
4
+ * points this at the results, and gets exactly the failing test names + file:line
5
+ * + assertion message — instead of re-reading hundreds of log lines — then feeds
6
+ * that into `repair`. Inspired by dorny/test-reporter, action-junit-report,
7
+ * gotestsum.
8
+ *
9
+ * Pure + deterministic: a results string in, a normalized summary out. The file
10
+ * read / glob lives in ../commands/testreport.ts, so this is fixture-testable.
11
+ * No XML dependency — well-formed JUnit escapes <>& in attribute values, so a
12
+ * focused tokenizer over <testcase>/<failure> is safe.
13
+ */
14
+ /** Decode the five predefined XML entities. Pure. */
15
+ function decodeXml(s) {
16
+ return s
17
+ .replace(/&lt;/g, '<')
18
+ .replace(/&gt;/g, '>')
19
+ .replace(/&quot;/g, '"')
20
+ .replace(/&apos;/g, "'")
21
+ .replace(/&#(\d+);/g, (_, d) => String.fromCharCode(parseInt(d, 10)))
22
+ .replace(/&amp;/g, '&'); // last, so &amp;lt; → &lt; not <
23
+ }
24
+ /** Extract key="value" / key='value' attributes from a tag's attribute text. Pure. */
25
+ function parseAttrs(attrText) {
26
+ const out = {};
27
+ const re = /([\w:.-]+)\s*=\s*("([^"]*)"|'([^']*)')/g;
28
+ let m;
29
+ while ((m = re.exec(attrText)) !== null) {
30
+ out[m[1]] = decodeXml(m[3] ?? m[4] ?? '');
31
+ }
32
+ return out;
33
+ }
34
+ /** Pull a `file:line` out of a stack-trace / assertion message. Pure. */
35
+ export function extractFileLine(text) {
36
+ if (!text)
37
+ return {};
38
+ // Prefer a parenthesised frame `(path:line:col)`, else a bare `path:line`.
39
+ const paren = text.match(/\(([^()\s]+?):(\d+):(?:\d+)\)/);
40
+ if (paren)
41
+ return { file: paren[1], line: parseInt(paren[2], 10) };
42
+ const bare = text.match(/([\w./\\-]+\.[a-zA-Z]{1,5}):(\d+)(?::\d+)?/);
43
+ if (bare)
44
+ return { file: bare[1], line: parseInt(bare[2], 10) };
45
+ return {};
46
+ }
47
+ /** Parse JUnit XML (testsuites/testsuite/testcase). Pure. */
48
+ export function parseJUnit(xml) {
49
+ const failures = [];
50
+ let passed = 0, failed = 0, skipped = 0, durationMs = 0;
51
+ const caseRe = /<testcase\b([^>]*?)(?:\/>|>([\s\S]*?)<\/testcase>)/g;
52
+ let c;
53
+ while ((c = caseRe.exec(xml)) !== null) {
54
+ const attrs = parseAttrs(c[1]);
55
+ const body = c[2] ?? '';
56
+ const name = attrs.name ?? '(unnamed)';
57
+ const suite = attrs.classname ?? attrs.suite ?? '';
58
+ if (attrs.time)
59
+ durationMs += Math.round(parseFloat(attrs.time) * 1000) || 0;
60
+ const fail = body.match(/<(failure|error)\b([^>]*?)(?:\/>|>([\s\S]*?)<\/\1>)/);
61
+ const isSkipped = /<skipped\b[^>]*\/?>/.test(body);
62
+ if (fail) {
63
+ failed++;
64
+ const fAttrs = parseAttrs(fail[2]);
65
+ const inner = decodeXml((fail[3] ?? '').trim());
66
+ const message = fAttrs.message || inner.split('\n')[0] || undefined;
67
+ // Prefer explicit file/line attrs (pytest, some emitters), else sniff the trace.
68
+ const loc = attrs.file
69
+ ? { file: attrs.file, line: attrs.line ? parseInt(attrs.line, 10) : undefined }
70
+ : extractFileLine(inner || fAttrs.message || '');
71
+ failures.push({ suite, name, message, type: fAttrs.type, ...loc });
72
+ }
73
+ else if (isSkipped) {
74
+ skipped++;
75
+ }
76
+ else {
77
+ passed++;
78
+ }
79
+ }
80
+ return { passed, failed, skipped, total: passed + failed + skipped, durationMs, failures };
81
+ }
82
+ /** Parse TAP (Test Anything Protocol) output. Pure. */
83
+ export function parseTAP(text) {
84
+ const failures = [];
85
+ let passed = 0, failed = 0, skipped = 0;
86
+ const lines = text.split('\n');
87
+ for (let i = 0; i < lines.length; i++) {
88
+ const line = lines[i];
89
+ const m = line.match(/^(ok|not ok)\b\s*(\d+)?\s*-?\s*(.*)$/);
90
+ if (!m)
91
+ continue;
92
+ const ok = m[1] === 'ok';
93
+ let desc = m[3].trim();
94
+ const directive = desc.match(/#\s*(SKIP|TODO)\b(.*)$/i);
95
+ if (directive)
96
+ desc = desc.slice(0, directive.index).trim();
97
+ if (directive && /skip/i.test(directive[1])) {
98
+ skipped++;
99
+ continue;
100
+ }
101
+ if (ok) {
102
+ passed++;
103
+ }
104
+ else {
105
+ failed++;
106
+ // Look ahead for an indented YAML diagnostic block for message/file/line.
107
+ let message;
108
+ let file;
109
+ let lineNo;
110
+ for (let j = i + 1; j < lines.length; j++) {
111
+ const d = lines[j];
112
+ if (!/^\s/.test(d) && d.trim() !== '')
113
+ break; // dedented → block ended
114
+ const mm = d.match(/^\s*message:\s*(.+)$/);
115
+ if (mm)
116
+ message = mm[1].replace(/^["']|["']$/g, '').trim();
117
+ const fm = d.match(/^\s*(?:file|at):\s*(.+)$/);
118
+ if (fm) {
119
+ const fl = extractFileLine(fm[1]);
120
+ if (fl.file) {
121
+ file = fl.file;
122
+ lineNo = fl.line;
123
+ }
124
+ }
125
+ const lm = d.match(/^\s*line:\s*(\d+)/);
126
+ if (lm)
127
+ lineNo = parseInt(lm[1], 10);
128
+ if (/^\s*\.\.\.\s*$/.test(d))
129
+ break; // end of YAML block
130
+ }
131
+ failures.push({ suite: '', name: desc || '(unnamed)', message, file, line: lineNo });
132
+ }
133
+ }
134
+ return { passed, failed, skipped, total: passed + failed + skipped, durationMs: 0, failures };
135
+ }
136
+ /** Sniff the format from a path extension, then content. Pure. */
137
+ export function detectFormat(content, path) {
138
+ if (path) {
139
+ if (/\.tap$/i.test(path))
140
+ return 'tap';
141
+ if (/\.xml$/i.test(path))
142
+ return 'junit';
143
+ }
144
+ if (/<testsuite|<testcase/i.test(content))
145
+ return 'junit';
146
+ if (/^\s*(TAP version|1\.\.\d|ok\b|not ok\b)/m.test(content))
147
+ return 'tap';
148
+ return 'junit';
149
+ }
150
+ /** Parse by explicit or detected format. Pure. */
151
+ export function parseTestReport(content, format) {
152
+ return format === 'tap' ? parseTAP(content) : parseJUnit(content);
153
+ }
154
+ /** Merge several summaries (multi-file globs). Pure. */
155
+ export function mergeSummaries(list) {
156
+ return list.reduce((acc, s) => ({
157
+ passed: acc.passed + s.passed,
158
+ failed: acc.failed + s.failed,
159
+ skipped: acc.skipped + s.skipped,
160
+ total: acc.total + s.total,
161
+ durationMs: acc.durationMs + s.durationMs,
162
+ failures: acc.failures.concat(s.failures),
163
+ }), { passed: 0, failed: 0, skipped: 0, total: 0, durationMs: 0, failures: [] });
164
+ }
165
+ /** Human-readable digest. Pure. */
166
+ export function formatSummary(s, opts = {}) {
167
+ const head = `${s.passed} passed · ${s.failed} failed · ${s.skipped} skipped (${s.total} total, ${s.durationMs}ms)`;
168
+ if (s.failures.length === 0)
169
+ return head + (s.failed === 0 ? ' ✓' : '');
170
+ const shown = opts.top && opts.top > 0 ? s.failures.slice(0, opts.top) : s.failures;
171
+ const lines = [head, ''];
172
+ for (const f of shown) {
173
+ const where = f.file ? `${f.file}${f.line ? `:${f.line}` : ''}` : '';
174
+ lines.push(`✗ ${f.suite ? f.suite + ' › ' : ''}${f.name}${where ? ` (${where})` : ''}`);
175
+ if (f.message)
176
+ lines.push(` ${f.message.split('\n')[0]}`);
177
+ }
178
+ if (shown.length < s.failures.length)
179
+ lines.push(`… and ${s.failures.length - shown.length} more`);
180
+ return lines.join('\n');
181
+ }
182
+ //# sourceMappingURL=testreport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testreport.js","sourceRoot":"","sources":["../../../src/testreport/testreport.ts"],"names":[],"mappings":"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"}