blob: 02183092b56cc5805ec58e8c9a8880eb27858ccc [file] [log] [blame]
Marc Kupietz3da0c5e2026-07-29 13:59:44 +09001#!/usr/bin/env node
2// Summarizes KorAP.e2e.log into one line per test run matching a keyword.
3//
4// Usage: node summarize-log.js <keyword> [logfile]
5// keyword substring to match against the run's target URL (e.g. "dnb")
6// logfile path to the log file (default: ./KorAP.e2e.log)
7
8const fs = require('fs');
9const path = require('path');
10
11const keyword = process.argv[2];
12const logFile = process.argv[3] || path.join(__dirname, 'KorAP.e2e.log');
13
14if (!keyword) {
15 console.error('Usage: node summarize-log.js <keyword> [logfile]');
16 process.exit(1);
17}
18
19const lines = fs.readFileSync(logFile, 'utf8').split('\n');
20
21const RUN_START_RE = /^\s*Running KorAP UI end-to-end tests on (\S+)/;
22const TIMESTAMP_RE = /^Run started (\S+) on/;
23const CHECK_RE = /^\s*(✔|✘|-)\s+(.+?)(?:\s*\(\d+m?s\))?$/;
24const SUMMARY_RE = /^\s*(\d+) (passing|pending|failing)(?:\s*\(\S+\))?/;
25
26const runs = [];
27let current = null;
28
29for (const line of lines) {
30 const startMatch = line.match(RUN_START_RE);
31 if (startMatch) {
32 current = { url: startMatch[1], timestamp: null, checks: [], summary: {} };
33 runs.push(current);
34 continue;
35 }
36 if (!current) continue;
37
38 const tsMatch = line.match(TIMESTAMP_RE);
39 if (tsMatch) {
40 current.timestamp = tsMatch[1];
41 continue;
42 }
43
44 const checkMatch = line.match(CHECK_RE);
45 if (checkMatch) {
46 const [, mark, name] = checkMatch;
47 const status = mark === '✔' ? 'pass' : mark === '✘' ? 'fail' : 'skip';
48 current.checks.push({ status, name: name.trim() });
49 continue;
50 }
51
52 const summaryMatch = line.match(SUMMARY_RE);
53 if (summaryMatch) {
54 current.summary[summaryMatch[2]] = parseInt(summaryMatch[1], 10);
55 }
56}
57
58const matching = runs.filter(r => r.url.toLowerCase().includes(keyword.toLowerCase()));
59
60if (matching.length === 0) {
61 console.error(`No runs found matching "${keyword}" in ${logFile}`);
62 process.exit(1);
63}
64
65for (const run of matching) {
66 const date = run.timestamp ? run.timestamp.replace('T', ' ').replace(/\.\d+Z$/, '') : 'unknown time';
67 const [datePart, timePart] = date.split(' ');
68
69 const failed = run.checks.filter(c => c.status === 'fail');
70 const passed = run.summary.passing ?? run.checks.filter(c => c.status === 'pass').length;
71 const skipped = run.summary.pending ?? run.checks.filter(c => c.status === 'skip').length;
72
73 const mark = failed.length > 0 ? '✗' : '✓';
74 const info = failed.length > 0
75 ? `${passed} passing, ${failed.length} failing: ${failed.map(c => c.name).join('; ')}`
76 : `${passed} passing, ${skipped} skipped`;
77
78 console.log(`${datePart} ${timePart} ${info} ${mark}`);
79}