@arghajit/dummy 0.3.10 → 0.3.12
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arghajit/dummy",
|
|
3
3
|
"author": "Arghajit Singha",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.12",
|
|
5
5
|
"description": "A Playwright reporter and dashboard for visualizing test results.",
|
|
6
6
|
"homepage": "https://playwright-pulse-report.netlify.app/",
|
|
7
7
|
"keywords": [
|
|
@@ -225,15 +225,15 @@ function generateMinifiedHTML(reportData) {
|
|
|
225
225
|
case "Minor":
|
|
226
226
|
return "#006064";
|
|
227
227
|
case "Low":
|
|
228
|
-
return "#E65100";
|
|
229
|
-
case "Medium":
|
|
230
228
|
return "#FFA07A";
|
|
229
|
+
case "Medium":
|
|
230
|
+
return "#577A11";
|
|
231
231
|
case "High":
|
|
232
232
|
return "#B71C1C";
|
|
233
233
|
case "Critical":
|
|
234
|
-
return "#
|
|
234
|
+
return "#64158A";
|
|
235
235
|
default:
|
|
236
|
-
return "#
|
|
236
|
+
return "#577A11";
|
|
237
237
|
}
|
|
238
238
|
};
|
|
239
239
|
// We use inline styles here to ensure they render correctly in emails
|
|
@@ -286,7 +286,7 @@ function generateMinifiedHTML(reportData) {
|
|
|
286
286
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
287
287
|
<link rel="icon" type="image/png" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
288
288
|
<link rel="apple-touch-icon" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
289
|
-
<title>
|
|
289
|
+
<title>Pulse Summary Report</title>
|
|
290
290
|
<style>
|
|
291
291
|
:root {
|
|
292
292
|
--primary-color: #2c3e50; /* Dark Blue/Grey */
|
|
@@ -527,7 +527,7 @@ function generateMinifiedHTML(reportData) {
|
|
|
527
527
|
<header class="report-header">
|
|
528
528
|
<div class="report-header-title">
|
|
529
529
|
<img id="report-logo" src="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png" alt="Report Logo">
|
|
530
|
-
<h1>
|
|
530
|
+
<h1>Pulse Summary Report</h1>
|
|
531
531
|
</div>
|
|
532
532
|
<div class="run-info">
|
|
533
533
|
<strong>Run Date:</strong> ${formatDate(
|
|
@@ -569,10 +569,10 @@ function generateMinifiedHTML(reportData) {
|
|
|
569
569
|
<span style="margin-left: 4px; font-weight: 600; color: var(--text-color);">Severity:</span>
|
|
570
570
|
|
|
571
571
|
<span style="background-color: #006064; color: #fff; padding: 2px 6px; border-radius: 3px;">Minor</span>
|
|
572
|
-
<span style="background-color: #
|
|
573
|
-
<span style="background-color: #
|
|
572
|
+
<span style="background-color: #FFA07A; color: #fff; padding: 2px 6px; border-radius: 3px;">Low</span>
|
|
573
|
+
<span style="background-color: #577A11; color: #fff; padding: 2px 6px; border-radius: 3px;">Medium</span>
|
|
574
574
|
<span style="background-color: #B71C1C; color: #fff; padding: 2px 6px; border-radius: 3px;">High</span>
|
|
575
|
-
<span style="background-color: #
|
|
575
|
+
<span style="background-color: #64158A; color: #fff; padding: 2px 6px; border-radius: 3px;">Critical</span>
|
|
576
576
|
|
|
577
577
|
<span style="border-left: 1px solid #ccc; height: 14px; margin: 0 4px;"></span>
|
|
578
578
|
|
|
@@ -702,6 +702,9 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
702
702
|
const cardHeight = Math.floor(dashboardHeight * 0.44);
|
|
703
703
|
const cardContentPadding = 16; // px
|
|
704
704
|
|
|
705
|
+
// Logic for Run Context
|
|
706
|
+
const runContext = process.env.CI ? "CI" : "Local Test";
|
|
707
|
+
|
|
705
708
|
return `
|
|
706
709
|
<div class="environment-dashboard-wrapper" id="${dashboardId}">
|
|
707
710
|
<style>
|
|
@@ -744,6 +747,20 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
744
747
|
gap: 20px;
|
|
745
748
|
font-size: 14px;
|
|
746
749
|
}
|
|
750
|
+
|
|
751
|
+
/* Mobile Responsiveness */
|
|
752
|
+
@media (max-width: 768px) {
|
|
753
|
+
.environment-dashboard-wrapper {
|
|
754
|
+
grid-template-columns: 1fr; /* Stack columns on mobile */
|
|
755
|
+
grid-template-rows: auto;
|
|
756
|
+
padding: 16px;
|
|
757
|
+
height: auto !important; /* Allow height to grow */
|
|
758
|
+
}
|
|
759
|
+
.env-card {
|
|
760
|
+
height: auto !important; /* Allow cards to grow based on content */
|
|
761
|
+
min-height: 200px;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
747
764
|
|
|
748
765
|
.env-dashboard-header {
|
|
749
766
|
grid-column: 1 / -1;
|
|
@@ -753,6 +770,8 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
753
770
|
border-bottom: 1px solid var(--border-color);
|
|
754
771
|
padding-bottom: 16px;
|
|
755
772
|
margin-bottom: 8px;
|
|
773
|
+
flex-wrap: wrap; /* Allow wrapping header items */
|
|
774
|
+
gap: 10px;
|
|
756
775
|
}
|
|
757
776
|
|
|
758
777
|
.env-dashboard-title {
|
|
@@ -810,6 +829,8 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
810
829
|
padding: 10px 0;
|
|
811
830
|
border-bottom: 1px solid var(--border-light-color);
|
|
812
831
|
font-size: 0.875rem;
|
|
832
|
+
flex-wrap: wrap; /* Allow details to wrap on very small screens */
|
|
833
|
+
gap: 8px;
|
|
813
834
|
}
|
|
814
835
|
|
|
815
836
|
.env-detail-row:last-child {
|
|
@@ -827,6 +848,7 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
827
848
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
828
849
|
text-align: right;
|
|
829
850
|
word-break: break-all;
|
|
851
|
+
margin-left: auto; /* Push to right */
|
|
830
852
|
}
|
|
831
853
|
|
|
832
854
|
.env-chip {
|
|
@@ -1012,7 +1034,7 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
1012
1034
|
</div>
|
|
1013
1035
|
<div class="env-detail-row">
|
|
1014
1036
|
<span class="env-detail-label">Run Context</span>
|
|
1015
|
-
<span class="env-detail-value"
|
|
1037
|
+
<span class="env-detail-value">${runContext}</span>
|
|
1016
1038
|
</div>
|
|
1017
1039
|
</div>
|
|
1018
1040
|
</div>
|
|
@@ -1466,11 +1488,14 @@ function getSuitesData(results) {
|
|
|
1466
1488
|
}
|
|
1467
1489
|
function generateSuitesWidget(suitesData) {
|
|
1468
1490
|
if (!suitesData || suitesData.length === 0) {
|
|
1469
|
-
|
|
1491
|
+
// Maintain height consistency even if empty
|
|
1492
|
+
return `<div class="suites-widget" style="height: 450px;"><div class="suites-header"><h2>Test Suites</h2></div><div class="no-data">No suite data available.</div></div>`;
|
|
1470
1493
|
}
|
|
1494
|
+
|
|
1495
|
+
// Added inline styles for height consistency with Pie Chart (approx 450px) and scrolling
|
|
1471
1496
|
return `
|
|
1472
|
-
<div class="suites-widget">
|
|
1473
|
-
<div class="suites-header">
|
|
1497
|
+
<div class="suites-widget" style="height: 450px; display: flex; flex-direction: column;">
|
|
1498
|
+
<div class="suites-header" style="flex-shrink: 0;">
|
|
1474
1499
|
<h2>Test Suites</h2>
|
|
1475
1500
|
<span class="summary-badge">${
|
|
1476
1501
|
suitesData.length
|
|
@@ -1479,44 +1504,49 @@ function generateSuitesWidget(suitesData) {
|
|
|
1479
1504
|
0
|
|
1480
1505
|
)} tests</span>
|
|
1481
1506
|
</div>
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
<
|
|
1489
|
-
suite
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
${
|
|
1501
|
-
suite.
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1507
|
+
|
|
1508
|
+
<div class="suites-grid-container" style="flex-grow: 1; overflow-y: auto; padding-right: 5px;">
|
|
1509
|
+
<div class="suites-grid">
|
|
1510
|
+
${suitesData
|
|
1511
|
+
.map(
|
|
1512
|
+
(suite) => `
|
|
1513
|
+
<div class="suite-card status-${suite.statusOverall}">
|
|
1514
|
+
<div class="suite-card-header">
|
|
1515
|
+
<h3 class="suite-name" title="${sanitizeHTML(
|
|
1516
|
+
suite.name
|
|
1517
|
+
)} (${sanitizeHTML(suite.browser)})">${sanitizeHTML(
|
|
1518
|
+
suite.name
|
|
1519
|
+
)}</h3>
|
|
1520
|
+
</div>
|
|
1521
|
+
<div>🖥️ <span class="browser-tag">${sanitizeHTML(
|
|
1522
|
+
suite.browser
|
|
1523
|
+
)}</span></div>
|
|
1524
|
+
<div class="suite-card-body">
|
|
1525
|
+
<span class="test-count">${suite.count} test${
|
|
1526
|
+
suite.count !== 1 ? "s" : ""
|
|
1527
|
+
}</span>
|
|
1528
|
+
<div class="suite-stats">
|
|
1529
|
+
${
|
|
1530
|
+
suite.passed > 0
|
|
1531
|
+
? `<span class="stat-passed" title="Passed"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/></svg> ${suite.passed}</span>`
|
|
1532
|
+
: ""
|
|
1533
|
+
}
|
|
1534
|
+
${
|
|
1535
|
+
suite.failed > 0
|
|
1536
|
+
? `<span class="stat-failed" title="Failed"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-x-circle-fill" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/></svg> ${suite.failed}</span>`
|
|
1537
|
+
: ""
|
|
1538
|
+
}
|
|
1539
|
+
${
|
|
1540
|
+
suite.skipped > 0
|
|
1541
|
+
? `<span class="stat-skipped" title="Skipped"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-exclamation-triangle-fill" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg> ${suite.skipped}</span>`
|
|
1542
|
+
: ""
|
|
1543
|
+
}
|
|
1544
|
+
</div>
|
|
1545
|
+
</div>
|
|
1546
|
+
</div>`
|
|
1547
|
+
)
|
|
1548
|
+
.join("")}
|
|
1516
1549
|
</div>
|
|
1517
|
-
</div>`
|
|
1518
|
-
)
|
|
1519
|
-
.join("")}
|
|
1520
1550
|
</div>
|
|
1521
1551
|
</div>`;
|
|
1522
1552
|
}
|
|
@@ -1875,6 +1905,140 @@ function generateDescribeDurationChart(results) {
|
|
|
1875
1905
|
</script>
|
|
1876
1906
|
`;
|
|
1877
1907
|
}
|
|
1908
|
+
/**
|
|
1909
|
+
* Generates a stacked column chart showing test results distributed by severity.
|
|
1910
|
+
* Matches dimensions of the System Environment section (~600px).
|
|
1911
|
+
* Lazy-loaded for performance.
|
|
1912
|
+
*/
|
|
1913
|
+
function generateSeverityDistributionChart(results) {
|
|
1914
|
+
if (!results || results.length === 0) {
|
|
1915
|
+
return '<div class="trend-chart" style="height: 600px;"><div class="no-data">No results available for severity distribution.</div></div>';
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
const severityLevels = ["Critical", "High", "Medium", "Low", "Minor"];
|
|
1919
|
+
const data = {
|
|
1920
|
+
passed: [0, 0, 0, 0, 0],
|
|
1921
|
+
failed: [0, 0, 0, 0, 0],
|
|
1922
|
+
skipped: [0, 0, 0, 0, 0],
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1925
|
+
results.forEach((test) => {
|
|
1926
|
+
const sev = test.severity || "Medium";
|
|
1927
|
+
const status = String(test.status).toLowerCase();
|
|
1928
|
+
|
|
1929
|
+
let index = severityLevels.indexOf(sev);
|
|
1930
|
+
if (index === -1) index = 2; // Default to Medium
|
|
1931
|
+
|
|
1932
|
+
if (status === "passed") {
|
|
1933
|
+
data.passed[index]++;
|
|
1934
|
+
} else if (
|
|
1935
|
+
status === "failed" ||
|
|
1936
|
+
status === "timedout" ||
|
|
1937
|
+
status === "interrupted"
|
|
1938
|
+
) {
|
|
1939
|
+
data.failed[index]++;
|
|
1940
|
+
} else {
|
|
1941
|
+
data.skipped[index]++;
|
|
1942
|
+
}
|
|
1943
|
+
});
|
|
1944
|
+
|
|
1945
|
+
const chartId = `sevDistChart-${Date.now()}-${Math.random()
|
|
1946
|
+
.toString(36)
|
|
1947
|
+
.substring(2, 7)}`;
|
|
1948
|
+
const renderFunctionName = `renderSevDistChart_${chartId.replace(/-/g, "_")}`;
|
|
1949
|
+
|
|
1950
|
+
const seriesData = [
|
|
1951
|
+
{ name: "Passed", data: data.passed, color: "var(--success-color)" },
|
|
1952
|
+
{ name: "Failed", data: data.failed, color: "var(--danger-color)" },
|
|
1953
|
+
{ name: "Skipped", data: data.skipped, color: "var(--warning-color)" },
|
|
1954
|
+
];
|
|
1955
|
+
|
|
1956
|
+
const seriesDataStr = JSON.stringify(seriesData);
|
|
1957
|
+
const categoriesStr = JSON.stringify(severityLevels);
|
|
1958
|
+
|
|
1959
|
+
return `
|
|
1960
|
+
<div class="trend-chart" style="height: 600px; padding: 28px; box-sizing: border-box;">
|
|
1961
|
+
<h3 class="chart-title-header">Severity Distribution</h3>
|
|
1962
|
+
<div id="${chartId}" class="lazy-load-chart" data-render-function-name="${renderFunctionName}" style="width: 100%; height: 100%;">
|
|
1963
|
+
<div class="no-data">Loading Severity Chart...</div>
|
|
1964
|
+
</div>
|
|
1965
|
+
<script>
|
|
1966
|
+
window.${renderFunctionName} = function() {
|
|
1967
|
+
const chartContainer = document.getElementById('${chartId}');
|
|
1968
|
+
if (!chartContainer) return;
|
|
1969
|
+
|
|
1970
|
+
if (typeof Highcharts !== 'undefined') {
|
|
1971
|
+
try {
|
|
1972
|
+
chartContainer.innerHTML = '';
|
|
1973
|
+
Highcharts.chart('${chartId}', {
|
|
1974
|
+
chart: { type: 'column', backgroundColor: 'transparent' },
|
|
1975
|
+
title: { text: null },
|
|
1976
|
+
xAxis: {
|
|
1977
|
+
categories: ${categoriesStr},
|
|
1978
|
+
crosshair: true,
|
|
1979
|
+
labels: { style: { color: 'var(--text-color-secondary)' } }
|
|
1980
|
+
},
|
|
1981
|
+
yAxis: {
|
|
1982
|
+
min: 0,
|
|
1983
|
+
title: { text: 'Test Count', style: { color: 'var(--text-color)' } },
|
|
1984
|
+
stackLabels: { enabled: true, style: { fontWeight: 'bold', color: 'var(--text-color)' } },
|
|
1985
|
+
labels: { style: { color: 'var(--text-color-secondary)' } }
|
|
1986
|
+
},
|
|
1987
|
+
legend: {
|
|
1988
|
+
itemStyle: { color: 'var(--text-color)' }
|
|
1989
|
+
},
|
|
1990
|
+
tooltip: {
|
|
1991
|
+
shared: true,
|
|
1992
|
+
useHTML: true,
|
|
1993
|
+
backgroundColor: 'rgba(10,10,10,0.92)',
|
|
1994
|
+
style: { color: '#f5f5f5' },
|
|
1995
|
+
formatter: function() {
|
|
1996
|
+
// Custom formatter to HIDE 0 values
|
|
1997
|
+
let tooltip = '';
|
|
1998
|
+
let hasItems = false;
|
|
1999
|
+
|
|
2000
|
+
this.points.forEach(point => {
|
|
2001
|
+
if (point.y > 0) { // ONLY show if count > 0
|
|
2002
|
+
tooltip += '<span style="color:' + point.series.color + '">●</span> ' +
|
|
2003
|
+
point.series.name + ': <b>' + point.y + '</b><br/>';
|
|
2004
|
+
hasItems = true;
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
|
|
2008
|
+
if (!hasItems) return false; // Hide tooltip entirely if no data
|
|
2009
|
+
|
|
2010
|
+
// Calculate total from visible points to ensure accuracy or use stackTotal
|
|
2011
|
+
tooltip += 'Total: ' + this.points[0].total;
|
|
2012
|
+
return tooltip;
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
plotOptions: {
|
|
2016
|
+
column: {
|
|
2017
|
+
stacking: 'normal',
|
|
2018
|
+
dataLabels: {
|
|
2019
|
+
enabled: true,
|
|
2020
|
+
color: '#fff',
|
|
2021
|
+
style: { textOutline: 'none' },
|
|
2022
|
+
formatter: function() {
|
|
2023
|
+
return (this.y > 0) ? this.y : null; // Hide 0 labels on chart bars
|
|
2024
|
+
}
|
|
2025
|
+
},
|
|
2026
|
+
borderRadius: 3
|
|
2027
|
+
}
|
|
2028
|
+
},
|
|
2029
|
+
series: ${seriesDataStr},
|
|
2030
|
+
credits: { enabled: false }
|
|
2031
|
+
});
|
|
2032
|
+
} catch(e) {
|
|
2033
|
+
console.error("Error rendering severity chart:", e);
|
|
2034
|
+
chartContainer.innerHTML = '<div class="no-data">Error rendering chart.</div>';
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
</script>
|
|
2039
|
+
</div>
|
|
2040
|
+
`;
|
|
2041
|
+
}
|
|
1878
2042
|
/**
|
|
1879
2043
|
* Generates the HTML content for the report.
|
|
1880
2044
|
* @param {object} reportData - The report data object containing run and results.
|
|
@@ -1923,15 +2087,17 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1923
2087
|
const getSeverityColor = (level) => {
|
|
1924
2088
|
switch (level) {
|
|
1925
2089
|
case "Minor":
|
|
1926
|
-
return "#006064";
|
|
2090
|
+
return "#006064";
|
|
1927
2091
|
case "Low":
|
|
1928
|
-
return "#
|
|
2092
|
+
return "#FFA07A";
|
|
2093
|
+
case "Medium":
|
|
2094
|
+
return "#577A11";
|
|
1929
2095
|
case "High":
|
|
1930
|
-
return "#B71C1C";
|
|
2096
|
+
return "#B71C1C";
|
|
1931
2097
|
case "Critical":
|
|
1932
|
-
return "#
|
|
2098
|
+
return "#64158A";
|
|
1933
2099
|
default:
|
|
1934
|
-
return "#
|
|
2100
|
+
return "#577A11";
|
|
1935
2101
|
}
|
|
1936
2102
|
};
|
|
1937
2103
|
const severityColor = getSeverityColor(severity);
|
|
@@ -2307,10 +2473,10 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2307
2473
|
<head>
|
|
2308
2474
|
<meta charset="UTF-8">
|
|
2309
2475
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2310
|
-
<link rel="icon" type="image/png" href="https://
|
|
2311
|
-
<link rel="apple-touch-icon" href="https://
|
|
2476
|
+
<link rel="icon" type="image/png" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
2477
|
+
<link rel="apple-touch-icon" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
2312
2478
|
<script src="https://code.highcharts.com/highcharts.js" defer></script>
|
|
2313
|
-
<title>
|
|
2479
|
+
<title>Pulse Report</title>
|
|
2314
2480
|
<style>
|
|
2315
2481
|
:root {
|
|
2316
2482
|
--primary-color: #3f51b5; --secondary-color: #ff4081; --accent-color: #673ab7; --accent-color-alt: #FF9800;
|
|
@@ -2351,7 +2517,7 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2351
2517
|
.status-passed .value, .stat-passed svg { color: var(--success-color); }
|
|
2352
2518
|
.status-failed .value, .stat-failed svg { color: var(--danger-color); }
|
|
2353
2519
|
.status-skipped .value, .stat-skipped svg { color: var(--warning-color); }
|
|
2354
|
-
.dashboard-bottom-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 28px; align-items:
|
|
2520
|
+
.dashboard-bottom-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 28px; align-items: start; }
|
|
2355
2521
|
.pie-chart-wrapper, .suites-widget, .trend-chart { background-color: var(--card-background-color); padding: 28px; border-radius: var(--border-radius); box-shadow: var(--box-shadow-light); display: flex; flex-direction: column; }
|
|
2356
2522
|
.pie-chart-wrapper h3, .suites-header h2, .trend-chart h3 { text-align: center; margin-top: 0; margin-bottom: 25px; font-size: 1.25em; font-weight: 600; color: var(--text-color); }
|
|
2357
2523
|
.trend-chart-container, .pie-chart-wrapper div[id^="pieChart-"] { flex-grow: 1; min-height: 250px; }
|
|
@@ -2738,8 +2904,8 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2738
2904
|
<div class="container">
|
|
2739
2905
|
<header class="header">
|
|
2740
2906
|
<div class="header-title">
|
|
2741
|
-
<img id="report-logo" src="https://
|
|
2742
|
-
<h1>
|
|
2907
|
+
<img id="report-logo" src="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png" alt="Report Logo">
|
|
2908
|
+
<h1>Pulse Report</h1>
|
|
2743
2909
|
</div>
|
|
2744
2910
|
<div class="run-info"><strong>Run Date:</strong> ${formatDate(
|
|
2745
2911
|
runSummary.timestamp
|
|
@@ -2773,7 +2939,7 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2773
2939
|
)}</div></div>
|
|
2774
2940
|
</div>
|
|
2775
2941
|
<div class="dashboard-bottom-row">
|
|
2776
|
-
<div style="display:
|
|
2942
|
+
<div style="display: flex; flex-direction: column; gap: 28px;">
|
|
2777
2943
|
${generatePieChart(
|
|
2778
2944
|
[
|
|
2779
2945
|
{ label: "Passed", value: runSummary.passed },
|
|
@@ -2790,9 +2956,13 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2790
2956
|
: '<div class="no-data">Environment data not available.</div>'
|
|
2791
2957
|
}
|
|
2792
2958
|
</div>
|
|
2959
|
+
|
|
2960
|
+
<div style="display: flex; flex-direction: column; gap: 28px;">
|
|
2793
2961
|
${generateSuitesWidget(suitesData)}
|
|
2962
|
+
${generateSeverityDistributionChart(results)}
|
|
2963
|
+
</div>
|
|
2794
2964
|
</div>
|
|
2795
|
-
|
|
2965
|
+
</div>
|
|
2796
2966
|
<div id="test-runs" class="tab-content">
|
|
2797
2967
|
<div class="filters">
|
|
2798
2968
|
<input type="text" id="filter-name" placeholder="Filter by test name/path..." style="border-color: black; border-style: outset;">
|
|
@@ -776,6 +776,9 @@ function generateEnvironmentDashboard(environment, dashboardHeight = 600) {
|
|
|
776
776
|
const cardHeight = Math.floor(dashboardHeight * 0.44);
|
|
777
777
|
const cardContentPadding = 16; // px
|
|
778
778
|
|
|
779
|
+
// Logic for Run Context
|
|
780
|
+
const runContext = process.env.CI ? "CI" : "Local Test";
|
|
781
|
+
|
|
779
782
|
return `
|
|
780
783
|
<div class="environment-dashboard-wrapper" id="${dashboardId}">
|
|
781
784
|
<style>
|
|
@@ -819,6 +822,20 @@ gap: 20px;
|
|
|
819
822
|
font-size: 14px;
|
|
820
823
|
}
|
|
821
824
|
|
|
825
|
+
/* Mobile Responsiveness */
|
|
826
|
+
@media (max-width: 768px) {
|
|
827
|
+
.environment-dashboard-wrapper {
|
|
828
|
+
grid-template-columns: 1fr; /* Stack columns on mobile */
|
|
829
|
+
grid-template-rows: auto;
|
|
830
|
+
padding: 16px;
|
|
831
|
+
height: auto !important; /* Allow height to grow */
|
|
832
|
+
}
|
|
833
|
+
.env-card {
|
|
834
|
+
height: auto !important; /* Allow cards to grow based on content */
|
|
835
|
+
min-height: 200px;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
822
839
|
.env-dashboard-header {
|
|
823
840
|
grid-column: 1 / -1;
|
|
824
841
|
display: flex;
|
|
@@ -827,6 +844,8 @@ align-items: center;
|
|
|
827
844
|
border-bottom: 1px solid var(--border-color);
|
|
828
845
|
padding-bottom: 16px;
|
|
829
846
|
margin-bottom: 8px;
|
|
847
|
+
flex-wrap: wrap; /* Allow wrapping header items */
|
|
848
|
+
gap: 10px;
|
|
830
849
|
}
|
|
831
850
|
|
|
832
851
|
.env-dashboard-title {
|
|
@@ -1086,7 +1105,7 @@ border-color: var(--border-color);
|
|
|
1086
1105
|
</div>
|
|
1087
1106
|
<div class="env-detail-row">
|
|
1088
1107
|
<span class="env-detail-label">Run Context</span>
|
|
1089
|
-
<span class="env-detail-value"
|
|
1108
|
+
<span class="env-detail-value">${runContext}</span>
|
|
1090
1109
|
</div>
|
|
1091
1110
|
</div>
|
|
1092
1111
|
</div>
|
|
@@ -2012,6 +2031,140 @@ function generateDescribeDurationChart(results) {
|
|
|
2012
2031
|
</script>
|
|
2013
2032
|
`;
|
|
2014
2033
|
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Generates a stacked column chart showing test results distributed by severity.
|
|
2036
|
+
* Matches dimensions of the System Environment section (~600px).
|
|
2037
|
+
* Lazy-loaded for performance.
|
|
2038
|
+
*/
|
|
2039
|
+
function generateSeverityDistributionChart(results) {
|
|
2040
|
+
if (!results || results.length === 0) {
|
|
2041
|
+
return '<div class="trend-chart" style="height: 600px;"><div class="no-data">No results available for severity distribution.</div></div>';
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
const severityLevels = ["Critical", "High", "Medium", "Low", "Minor"];
|
|
2045
|
+
const data = {
|
|
2046
|
+
passed: [0, 0, 0, 0, 0],
|
|
2047
|
+
failed: [0, 0, 0, 0, 0],
|
|
2048
|
+
skipped: [0, 0, 0, 0, 0],
|
|
2049
|
+
};
|
|
2050
|
+
|
|
2051
|
+
results.forEach((test) => {
|
|
2052
|
+
const sev = test.severity || "Medium";
|
|
2053
|
+
const status = String(test.status).toLowerCase();
|
|
2054
|
+
|
|
2055
|
+
let index = severityLevels.indexOf(sev);
|
|
2056
|
+
if (index === -1) index = 2; // Default to Medium
|
|
2057
|
+
|
|
2058
|
+
if (status === "passed") {
|
|
2059
|
+
data.passed[index]++;
|
|
2060
|
+
} else if (
|
|
2061
|
+
status === "failed" ||
|
|
2062
|
+
status === "timedout" ||
|
|
2063
|
+
status === "interrupted"
|
|
2064
|
+
) {
|
|
2065
|
+
data.failed[index]++;
|
|
2066
|
+
} else {
|
|
2067
|
+
data.skipped[index]++;
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
|
|
2071
|
+
const chartId = `sevDistChart-${Date.now()}-${Math.random()
|
|
2072
|
+
.toString(36)
|
|
2073
|
+
.substring(2, 7)}`;
|
|
2074
|
+
const renderFunctionName = `renderSevDistChart_${chartId.replace(/-/g, "_")}`;
|
|
2075
|
+
|
|
2076
|
+
const seriesData = [
|
|
2077
|
+
{ name: "Passed", data: data.passed, color: "var(--success-color)" },
|
|
2078
|
+
{ name: "Failed", data: data.failed, color: "var(--danger-color)" },
|
|
2079
|
+
{ name: "Skipped", data: data.skipped, color: "var(--warning-color)" },
|
|
2080
|
+
];
|
|
2081
|
+
|
|
2082
|
+
const seriesDataStr = JSON.stringify(seriesData);
|
|
2083
|
+
const categoriesStr = JSON.stringify(severityLevels);
|
|
2084
|
+
|
|
2085
|
+
return `
|
|
2086
|
+
<div class="trend-chart" style="height: 600px; padding: 28px; box-sizing: border-box;">
|
|
2087
|
+
<h3 class="chart-title-header">Severity Distribution</h3>
|
|
2088
|
+
<div id="${chartId}" class="lazy-load-chart" data-render-function-name="${renderFunctionName}" style="width: 100%; height: 100%;">
|
|
2089
|
+
<div class="no-data">Loading Severity Chart...</div>
|
|
2090
|
+
</div>
|
|
2091
|
+
<script>
|
|
2092
|
+
window.${renderFunctionName} = function() {
|
|
2093
|
+
const chartContainer = document.getElementById('${chartId}');
|
|
2094
|
+
if (!chartContainer) return;
|
|
2095
|
+
|
|
2096
|
+
if (typeof Highcharts !== 'undefined') {
|
|
2097
|
+
try {
|
|
2098
|
+
chartContainer.innerHTML = '';
|
|
2099
|
+
Highcharts.chart('${chartId}', {
|
|
2100
|
+
chart: { type: 'column', backgroundColor: 'transparent' },
|
|
2101
|
+
title: { text: null },
|
|
2102
|
+
xAxis: {
|
|
2103
|
+
categories: ${categoriesStr},
|
|
2104
|
+
crosshair: true,
|
|
2105
|
+
labels: { style: { color: 'var(--text-color-secondary)' } }
|
|
2106
|
+
},
|
|
2107
|
+
yAxis: {
|
|
2108
|
+
min: 0,
|
|
2109
|
+
title: { text: 'Test Count', style: { color: 'var(--text-color)' } },
|
|
2110
|
+
stackLabels: { enabled: true, style: { fontWeight: 'bold', color: 'var(--text-color)' } },
|
|
2111
|
+
labels: { style: { color: 'var(--text-color-secondary)' } }
|
|
2112
|
+
},
|
|
2113
|
+
legend: {
|
|
2114
|
+
itemStyle: { color: 'var(--text-color)' }
|
|
2115
|
+
},
|
|
2116
|
+
tooltip: {
|
|
2117
|
+
shared: true,
|
|
2118
|
+
useHTML: true,
|
|
2119
|
+
backgroundColor: 'rgba(10,10,10,0.92)',
|
|
2120
|
+
style: { color: '#f5f5f5' },
|
|
2121
|
+
formatter: function() {
|
|
2122
|
+
// Custom formatter to HIDE 0 values
|
|
2123
|
+
let tooltip = '';
|
|
2124
|
+
let hasItems = false;
|
|
2125
|
+
|
|
2126
|
+
this.points.forEach(point => {
|
|
2127
|
+
if (point.y > 0) { // ONLY show if count > 0
|
|
2128
|
+
tooltip += '<span style="color:' + point.series.color + '">●</span> ' +
|
|
2129
|
+
point.series.name + ': <b>' + point.y + '</b><br/>';
|
|
2130
|
+
hasItems = true;
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2134
|
+
if (!hasItems) return false; // Hide tooltip entirely if no data
|
|
2135
|
+
|
|
2136
|
+
// Calculate total from visible points to ensure accuracy or use stackTotal
|
|
2137
|
+
tooltip += 'Total: ' + this.points[0].total;
|
|
2138
|
+
return tooltip;
|
|
2139
|
+
}
|
|
2140
|
+
},
|
|
2141
|
+
plotOptions: {
|
|
2142
|
+
column: {
|
|
2143
|
+
stacking: 'normal',
|
|
2144
|
+
dataLabels: {
|
|
2145
|
+
enabled: true,
|
|
2146
|
+
color: '#fff',
|
|
2147
|
+
style: { textOutline: 'none' },
|
|
2148
|
+
formatter: function() {
|
|
2149
|
+
return (this.y > 0) ? this.y : null; // Hide 0 labels on chart bars
|
|
2150
|
+
}
|
|
2151
|
+
},
|
|
2152
|
+
borderRadius: 3
|
|
2153
|
+
}
|
|
2154
|
+
},
|
|
2155
|
+
series: ${seriesDataStr},
|
|
2156
|
+
credits: { enabled: false }
|
|
2157
|
+
});
|
|
2158
|
+
} catch(e) {
|
|
2159
|
+
console.error("Error rendering severity chart:", e);
|
|
2160
|
+
chartContainer.innerHTML = '<div class="no-data">Error rendering chart.</div>';
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
</script>
|
|
2165
|
+
</div>
|
|
2166
|
+
`;
|
|
2167
|
+
}
|
|
2015
2168
|
/**
|
|
2016
2169
|
* Generates the HTML report.
|
|
2017
2170
|
* @param {object} reportData - The data for the report.
|
|
@@ -2059,15 +2212,17 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2059
2212
|
const getSeverityColor = (level) => {
|
|
2060
2213
|
switch (level) {
|
|
2061
2214
|
case "Minor":
|
|
2062
|
-
return "#006064";
|
|
2215
|
+
return "#006064";
|
|
2063
2216
|
case "Low":
|
|
2064
|
-
return "#
|
|
2217
|
+
return "#FFA07A";
|
|
2218
|
+
case "Medium":
|
|
2219
|
+
return "#577A11";
|
|
2065
2220
|
case "High":
|
|
2066
|
-
return "#B71C1C";
|
|
2221
|
+
return "#B71C1C";
|
|
2067
2222
|
case "Critical":
|
|
2068
|
-
return "#
|
|
2223
|
+
return "#64158A";
|
|
2069
2224
|
default:
|
|
2070
|
-
return "#
|
|
2225
|
+
return "#577A11";
|
|
2071
2226
|
}
|
|
2072
2227
|
};
|
|
2073
2228
|
const severityColor = getSeverityColor(severity);
|
|
@@ -2476,10 +2631,10 @@ function generateHTML(reportData, trendData = null) {
|
|
|
2476
2631
|
<head>
|
|
2477
2632
|
<meta charset="UTF-8">
|
|
2478
2633
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2479
|
-
<link rel="icon" type="image/png" href="https://
|
|
2480
|
-
<link rel="apple-touch-icon" href="https://
|
|
2634
|
+
<link rel="icon" type="image/png" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
2635
|
+
<link rel="apple-touch-icon" href="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png">
|
|
2481
2636
|
<script src="https://code.highcharts.com/highcharts.js" defer></script>
|
|
2482
|
-
<title>
|
|
2637
|
+
<title>Pulse Static Report</title>
|
|
2483
2638
|
|
|
2484
2639
|
<style>
|
|
2485
2640
|
:root {
|
|
@@ -2521,7 +2676,7 @@ body { font-family: var(--font-family); margin: 0; background-color: var(--backg
|
|
|
2521
2676
|
.status-passed .value, .stat-passed svg { color: var(--success-color); }
|
|
2522
2677
|
.status-failed .value, .stat-failed svg { color: var(--danger-color); }
|
|
2523
2678
|
.status-skipped .value, .stat-skipped svg { color: var(--warning-color); }
|
|
2524
|
-
.dashboard-bottom-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 28px; align-items:
|
|
2679
|
+
.dashboard-bottom-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 28px; align-items: start; }
|
|
2525
2680
|
.pie-chart-wrapper, .suites-widget, .trend-chart { background-color: var(--card-background-color); padding: 28px; border-radius: var(--border-radius); box-shadow: var(--box-shadow-light); display: flex; flex-direction: column; }
|
|
2526
2681
|
.pie-chart-wrapper h3, .suites-header h2, .trend-chart h3 { text-align: center; margin-top: 0; margin-bottom: 25px; font-size: 1.25em; font-weight: 600; color: var(--text-color); }
|
|
2527
2682
|
.trend-chart-container, .pie-chart-wrapper div[id^="pieChart-"] { flex-grow: 1; min-height: 250px; }
|
|
@@ -2725,8 +2880,8 @@ aspect-ratio: 16 / 9;
|
|
|
2725
2880
|
<div class="container">
|
|
2726
2881
|
<header class="header">
|
|
2727
2882
|
<div class="header-title">
|
|
2728
|
-
<img id="report-logo" src="https://
|
|
2729
|
-
<h1>
|
|
2883
|
+
<img id="report-logo" src="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images/pulse-report/playwright_pulse_icon.png" alt="Report Logo">
|
|
2884
|
+
<h1>Pulse Static Report</h1>
|
|
2730
2885
|
</div>
|
|
2731
2886
|
<div class="run-info"><strong>Run Date:</strong> ${formatDate(
|
|
2732
2887
|
runSummary.timestamp
|
|
@@ -2777,7 +2932,10 @@ aspect-ratio: 16 / 9;
|
|
|
2777
2932
|
: '<div class="no-data">Environment data not available.</div>'
|
|
2778
2933
|
}
|
|
2779
2934
|
</div>
|
|
2780
|
-
|
|
2935
|
+
<div style="display: flex; flex-direction: column; gap: 28px;">
|
|
2936
|
+
${generateSuitesWidget(suitesData)}
|
|
2937
|
+
${generateSeverityDistributionChart(results)}
|
|
2938
|
+
</div>
|
|
2781
2939
|
</div>
|
|
2782
2940
|
</div>
|
|
2783
2941
|
<div id="test-runs" class="tab-content">
|
|
@@ -3658,4 +3816,4 @@ main().catch((err) => {
|
|
|
3658
3816
|
);
|
|
3659
3817
|
console.error(err.stack);
|
|
3660
3818
|
process.exit(1);
|
|
3661
|
-
});
|
|
3819
|
+
});
|