This is an automated email from the ASF dual-hosted git repository.

ashishvijaywargiya pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 9df715a663 Reskin Gradle's native unit test HTML report to match the 
integration report theme (#1604)
9df715a663 is described below

commit 9df715a6633297f3f81666b72cc4d1d309add469
Author: Ashish Vijaywargiya <[email protected]>
AuthorDate: Sat Aug 8 17:57:10 2026 +0530

    Reskin Gradle's native unit test HTML report to match the integration 
report theme (#1604)
    
    Reskin Gradle's native unit test HTML report to match the integration
    report theme
---
 build.gradle        |   1 +
 test-reports.gradle | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/build.gradle b/build.gradle
index 9142a731e5..34baa7f804 100644
--- a/build.gradle
+++ b/build.gradle
@@ -398,6 +398,7 @@ test {
     testLogging {
         events "passed", "skipped", "failed"
     }
+    finalizedBy(reskinGradleTestReport)
 }
 
 // 'gradlew test --tests <ClassName>' against a @JunitJupiterTest class fails 
with Gradle's generic
diff --git a/test-reports.gradle b/test-reports.gradle
index c8b874c2fa..e2b4bee108 100644
--- a/test-reports.gradle
+++ b/test-reports.gradle
@@ -739,3 +739,131 @@ task createFramedTestReport(group: sysadminGroup,
         println "Framed test report written to ${outDir}/index.html"
     }
 }
+
+def gradleReportReskinCss() {
+    // Layered on top of Gradle's own built-in test report 
(build/reports/tests/test/), which is
+    // baked into the Gradle distribution itself and has no supported theming 
hook - this targets
+    // that report's existing, stable class/id names (.infoBox, .tabLinks, 
td.success, etc.)
+    // rather than replacing the report wholesale, so the native per-class 
stdout/stderr tab,
+    // breadcrumbs and tab-switching JS all keep working untouched. 
Deliberately not shared with
+    // modernReportCss() above: that one styles markup this file itself 
renders, this one only
+    // overrides selectors Gradle renders, and the two happen to converge on 
the same palette.
+    '''
+:root {
+  --bs-primary: #0d6efd;
+  --bs-success: #198754;
+  --bs-danger: #dc3545;
+  --bs-secondary: #6c757d;
+  --bs-body-bg: #f8f9fa;
+  --bs-border-color: #dee2e6;
+}
+html, body { background: var(--bs-body-bg) !important; }
+body, body a, body a:visited {
+  font-family: -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, 
sans-serif !important;
+  color: #212529 !important;
+}
+#content > h1 {
+  /* Bleeds edge-to-edge by canceling out #content's native 30px/50px padding 
(left
+     untouched here) with an equal negative margin, then reapplying its own 
padding so the
+     title text still lines up with the rest of the page's left/right margin. 
*/
+  margin: -30px -50px 1.5rem !important;
+  padding: 0.9rem 50px !important;
+  background: var(--bs-primary);
+  color: #fff !important;
+  font-size: 1.4rem;
+  font-weight: 600;
+}
+.breadcrumbs, .breadcrumbs a { color: var(--bs-secondary) !important; 
font-size: 0.85rem; }
+.breadcrumbs { margin: -1rem 0 1.5rem !important; }
+
+.summaryGroup, #successRate.infoBox {
+  border: 1px solid var(--bs-border-color) !important;
+  border-radius: 0.5rem !important;
+  background: #fff;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
+}
+.infoBox { padding: 1rem !important; }
+.counter, .percent { font-size: 1.6rem !important; font-weight: 700 
!important; color: #212529; }
+.infoBox p { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 
0.03em; color: var(--bs-secondary); margin-top: 0.35rem !important; }
+#failures .counter { color: var(--bs-danger); }
+#tests .counter { color: var(--bs-primary); }
+#ignored .counter { color: var(--bs-secondary); }
+div.success, #successRate.success { background: #fff !important; border-color: 
var(--bs-success) !important; }
+div.success .percent, #successRate.success .percent { color: var(--bs-success) 
!important; }
+div.failures, #successRate.failures { background: #fff !important; 
border-color: var(--bs-danger) !important; }
+div.failures .percent, #successRate.failures .percent { color: 
var(--bs-danger) !important; }
+
+ul.tabLinks { border-bottom: 1px solid var(--bs-border-color) !important; 
min-width: 0 !important; }
+ul.tabLinks li {
+  background: transparent !important;
+  border: none !important;
+  border-radius: 0 !important;
+  padding: 0.6rem 0.2rem !important;
+  margin-right: 1.5rem !important;
+}
+ul.tabLinks li a { font-size: 0.95rem !important; color: var(--bs-secondary); 
font-weight: 500; }
+ul.tabLinks li.selected { background: transparent !important; border-bottom: 
2px solid var(--bs-primary) !important; }
+ul.tabLinks li.selected a { color: var(--bs-primary) !important; }
+
+div.tab table {
+  width: 100% !important;
+  min-width: 0 !important;
+  background: #fff;
+  border: 1px solid var(--bs-border-color);
+  border-radius: 0.5rem;
+  border-collapse: separate !important;
+  border-spacing: 0;
+}
+div.tab th {
+  background: #f1f3f5 !important;
+  text-transform: uppercase;
+  font-size: 0.72rem;
+  letter-spacing: 0.03em;
+  color: var(--bs-secondary);
+  padding: 0.6rem 0.9rem !important;
+  white-space: nowrap;
+}
+div.tab td { padding: 0.55rem 0.9rem !important; white-space: normal 
!important; border-top: 1px solid var(--bs-border-color) !important; }
+div.tab tr:nth-child(even) td { background: rgba(0, 0, 0, 0.015); }
+div.tab tr:hover td { background: rgba(13, 110, 253, 0.06); }
+td.success { color: var(--bs-success) !important; }
+td.failures { color: var(--bs-danger) !important; }
+
+span.code pre {
+  background: #f8f9fa !important;
+  border: 1px solid var(--bs-border-color) !important;
+  border-radius: 0.5rem !important;
+  padding: 1rem !important;
+  font-size: 0.82rem !important;
+  color: #333;
+}
+
+#footer, #footer a { color: var(--bs-secondary) !important; }
+#footer { border-top: 1px solid var(--bs-border-color); padding-top: 1rem; }
+'''
+}
+
+task reskinGradleTestReport(group: sysadminGroup,
+        description: "Layer a Bootstrap-style stylesheet onto Gradle's native 
build/reports/tests/test HTML report") {
+    doLast {
+        def outDir = file('./build/reports/tests/test')
+        if (!outDir.exists()) {
+            return
+        }
+        def cssFile = file("${outDir}/junit-report-reskin.css")
+        cssFile.text = gradleReportReskinCss()
+        def linkTag = { String href -> "<link rel=\"stylesheet\" 
href=\"${href}\">\n</head>" }
+        fileTree(outDir) { include '**/*.html' }.each { htmlFile ->
+            def content = htmlFile.text
+            // Idempotency guard: 'test' being UP-TO-DATE still runs this 
finalizedBy task (it
+            // carries no declared inputs/outputs of its own), which would 
otherwise re-inject the
+            // <link> into HTML Gradle didn't regenerate and left 
already-reskinned from last time.
+            if (!content.contains('junit-report-reskin.css') && 
content.contains('</head>')) {
+                def depth = 
outDir.toPath().relativize(htmlFile.toPath()).nameCount - 1
+                def href = ('../' * depth) + 'junit-report-reskin.css'
+                htmlFile.text = content.replace('</head>', linkTag(href))
+            }
+        }
+        println "Reskinned Gradle test report at ${outDir}/index.html"
+    }
+}

Reply via email to