slik-report 1.0.3 → 1.0.4
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.
- package/dist/index.js +268 -37
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -51,13 +51,12 @@ class AggregatorReporter {
|
|
|
51
51
|
console.warn('AggregatorReporter: JSON report not found at', this.input);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
console.log('AggregatorReporter: JSON file found. Reading file...');
|
|
54
|
+
console.log('AggregatorReporter: JSON data file found. Reading file and Processing...');
|
|
55
55
|
const report = JSON.parse(fs.readFileSync(this.input, 'utf8'));
|
|
56
56
|
// Check if external HTML exists
|
|
57
57
|
const hasExternalHtml = fs.existsSync(this.anotherHTML);
|
|
58
58
|
// Ensure we use a relative path for the HTML src attribute
|
|
59
59
|
const externalHtmlPath = this.anotherHTML;
|
|
60
|
-
console.log('AggregatorReporter: JSON data read. Processing...');
|
|
61
60
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
62
61
|
const historyFile = path.join(this.historyDir, `run-${timestamp}.json`);
|
|
63
62
|
writeFile(historyFile, safeJson(report));
|
|
@@ -70,7 +69,7 @@ class AggregatorReporter {
|
|
|
70
69
|
};
|
|
71
70
|
const htmlContent = this.generateReportHtml(processedReport);
|
|
72
71
|
writeFile(this.outputHtml, htmlContent);
|
|
73
|
-
console.log('
|
|
72
|
+
console.log('Reporter: Report generation successful!', this.outputHtml);
|
|
74
73
|
}
|
|
75
74
|
catch (e) {
|
|
76
75
|
console.error('AggregatorReporter failed:', e);
|
|
@@ -458,6 +457,7 @@ iframe { width: 100%; height: 80vh; border: none; border-radius: 8px; box-shadow
|
|
|
458
457
|
<li class="sidebar-menu-item"><a href="#" class="active" data-tab="overview">Overview</a></li>
|
|
459
458
|
<li class="sidebar-menu-item"><a href="#" data-tab="categories">Categories</a></li>
|
|
460
459
|
<li class="sidebar-menu-item"><a href="#" data-tab="suites">Suites</a></li>
|
|
460
|
+
<li class="sidebar-menu-item"><a href="#" data-tab="execution-view">Execution View</a></li>
|
|
461
461
|
<li class="sidebar-menu-item"><a href="#" data-tab="graphs">Graphs</a></li>
|
|
462
462
|
<li class="sidebar-menu-item"><a href="#" data-tab="timeline">Timeline</a></li>
|
|
463
463
|
<li class="sidebar-menu-item"><a href="#" data-tab="history">Historical Runs</a></li>
|
|
@@ -509,6 +509,13 @@ iframe { width: 100%; height: 80vh; border: none; border-radius: 8px; box-shadow
|
|
|
509
509
|
</div>
|
|
510
510
|
</div>
|
|
511
511
|
|
|
512
|
+
<div id="execution-view" class="tab-content">
|
|
513
|
+
<div class="card">
|
|
514
|
+
<h2>Execution Flow</h2>
|
|
515
|
+
<div id="cy" style="width: 100%; height: 650px; background-color: var(--table-header-bg); border-radius: 8px; border: 1px solid var(--table-border);"></div>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
|
|
512
519
|
<div id="graphs" class="tab-content">
|
|
513
520
|
<div class="card">
|
|
514
521
|
<h2>Test Graphs & Trends</h2>
|
|
@@ -600,6 +607,7 @@ iframe { width: 100%; height: 80vh; border: none; border-radius: 8px; box-shadow
|
|
|
600
607
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
601
608
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
|
602
609
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
|
610
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.26.0/cytoscape.min.js"></script>
|
|
603
611
|
|
|
604
612
|
<script>
|
|
605
613
|
const reportData = ${safeReportJson};
|
|
@@ -663,6 +671,7 @@ let allTests = [];
|
|
|
663
671
|
return;
|
|
664
672
|
}
|
|
665
673
|
|
|
674
|
+
if (targetId === 'execution-view') { renderExecutionView(); }
|
|
666
675
|
if (targetId === 'graphs') { renderCharts(); }
|
|
667
676
|
if (targetId === 'timeline') { renderTimeline(); }
|
|
668
677
|
if (targetId === 'history') { renderHistoryGraph(); }
|
|
@@ -945,6 +954,131 @@ let allTests = [];
|
|
|
945
954
|
}
|
|
946
955
|
}
|
|
947
956
|
|
|
957
|
+
function renderExecutionView() {
|
|
958
|
+
const cyContainer = document.getElementById('cy');
|
|
959
|
+
if (!cyContainer || cyContainer.initialized) return;
|
|
960
|
+
|
|
961
|
+
const elements = [];
|
|
962
|
+
elements.push({ data: { id: 'start', label: 'START', type: 'root' } });
|
|
963
|
+
|
|
964
|
+
reportData.suites.forEach((suite, sIdx) => {
|
|
965
|
+
const suiteId = 'suite_' + sIdx;
|
|
966
|
+
elements.push({
|
|
967
|
+
data: {
|
|
968
|
+
id: suiteId,
|
|
969
|
+
label: suite.title,
|
|
970
|
+
type: 'suite'
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
elements.push({ data: { source: 'start', target: suiteId } });
|
|
974
|
+
|
|
975
|
+
suite.specs.forEach((spec, spIdx) => {
|
|
976
|
+
const test = spec.tests[0];
|
|
977
|
+
const testId = suiteId + '_test_' + spIdx;
|
|
978
|
+
const startTimeStr = test.results?.[0]?.startTime ? new Date(test.results[0].startTime).toLocaleTimeString() : 'N/A';
|
|
979
|
+
const endTimeStr = (test.results?.[0]?.startTime && test.duration)
|
|
980
|
+
? new Date(new Date(test.results[0].startTime).getTime() + test.duration).toLocaleTimeString()
|
|
981
|
+
: 'N/A';
|
|
982
|
+
|
|
983
|
+
elements.push({
|
|
984
|
+
data: {
|
|
985
|
+
id: testId,
|
|
986
|
+
label: spec.title,
|
|
987
|
+
type: 'test',
|
|
988
|
+
status: test.status,
|
|
989
|
+
duration: (test.duration / 1000).toFixed(2) + 's',
|
|
990
|
+
start: startTimeStr,
|
|
991
|
+
end: endTimeStr
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
elements.push({ data: { source: suiteId, target: testId } });
|
|
995
|
+
});
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
const cy = cytoscape({
|
|
999
|
+
container: cyContainer,
|
|
1000
|
+
elements: elements,
|
|
1001
|
+
style: [
|
|
1002
|
+
{
|
|
1003
|
+
selector: 'node',
|
|
1004
|
+
style: {
|
|
1005
|
+
'label': 'data(label)',
|
|
1006
|
+
'background-color': '#2563EB',
|
|
1007
|
+
'color': '#fff',
|
|
1008
|
+
'text-valign': 'center',
|
|
1009
|
+
'text-halign': 'center',
|
|
1010
|
+
'font-size': '10px',
|
|
1011
|
+
'width': '100px',
|
|
1012
|
+
'height': '40px',
|
|
1013
|
+
'shape': 'round-rectangle',
|
|
1014
|
+
'text-wrap': 'wrap',
|
|
1015
|
+
'text-max-width': '90px'
|
|
1016
|
+
}
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
selector: 'node[type="root"]',
|
|
1020
|
+
style: { 'background-color': '#172B4D', 'width': '60px', 'height': '60px', 'shape': 'ellipse', 'font-weight': 'bold' }
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
selector: 'node[type="suite"]',
|
|
1024
|
+
style: { 'background-color': '#6B7280', 'width': '140px', 'font-style': 'italic' }
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
selector: 'node[status="passed"]',
|
|
1028
|
+
style: { 'background-color': '#4CAF50' }
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
selector: 'node[status="failed"]',
|
|
1032
|
+
style: { 'background-color': '#F44336' }
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
selector: 'node[status="skipped"]',
|
|
1036
|
+
style: { 'background-color': '#9E9E9E' }
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
selector: 'edge',
|
|
1040
|
+
style: {
|
|
1041
|
+
'width': 2,
|
|
1042
|
+
'line-color': '#cbd5e1',
|
|
1043
|
+
'target-arrow-color': '#cbd5e1',
|
|
1044
|
+
'target-arrow-shape': 'triangle',
|
|
1045
|
+
'curve-style': 'bezier'
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
],
|
|
1049
|
+
layout: {
|
|
1050
|
+
name: 'breadthfirst',
|
|
1051
|
+
directed: true,
|
|
1052
|
+
padding: 30,
|
|
1053
|
+
spacingFactor: 1.2
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
cy.on('tap', 'node', function(evt){
|
|
1058
|
+
const node = evt.target;
|
|
1059
|
+
const data = node.data();
|
|
1060
|
+
if (data.id === 'start') return;
|
|
1061
|
+
|
|
1062
|
+
document.getElementById('modalTitle').textContent = (data.type === 'suite' ? 'Suite/File: ' : 'Test Case: ') + data.label;
|
|
1063
|
+
modalHeader.innerHTML = '<tr><th>Property</th><th>Value</th></tr>';
|
|
1064
|
+
|
|
1065
|
+
let detailsHtml = '<tr><td>Name</td><td>' + data.label + '</td></tr>';
|
|
1066
|
+
if (data.type === 'test') {
|
|
1067
|
+
detailsHtml += '<tr><td>Status</td><td><span class="status-badge status-' + data.status + '">' + data.status + '</span></td></tr>' +
|
|
1068
|
+
'<tr><td>Duration</td><td>' + data.duration + '</td></tr>' +
|
|
1069
|
+
'<tr><td>Start Time</td><td>' + data.start + '</td></tr>' +
|
|
1070
|
+
'<tr><td>End Time</td><td>' + data.end + '</td></tr>';
|
|
1071
|
+
} else {
|
|
1072
|
+
detailsHtml += '<tr><td>Type</td><td>TestSuite / Source File</td></tr>';
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
modalBody.innerHTML = detailsHtml;
|
|
1076
|
+
modal.style.display = 'block';
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
cyContainer.initialized = true;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
948
1082
|
function renderTags() {
|
|
949
1083
|
const stats = reportData.tagStats;
|
|
950
1084
|
if (!stats || stats.length === 0) return;
|
|
@@ -1122,42 +1256,139 @@ let allTests = [];
|
|
|
1122
1256
|
}
|
|
1123
1257
|
|
|
1124
1258
|
function renderHistoryGraph() {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
{ type: 'bar', label: 'Skipped', data: history.map(h => h.skipped), backgroundColor: 'rgba(158, 158, 158, 0.8)', order: 1 }
|
|
1141
|
-
]
|
|
1142
|
-
},
|
|
1143
|
-
options: {
|
|
1144
|
-
responsive: true, maintainAspectRatio: false,
|
|
1145
|
-
animation: {
|
|
1146
|
-
duration: 1200,
|
|
1147
|
-
easing: 'easeOutQuart'
|
|
1148
|
-
},
|
|
1149
|
-
scales: {
|
|
1150
|
-
x: { stacked: true, },
|
|
1151
|
-
y: { stacked: true, beginAtZero: true, title: { display: true, text: 'Test Count' } },
|
|
1152
|
-
y1: { position: 'right', beginAtZero: true, max: 100, title: { display: true, text: 'Pass Rate (%)' }, grid: { drawOnChartArea: false } }
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
});
|
|
1156
|
-
} else {
|
|
1157
|
-
historyCtx.parentElement.innerHTML = '<div>No historical runs data available.</div>';
|
|
1158
|
-
}
|
|
1259
|
+
const history = reportData.history;
|
|
1260
|
+
document.getElementById('historyRunsTitle').textContent =
|
|
1261
|
+
'Historical Runs (Count: ' + history.length + ')';
|
|
1262
|
+
|
|
1263
|
+
const historyCtx = document.getElementById('historicalRunsChart');
|
|
1264
|
+
|
|
1265
|
+
if (!history || history.length === 0) {
|
|
1266
|
+
historyCtx.parentElement.innerHTML =
|
|
1267
|
+
'<div>No historical runs data available.</div>';
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// Destroy previous chart to avoid leaks / overlays
|
|
1272
|
+
if (historicalRunsChart) {
|
|
1273
|
+
historicalRunsChart.destroy();
|
|
1159
1274
|
}
|
|
1160
1275
|
|
|
1276
|
+
historicalRunsChart = new Chart(historyCtx, {
|
|
1277
|
+
type: 'bar',
|
|
1278
|
+
data: {
|
|
1279
|
+
labels: history.map(h => h.date),
|
|
1280
|
+
datasets: [
|
|
1281
|
+
{
|
|
1282
|
+
type: 'line',
|
|
1283
|
+
label: 'Pass Rate',
|
|
1284
|
+
data: history.map(h => h.passRate), // assume 0–100
|
|
1285
|
+
yAxisID: 'y1',
|
|
1286
|
+
borderColor: 'rgb(255, 159, 64)',
|
|
1287
|
+
pointBackgroundColor: 'rgb(255, 159, 64)',
|
|
1288
|
+
pointRadius: 5,
|
|
1289
|
+
tension: 0.1,
|
|
1290
|
+
order: 0,
|
|
1291
|
+
stack: 'passrate',
|
|
1292
|
+
animations: {
|
|
1293
|
+
opacity: {
|
|
1294
|
+
from: 0,
|
|
1295
|
+
to: 1,
|
|
1296
|
+
duration: 800,
|
|
1297
|
+
easing: 'linear'
|
|
1298
|
+
},
|
|
1299
|
+
tension: {
|
|
1300
|
+
duration: 1200,
|
|
1301
|
+
easing: 'easeOutCubic',
|
|
1302
|
+
from: 0.4,
|
|
1303
|
+
to: 0.1
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
label: 'Passed',
|
|
1309
|
+
data: history.map(h => h.passed),
|
|
1310
|
+
backgroundColor: '#4CAF50',
|
|
1311
|
+
order: 1
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
label: 'Failed',
|
|
1315
|
+
data: history.map(h => h.failed),
|
|
1316
|
+
backgroundColor: 'rgba(255, 99, 132, 0.8)',
|
|
1317
|
+
order: 1
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
label: 'Skipped',
|
|
1321
|
+
data: history.map(h => h.skipped),
|
|
1322
|
+
backgroundColor: 'rgba(158, 158, 158, 0.8)',
|
|
1323
|
+
order: 1
|
|
1324
|
+
}
|
|
1325
|
+
]
|
|
1326
|
+
},
|
|
1327
|
+
options: {
|
|
1328
|
+
responsive: true,
|
|
1329
|
+
maintainAspectRatio: false,
|
|
1330
|
+
animation: {
|
|
1331
|
+
duration: 1800,
|
|
1332
|
+
easing: 'easeOutQuart',
|
|
1333
|
+
delay: (ctx) => {
|
|
1334
|
+
if (ctx.type === 'data') {
|
|
1335
|
+
return ctx.dataIndex * 120;
|
|
1336
|
+
}
|
|
1337
|
+
return 0;
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1340
|
+
animations: {
|
|
1341
|
+
y: {
|
|
1342
|
+
from: 0,
|
|
1343
|
+
duration: 1400,
|
|
1344
|
+
easing: 'easeOutCubic'
|
|
1345
|
+
},
|
|
1346
|
+
opacity: {
|
|
1347
|
+
duration: 800,
|
|
1348
|
+
easing: 'linear',
|
|
1349
|
+
from: 0,
|
|
1350
|
+
to: 1
|
|
1351
|
+
}
|
|
1352
|
+
},
|
|
1353
|
+
plugins: {
|
|
1354
|
+
legend: {
|
|
1355
|
+
position: 'top'
|
|
1356
|
+
},
|
|
1357
|
+
tooltip: {
|
|
1358
|
+
mode: 'index',
|
|
1359
|
+
intersect: false
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
scales: {
|
|
1363
|
+
x: {
|
|
1364
|
+
stacked: true
|
|
1365
|
+
},
|
|
1366
|
+
y: {
|
|
1367
|
+
stacked: true,
|
|
1368
|
+
beginAtZero: true,
|
|
1369
|
+
title: {
|
|
1370
|
+
display: true,
|
|
1371
|
+
text: 'Test Count'
|
|
1372
|
+
}
|
|
1373
|
+
},
|
|
1374
|
+
y1: {
|
|
1375
|
+
type: 'linear',
|
|
1376
|
+
position: 'right',
|
|
1377
|
+
beginAtZero: true,
|
|
1378
|
+
max: 100,
|
|
1379
|
+
title: {
|
|
1380
|
+
display: true,
|
|
1381
|
+
text: 'Pass Rate (%)'
|
|
1382
|
+
},
|
|
1383
|
+
grid: {
|
|
1384
|
+
drawOnChartArea: false
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1161
1392
|
const filterPassed = document.getElementById('filterPassed');
|
|
1162
1393
|
const filterFailed = document.getElementById('filterFailed');
|
|
1163
1394
|
const filterSkipped = document.getElementById('filterSkipped');
|
package/package.json
CHANGED