test-reporting 3.2.0__tar.gz → 3.2.1__tar.gz
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.
- {test_reporting-3.2.0/test_reporting.egg-info → test_reporting-3.2.1}/PKG-INFO +1 -1
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/templates/project.html +101 -57
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/templates/run.html +7 -7
- {test_reporting-3.2.0 → test_reporting-3.2.1}/setup.py +1 -1
- {test_reporting-3.2.0 → test_reporting-3.2.1/test_reporting.egg-info}/PKG-INFO +1 -1
- {test_reporting-3.2.0 → test_reporting-3.2.1}/LICENSE +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/README.md +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/__init__.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/classifier.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/cli.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/config.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/plugin.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/publisher.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/storage.py +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/reporting/templates/index.html +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/setup.cfg +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/test_reporting.egg-info/SOURCES.txt +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/test_reporting.egg-info/dependency_links.txt +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/test_reporting.egg-info/entry_points.txt +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/test_reporting.egg-info/requires.txt +0 -0
- {test_reporting-3.2.0 → test_reporting-3.2.1}/test_reporting.egg-info/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
|
7
7
|
<meta http-equiv="Pragma" content="no-cache" />
|
|
8
8
|
<meta http-equiv="Expires" content="0" />
|
|
9
|
-
<title>Project
|
|
9
|
+
<title>Project - Test Dashboard</title>
|
|
10
10
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
|
11
11
|
<style>
|
|
12
12
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -157,6 +157,8 @@
|
|
|
157
157
|
td { padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
|
|
158
158
|
tr:last-child td { border-bottom: none; }
|
|
159
159
|
tr:hover td { background: var(--bg); }
|
|
160
|
+
tr.clickable-row { cursor: pointer; }
|
|
161
|
+
tr.clickable-row:hover td { background: var(--blue-bg); }
|
|
160
162
|
.test-name { font-weight: 600; max-width: 280px; overflow: hidden;
|
|
161
163
|
text-overflow: ellipsis; white-space: nowrap; }
|
|
162
164
|
.file-name { color: var(--muted); font-size: 12px; margin-top: 2px; }
|
|
@@ -271,6 +273,13 @@
|
|
|
271
273
|
opacity: 0; transition: opacity .15s; z-index: 200;
|
|
272
274
|
}
|
|
273
275
|
[data-tooltip]:hover::after { opacity: 1; }
|
|
276
|
+
|
|
277
|
+
/* ── Expandable tables ── */
|
|
278
|
+
.table-expand-btn { padding: 12px 24px; text-align: center; border-top: 1px solid var(--border);
|
|
279
|
+
cursor: pointer; color: var(--blue); font-size: 13px; font-weight: 600;
|
|
280
|
+
transition: background .1s; }
|
|
281
|
+
.table-expand-btn:hover { background: var(--bg); }
|
|
282
|
+
.table-row-hidden { display: none; }
|
|
274
283
|
</style>
|
|
275
284
|
</head>
|
|
276
285
|
<body>
|
|
@@ -325,7 +334,7 @@
|
|
|
325
334
|
|
|
326
335
|
/* ── Helpers ── */
|
|
327
336
|
function relTime(iso) {
|
|
328
|
-
if (!iso) return '
|
|
337
|
+
if (!iso) return '-';
|
|
329
338
|
const diff = Date.now() - new Date(iso).getTime();
|
|
330
339
|
const m = Math.floor(diff / 60000);
|
|
331
340
|
if (m < 1) return 'Just now';
|
|
@@ -336,12 +345,12 @@
|
|
|
336
345
|
}
|
|
337
346
|
|
|
338
347
|
function fmtDate(iso) {
|
|
339
|
-
if (!iso) return '
|
|
348
|
+
if (!iso) return '-';
|
|
340
349
|
return new Date(iso).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
|
|
341
350
|
}
|
|
342
351
|
|
|
343
352
|
function fmtDur(s) {
|
|
344
|
-
if (!s || s === 0) return '
|
|
353
|
+
if (!s || s === 0) return '-';
|
|
345
354
|
if (s >= 60) return Math.floor(s / 60) + 'm ' + Math.floor(s % 60) + 's';
|
|
346
355
|
return s.toFixed(1) + 's';
|
|
347
356
|
}
|
|
@@ -519,7 +528,7 @@
|
|
|
519
528
|
return hero +
|
|
520
529
|
'<div class="section">' +
|
|
521
530
|
'<div class="section-head">' +
|
|
522
|
-
'<h3>
|
|
531
|
+
'<h3>Recent Test Runs</h3>' +
|
|
523
532
|
'<p class="section-explain">Each group shows all test files that ran together on a given tag. Click a test file to see the full test breakdown.</p>' +
|
|
524
533
|
'</div>' +
|
|
525
534
|
'<div class="section-body">' + regsHtml + '</div>' +
|
|
@@ -533,6 +542,21 @@
|
|
|
533
542
|
ch.classList.toggle('open', open);
|
|
534
543
|
}
|
|
535
544
|
|
|
545
|
+
function toggleTableRows(btn) {
|
|
546
|
+
const table = btn.previousElementSibling;
|
|
547
|
+
const hiddenRows = table.querySelectorAll('.table-row-hidden');
|
|
548
|
+
const isExpanded = hiddenRows[0].style.display === 'table-row';
|
|
549
|
+
|
|
550
|
+
hiddenRows.forEach(function(row) {
|
|
551
|
+
row.style.display = isExpanded ? 'none' : 'table-row';
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
const count = hiddenRows.length;
|
|
555
|
+
btn.textContent = isExpanded
|
|
556
|
+
? 'Show ' + count + ' more ▼'
|
|
557
|
+
: 'Show less ▲';
|
|
558
|
+
}
|
|
559
|
+
|
|
536
560
|
function goToRun(runId) {
|
|
537
561
|
if (runId) location.href = 'run.html?r=' + encodeURIComponent(runId) + '&p=' + encodeURIComponent(projectName);
|
|
538
562
|
}
|
|
@@ -567,33 +591,31 @@
|
|
|
567
591
|
'</div>' +
|
|
568
592
|
'</div>' +
|
|
569
593
|
|
|
570
|
-
'<div class="
|
|
571
|
-
'<div class="section">' +
|
|
572
|
-
'<
|
|
573
|
-
|
|
574
|
-
'<p class="section-explain">Failure type breakdown. Real bugs need code fixes; infrastructure issues are environment problems.</p>' +
|
|
575
|
-
'</div>' +
|
|
576
|
-
'<div class="section-body">' +
|
|
577
|
-
((a.failure_type_breakdown || []).length === 0
|
|
578
|
-
? '<p class="empty-section">No failures recorded yet.</p>'
|
|
579
|
-
: '<div class="chart-wrap chart-wrap-sm"><canvas id="failureTypeChart"></canvas></div>') +
|
|
580
|
-
'</div>' +
|
|
594
|
+
'<div class="section">' +
|
|
595
|
+
'<div class="section-head">' +
|
|
596
|
+
'<h3>Why Are Tests Failing?</h3>' +
|
|
597
|
+
'<p class="section-explain">Failure type breakdown. Real bugs need code fixes; infrastructure issues are environment problems.</p>' +
|
|
581
598
|
'</div>' +
|
|
599
|
+
'<div class="section-body">' +
|
|
600
|
+
((a.failure_type_breakdown || []).length === 0
|
|
601
|
+
? '<p class="empty-section">No failures recorded yet.</p>'
|
|
602
|
+
: '<div class="chart-wrap chart-wrap-sm"><canvas id="failureTypeChart"></canvas></div>') +
|
|
603
|
+
'</div>' +
|
|
604
|
+
'</div>' +
|
|
582
605
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
'</div>' +
|
|
606
|
+
'<div class="section">' +
|
|
607
|
+
'<div class="section-head">' +
|
|
608
|
+
'<h3>Test File Reliability (Treemap)</h3>' +
|
|
609
|
+
'<p class="section-explain">Each block = one file. Size ∝ test count. Color = pass rate. Worst files at top-left.</p>' +
|
|
610
|
+
'</div>' +
|
|
611
|
+
'<div class="section-body">' +
|
|
612
|
+
renderTreemap(a.file_health || []) +
|
|
591
613
|
'</div>' +
|
|
592
614
|
'</div>' +
|
|
593
615
|
|
|
594
616
|
'<div class="section">' +
|
|
595
617
|
'<div class="section-head">' +
|
|
596
|
-
'<h3>Duration vs Failures
|
|
618
|
+
'<h3>Duration vs Failures - Scatter</h3>' +
|
|
597
619
|
'<p class="section-explain">Each dot = one test. X = avg duration, Y = failure count. Top-right quadrant = highest priority fixes.</p>' +
|
|
598
620
|
'</div>' +
|
|
599
621
|
'<div class="section-body">' +
|
|
@@ -607,7 +629,7 @@
|
|
|
607
629
|
|
|
608
630
|
'<div class="section">' +
|
|
609
631
|
'<div class="section-head">' +
|
|
610
|
-
'<h3>Unreliable Tests
|
|
632
|
+
'<h3>Unreliable Tests - Flaky</h3>' +
|
|
611
633
|
'<p class="section-explain">Tests that pass sometimes and fail other times without code changes. Flaky tests erode trust in your test suite.</p>' +
|
|
612
634
|
'</div>' +
|
|
613
635
|
'<div class="section-body-flush">' +
|
|
@@ -618,32 +640,30 @@
|
|
|
618
640
|
'<div class="section">' +
|
|
619
641
|
'<div class="section-head">' +
|
|
620
642
|
'<h3>Tests That Break the Most</h3>' +
|
|
621
|
-
'<p class="section-explain">Highest-priority fixes
|
|
643
|
+
'<p class="section-explain">Highest-priority fixes - resolving these has the biggest positive impact on your overall pass rate.</p>' +
|
|
622
644
|
'</div>' +
|
|
623
645
|
'<div class="section-body-flush">' +
|
|
624
646
|
renderHotspotsTable(a.failure_hotspots || []) +
|
|
625
647
|
'</div>' +
|
|
626
648
|
'</div>' +
|
|
627
649
|
|
|
628
|
-
'<div class="
|
|
629
|
-
'<div class="section">' +
|
|
630
|
-
'<
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
renderSlowTable(a.slowest_tests || []) +
|
|
636
|
-
'</div>' +
|
|
650
|
+
'<div class="section">' +
|
|
651
|
+
'<div class="section-head">' +
|
|
652
|
+
'<h3>Slowest Tests</h3>' +
|
|
653
|
+
'<p class="section-explain">Tests taking the longest to run. Good candidates for optimization.</p>' +
|
|
654
|
+
'</div>' +
|
|
655
|
+
'<div class="section-body-flush">' +
|
|
656
|
+
renderSlowTable(a.slowest_tests || []) +
|
|
637
657
|
'</div>' +
|
|
658
|
+
'</div>' +
|
|
638
659
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
'</div>' +
|
|
660
|
+
'<div class="section">' +
|
|
661
|
+
'<div class="section-head">' +
|
|
662
|
+
'<h3>Tests Getting Slower</h3>' +
|
|
663
|
+
'<p class="section-explain">Tests that have become significantly slower over the last 7 days. A slowing test can signal feature degradation.</p>' +
|
|
664
|
+
'</div>' +
|
|
665
|
+
'<div class="section-body-flush">' +
|
|
666
|
+
renderRegressionTable(a.performance_regressions || []) +
|
|
647
667
|
'</div>' +
|
|
648
668
|
'</div>';
|
|
649
669
|
}
|
|
@@ -750,55 +770,79 @@
|
|
|
750
770
|
|
|
751
771
|
function renderFlakyTable(tests) {
|
|
752
772
|
if (tests.length === 0) return '<p class="empty-section" style="padding:20px">No flaky tests detected.</p>';
|
|
773
|
+
const limit = 5;
|
|
753
774
|
const rows = tests.map(function(t, i) {
|
|
754
|
-
|
|
775
|
+
const hiddenClass = i >= limit ? ' table-row-hidden' : '';
|
|
776
|
+
const clickAttr = t.last_run_id ? ' class="anim-row clickable-row' + hiddenClass + '" onclick="goToRun(\'' + t.last_run_id + '\')"' : ' class="anim-row' + hiddenClass + '"';
|
|
777
|
+
return '<tr' + clickAttr + ' style="animation-delay:' + (i * 0.04) + 's">' +
|
|
755
778
|
'<td><div class="test-name" title="' + t.test_name + '">' + t.test_name + '</div><div class="file-name">' + t.file_name + '</div></td>' +
|
|
756
779
|
'<td><span class="pill pill-yellow">' + t.pass_rate + '% pass rate</span></td>' +
|
|
757
780
|
'<td style="text-align:center">' + t.passed + '</td>' +
|
|
758
781
|
'<td style="text-align:center;color:var(--red)">' + t.failed + '</td>' +
|
|
759
782
|
'<td style="text-align:center">' + t.total_runs + '</td>' +
|
|
760
|
-
'<td style="color:var(--muted);font-size:12px">' + (t.last_failed ? fmtDate(t.last_failed) : '
|
|
783
|
+
'<td style="color:var(--muted);font-size:12px">' + (t.last_failed ? fmtDate(t.last_failed) : '-') + '</td>' +
|
|
761
784
|
'</tr>';
|
|
762
785
|
}).join('');
|
|
763
|
-
|
|
786
|
+
const expandBtn = tests.length > limit
|
|
787
|
+
? '<div class="table-expand-btn" onclick="toggleTableRows(this)">Show ' + (tests.length - limit) + ' more ▼</div>'
|
|
788
|
+
: '';
|
|
789
|
+
return '<table><thead><tr><th>Test</th><th>Consistency</th><th>Passed</th><th>Failed</th><th>Total Runs</th><th>Last Failed</th></tr></thead><tbody>' + rows + '</tbody></table>' + expandBtn;
|
|
764
790
|
}
|
|
765
791
|
|
|
766
792
|
function renderHotspotsTable(tests) {
|
|
767
793
|
if (tests.length === 0) return '<p class="empty-section" style="padding:20px">No failure hotspots detected yet.</p>';
|
|
794
|
+
const limit = 5;
|
|
768
795
|
const rows = tests.map(function(t, i) {
|
|
769
|
-
|
|
796
|
+
const hiddenClass = i >= limit ? ' table-row-hidden' : '';
|
|
797
|
+
const clickAttr = t.last_run_id ? ' class="anim-row clickable-row' + hiddenClass + '" onclick="goToRun(\'' + t.last_run_id + '\')"' : ' class="anim-row' + hiddenClass + '"';
|
|
798
|
+
return '<tr' + clickAttr + ' style="animation-delay:' + (i * 0.04) + 's">' +
|
|
770
799
|
'<td><div class="test-name" title="' + t.test_name + '">' + t.test_name + '</div><div class="file-name">' + t.file_name + '</div></td>' +
|
|
771
800
|
'<td><span class="pill pill-red">' + t.failure_count + ' failures</span></td>' +
|
|
772
801
|
'<td>' + t.failure_label + '</td>' +
|
|
773
|
-
'<td style="color:var(--muted);font-size:12px">' + (t.last_failed ? fmtDate(t.last_failed) : '
|
|
802
|
+
'<td style="color:var(--muted);font-size:12px">' + (t.last_failed ? fmtDate(t.last_failed) : '-') + '</td>' +
|
|
774
803
|
'</tr>';
|
|
775
804
|
}).join('');
|
|
776
|
-
|
|
805
|
+
const expandBtn = tests.length > limit
|
|
806
|
+
? '<div class="table-expand-btn" onclick="toggleTableRows(this)">Show ' + (tests.length - limit) + ' more ▼</div>'
|
|
807
|
+
: '';
|
|
808
|
+
return '<table><thead><tr><th>Test</th><th>Failure Count</th><th>Cause</th><th>Last Failed</th></tr></thead><tbody>' + rows + '</tbody></table>' + expandBtn;
|
|
777
809
|
}
|
|
778
810
|
|
|
779
811
|
function renderSlowTable(tests) {
|
|
780
812
|
if (tests.length === 0) return '<p class="empty-section" style="padding:20px">Not enough data yet.</p>';
|
|
813
|
+
const limit = 5;
|
|
781
814
|
const rows = tests.map(function(t, i) {
|
|
782
|
-
|
|
815
|
+
const hiddenClass = i >= limit ? ' table-row-hidden' : '';
|
|
816
|
+
const clickAttr = t.last_run_id ? ' class="anim-row clickable-row' + hiddenClass + '" onclick="goToRun(\'' + t.last_run_id + '\')"' : ' class="anim-row' + hiddenClass + '"';
|
|
817
|
+
return '<tr' + clickAttr + ' style="animation-delay:' + (i * 0.04) + 's">' +
|
|
783
818
|
'<td><div class="test-name" title="' + t.test_name + '">' + t.test_name + '</div><div class="file-name">' + t.file_name + '</div></td>' +
|
|
784
819
|
'<td style="font-weight:700">' + fmtDur(t.avg_duration) + '</td>' +
|
|
785
820
|
'<td style="color:var(--muted);font-size:12px">' + fmtDur(t.max_duration) + ' max</td>' +
|
|
786
821
|
'</tr>';
|
|
787
822
|
}).join('');
|
|
788
|
-
|
|
823
|
+
const expandBtn = tests.length > limit
|
|
824
|
+
? '<div class="table-expand-btn" onclick="toggleTableRows(this)">Show ' + (tests.length - limit) + ' more ▼</div>'
|
|
825
|
+
: '';
|
|
826
|
+
return '<table><thead><tr><th>Test</th><th>Avg Duration</th><th>Max</th></tr></thead><tbody>' + rows + '</tbody></table>' + expandBtn;
|
|
789
827
|
}
|
|
790
828
|
|
|
791
829
|
function renderRegressionTable(tests) {
|
|
792
830
|
if (tests.length === 0) return '<p class="empty-section" style="padding:20px">No performance regressions detected.</p>';
|
|
831
|
+
const limit = 5;
|
|
793
832
|
const rows = tests.map(function(t, i) {
|
|
794
|
-
|
|
833
|
+
const hiddenClass = i >= limit ? ' table-row-hidden' : '';
|
|
834
|
+
const clickAttr = t.last_run_id ? ' class="anim-row clickable-row' + hiddenClass + '" onclick="goToRun(\'' + t.last_run_id + '\')"' : ' class="anim-row' + hiddenClass + '"';
|
|
835
|
+
return '<tr' + clickAttr + ' style="animation-delay:' + (i * 0.04) + 's">' +
|
|
795
836
|
'<td><div class="test-name" title="' + t.test_name + '">' + t.test_name + '</div><div class="file-name">' + t.file_name + '</div></td>' +
|
|
796
837
|
'<td style="color:var(--muted);font-size:12px">' + fmtDur(t.historical_avg) + '</td>' +
|
|
797
838
|
'<td style="font-weight:700">' + fmtDur(t.recent_avg) + '</td>' +
|
|
798
839
|
'<td><span class="pill pill-red">+' + t.percent_slower + '% slower</span></td>' +
|
|
799
840
|
'</tr>';
|
|
800
841
|
}).join('');
|
|
801
|
-
|
|
842
|
+
const expandBtn = tests.length > limit
|
|
843
|
+
? '<div class="table-expand-btn" onclick="toggleTableRows(this)">Show ' + (tests.length - limit) + ' more ▼</div>'
|
|
844
|
+
: '';
|
|
845
|
+
return '<table><thead><tr><th>Test</th><th>Was</th><th>Now</th><th>Change</th></tr></thead><tbody>' + rows + '</tbody></table>' + expandBtn;
|
|
802
846
|
}
|
|
803
847
|
|
|
804
848
|
/* ═══════════════════════════════════════════════════
|
|
@@ -835,7 +879,7 @@
|
|
|
835
879
|
return '<tr>' +
|
|
836
880
|
'<td>' + fmtDate(run.timestamp) + '</td>' +
|
|
837
881
|
'<td><div style="font-weight:600;font-size:13px">' + run.file_name + '</div></td>' +
|
|
838
|
-
'<td>' + (run.regression_tag || '
|
|
882
|
+
'<td>' + (run.regression_tag || '-') + '</td>' +
|
|
839
883
|
'<td><span class="pill ' + pc + '">' + run.pass_rate.toFixed(0) + '%</span></td>' +
|
|
840
884
|
'<td>' + run.total_tests + '</td>' +
|
|
841
885
|
'<td style="color:var(--red)">' + run.failed + '</td>' +
|
|
@@ -850,7 +894,7 @@
|
|
|
850
894
|
var canvas = document.getElementById(sid);
|
|
851
895
|
if (!canvas) continue;
|
|
852
896
|
var pts = sparklineIds[sid];
|
|
853
|
-
if (pts.length < 2) { canvas.outerHTML = '<span class="sparkline-none-sm"
|
|
897
|
+
if (pts.length < 2) { canvas.outerHTML = '<span class="sparkline-none-sm">-</span>'; continue; }
|
|
854
898
|
new Chart(canvas, {
|
|
855
899
|
type: 'line',
|
|
856
900
|
data: {
|
|
@@ -1041,7 +1085,7 @@
|
|
|
1041
1085
|
|
|
1042
1086
|
document.getElementById('pageTitle').textContent = proj.name;
|
|
1043
1087
|
document.getElementById('lastRun').textContent = 'Last run ' + relTime(proj.last_run);
|
|
1044
|
-
document.title = proj.name + '
|
|
1088
|
+
document.title = proj.name + ' - Test Dashboard';
|
|
1045
1089
|
|
|
1046
1090
|
const analytics = proj.analytics || {};
|
|
1047
1091
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
|
7
7
|
<meta http-equiv="Pragma" content="no-cache" />
|
|
8
8
|
<meta http-equiv="Expires" content="0" />
|
|
9
|
-
<title>Run Details
|
|
9
|
+
<title>Run Details - Test Dashboard</title>
|
|
10
10
|
<style>
|
|
11
11
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
12
12
|
|
|
@@ -322,14 +322,14 @@
|
|
|
322
322
|
var projectName = params.get('p') || '';
|
|
323
323
|
|
|
324
324
|
function fmtDate(iso) {
|
|
325
|
-
if (!iso) return '
|
|
325
|
+
if (!iso) return '-';
|
|
326
326
|
return new Date(iso).toLocaleString(undefined, {
|
|
327
327
|
month:'short', day:'numeric', year:'numeric',
|
|
328
328
|
hour:'2-digit', minute:'2-digit'
|
|
329
329
|
});
|
|
330
330
|
}
|
|
331
331
|
function fmtDur(s) {
|
|
332
|
-
if (!s || s === 0) return '
|
|
332
|
+
if (!s || s === 0) return '-';
|
|
333
333
|
if (s >= 60) return Math.floor(s/60) + 'm ' + Math.floor(s%60) + 's';
|
|
334
334
|
return s.toFixed(1) + 's';
|
|
335
335
|
}
|
|
@@ -374,13 +374,13 @@
|
|
|
374
374
|
var cls = segClass(f.pass_rate);
|
|
375
375
|
var label = pct > 8 ? f.file_name.replace(/\.py$/, '') : '';
|
|
376
376
|
return '<div class="timeline-seg ' + cls + '" style="flex:' + pct.toFixed(2) + '"'
|
|
377
|
-
+ ' title="' + f.file_name + '
|
|
377
|
+
+ ' title="' + f.file_name + ' - ' + f.pass_rate.toFixed(0) + '% passing (' + f.passed + '/' + f.total + ')"'
|
|
378
378
|
+ ' onclick="scrollToFile(\'' + f.file_name.replace(/'/g, '') + '\')">'
|
|
379
379
|
+ label + '</div>';
|
|
380
380
|
}).join('');
|
|
381
381
|
|
|
382
382
|
return '<div class="timeline-wrap">'
|
|
383
|
-
+ '<div class="timeline-label">Test File Map
|
|
383
|
+
+ '<div class="timeline-label">Test File Map - click to jump</div>'
|
|
384
384
|
+ '<div class="timeline-bar">' + segs + '</div>'
|
|
385
385
|
+ '<div class="timeline-legend">'
|
|
386
386
|
+ '<div class="timeline-legend-item"><div class="legend-dot" style="background:#38a169"></div>Passing (≥95%)</div>'
|
|
@@ -410,7 +410,7 @@
|
|
|
410
410
|
return;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
document.title = (run.suite_name || 'Run') + '
|
|
413
|
+
document.title = (run.suite_name || 'Run') + ' - Test Dashboard';
|
|
414
414
|
document.getElementById('pageTitle').textContent =
|
|
415
415
|
(run.suite_name || 'Run') + ' · ' + (run.project_name || '');
|
|
416
416
|
document.getElementById('runTime').textContent = fmtDate(run.timestamp);
|
|
@@ -441,7 +441,7 @@
|
|
|
441
441
|
/* Timeline */
|
|
442
442
|
var timeline = buildTimeline(files, total);
|
|
443
443
|
|
|
444
|
-
/* Hero
|
|
444
|
+
/* Hero - ring card + metric cards */
|
|
445
445
|
var rateColor2 = ringColor(rate);
|
|
446
446
|
var ringHtml = buildRing(rate);
|
|
447
447
|
var hero = '<div class="hero">'
|
|
@@ -9,7 +9,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name='test-reporting',
|
|
12
|
-
version='3.2.
|
|
12
|
+
version='3.2.1',
|
|
13
13
|
description='Multi-project test reporting dashboard — collect results locally or push to S3',
|
|
14
14
|
long_description=long_description,
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|