@@ -38202,7 +38202,7 @@ async function run() {
3820238202 pollingInterval
3820338203 );
3820438204
38205- await ReportProcessor.processReport(reportData);
38205+ await ReportProcessor.processReport(reportData, buildName );
3820638206 } catch (error) {
3820738207 core.setFailed(`Action failed: ${error.message}`);
3820838208 }
@@ -38291,7 +38291,6 @@ class MockReportService {
3829138291 build_uuid: 'mock-build-123',
3829238292 report: {
3829338293 basic_html: `
38294- <html>
3829538294<body>
3829638295
3829738296 <h2>Build Insights</h2>
@@ -38402,8 +38401,257 @@ class MockReportService {
3840238401 </table>
3840338402
3840438403</body>
38405- </html>
38406- `
38404+ `,
38405+ rich_html: `<body>
38406+
38407+ <h2>Build Insights</h2>
38408+
38409+ <div class="grid-container">
38410+ <div class="metric-card">
38411+ <h1>5</h1>
38412+ <p>All</p>
38413+ </div>
38414+ <div class="metric-card passed">
38415+ <h1>2</h1>
38416+ <p>Passed</p>
38417+ </div>
38418+ <div class="metric-card failed">
38419+ <h1>2</h1>
38420+ <p>Failed</p>
38421+ </div>
38422+ <div class="metric-card skipped">
38423+ <h1>1</h1>
38424+ <p>Skipped</p>
38425+ </div>
38426+ <div class="metric-card unknown">
38427+ <h1>0</h1>
38428+ <p>Unknown</p>
38429+ </div>
38430+ </div>
38431+
38432+ <div class="grid-metrics">
38433+ <div class="metric-box">
38434+ <h2>New Failures</h2>
38435+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38436+ </div>
38437+ <div class="metric-box">
38438+ <h2>Always Failing</h2>
38439+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38440+ </div>
38441+ <div class="metric-box">
38442+ <h2>Flaky Test</h2>
38443+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38444+ </div>
38445+ <div class="metric-box">
38446+ <h2>Muted Tests</h2>
38447+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38448+ </div>
38449+ <div class="metric-box">
38450+ <h2>Unique Errors</h2>
38451+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38452+ </div>
38453+ <div class="metric-box">
38454+ <h2>Performance Anomaly</h2>
38455+ <h4><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=insights>" target="_blank">View</a></h4>
38456+ </div>
38457+ </div>
38458+
38459+ <div class="w3-panel w3-light-grey w3-border w3-round">
38460+ <p>Note: Click view or add report timeout in plugin settings to see build insights above.</p>
38461+ </div>
38462+ <br>
38463+
38464+ <h2>Test List</h2>
38465+
38466+ <table>
38467+ <thead>
38468+ <tr>
38469+ <th>Test Name</th>
38470+ <th>Status</th>
38471+ <th>Test History</th>
38472+ <th>Browser/Device</th>
38473+ <th>OS</th>
38474+ <th>Duration</th>
38475+ </tr>
38476+ </thead>
38477+ <tbody>
38478+ <tr>
38479+ <td class="test-link"><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=tests&details=1327748286>" target="_blank">Refresh API User token - Step not defined</a></td>
38480+ <td class="status-skipped">Skipped</td>
38481+ <td class="test-history"><a href="<https://observability.browserstack.com/projects/WDIO+Cucumber+GH/builds/Sanity+Only+Chrome/4052?tab=tests&details=1327748286&utm_medium=cicd&utm_source=jenkins>" target="_blank">View History</a></td>
38482+ <td>Chrome 135</td>
38483+ <td>OS X</td>
38484+ <td>92s</td>
38485+ </tr>
38486+ <tr>
38487+ <td class="test-link"><a href="#">Delete Account via API - Step Pending</a></td>
38488+ <td class="status-failed">Failed</td>
38489+ <td class="test-history"><a href="#">View History</a></td>
38490+ <td>Google Pixel 7</td>
38491+ <td>Android 12</td>
38492+ <td>180s</td>
38493+ </tr>
38494+ <tr>
38495+ <td class="test-link"><a href="#">BStack Demo API</a></td>
38496+ <td class="status-passed">Passed</td>
38497+ <td class="test-history"><a href="#">View History</a></td>
38498+ <td>Samsung Galaxy Tab S8</td>
38499+ <td>Android 12</td>
38500+ <td>134s</td>
38501+ </tr>
38502+ <tr>
38503+ <td class="test-link"><a href="#">Verify API Create Account (fred, password789)</a></td>
38504+ <td class="status-failed">Failed</td>
38505+ <td class="test-history"><a href="#">View History</a></td>
38506+ <td>iPhone 14 Pro</td>
38507+ <td>iOS 15.5</td>
38508+ <td>221s</td>
38509+ </tr>
38510+ <tr>
38511+ <td class="test-link"><a href="#">Verify API User Address</a></td>
38512+ <td class="status-passed">Passed</td>
38513+ <td class="test-history"><a href="#">View History</a></td>
38514+ <td>Chrome 135</td>
38515+ <td>Windows 11</td>
38516+ <td>102s</td>
38517+ </tr>
38518+ </tbody>
38519+ </table>
38520+
38521+ </body>`,
38522+ rich_css: `body {
38523+ font-family: 'Arial', sans-serif;
38524+ background-color: #f8f9fb;
38525+ padding: 20px;
38526+ }
38527+
38528+ h2 {
38529+ margin-top: 5px;
38530+ margin-bottom: 15px;
38531+ color: #2b3e50;
38532+ }
38533+
38534+ .grid-container {
38535+ display: grid;
38536+ grid-template-columns: repeat(5, 1fr);
38537+ gap: 10px;
38538+ margin-bottom: 30px;
38539+ max-width: 1000px;
38540+ }
38541+
38542+ .metric-card {
38543+ background-color: white;
38544+ border-radius: 8px;
38545+ padding: 20px;
38546+ text-align: center;
38547+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.05);
38548+ }
38549+
38550+ .metric-card h1 {
38551+ margin: 0;
38552+ font-size: 32px;
38553+ }
38554+
38555+ .passed {
38556+ color: green;
38557+ }
38558+
38559+ .failed {
38560+ color: red;
38561+ }
38562+
38563+ .skipped,
38564+ .unknown {
38565+ color: #6c757d;
38566+ }
38567+
38568+ .grid-metrics {
38569+ display: grid;
38570+ grid-template-columns: repeat(3, 1fr);
38571+ gap: 10px;
38572+ max-width: 1000px;
38573+ }
38574+
38575+ .metric-box {
38576+ background-color: white;
38577+ border-radius: 8px;
38578+ padding: 20px;
38579+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.05);
38580+ }
38581+
38582+ .metric-box h2 {
38583+ font-size: 20px;
38584+ margin-bottom: 10px;
38585+ }
38586+
38587+ .metric-box h1 {
38588+ font-size: 28px;
38589+ margin: 0;
38590+ }
38591+
38592+
38593+
38594+ .metric-box p {
38595+ font-size: 14px;
38596+ color: #666;
38597+ margin: 8px 0 0;
38598+ }
38599+
38600+ table {
38601+ width: 100%;
38602+ border-collapse: collapse;
38603+ background-color: white;
38604+ border-radius: 8px;
38605+ overflow: hidden;
38606+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.05);
38607+ }
38608+
38609+ th,
38610+ td {
38611+ padding: 12px 16px;
38612+ border-bottom: 1px solid #eee;
38613+ text-align: left;
38614+ font-size: 14px;
38615+ }
38616+
38617+ th {
38618+ background-color: #f1f3f5;
38619+ font-weight: bold;
38620+ }
38621+
38622+ tr:last-child td {
38623+ border-bottom: none;
38624+ }
38625+
38626+ .status-passed {
38627+ color: green;
38628+ font-weight: bold;
38629+ }
38630+
38631+ .status-failed {
38632+ color: red;
38633+ font-weight: bold;
38634+ }
38635+
38636+ .status-skipped {
38637+ color: #6c757d;
38638+ font-weight: bold;
38639+ }
38640+
38641+ .test-link a {
38642+ text-decoration: none;
38643+ color: #007bff;
38644+ }
38645+
38646+ .test-history a {
38647+ text-decoration: none;
38648+ color: #007bff;
38649+ }
38650+
38651+ .metric-box a {
38652+ text-decoration: none;
38653+ color: #007bff;
38654+ }`
3840738655 }
3840838656 };
3840938657 }
@@ -38421,20 +38669,25 @@ module.exports = new MockReportService(); // Export singleton instance
3842138669
3842238670
3842338671const core = __nccwpck_require__(7484);
38672+ const ArtifactManager = __nccwpck_require__(197);
3842438673
3842538674class ReportProcessor {
38426- static async processReport(reportData) {
38675+ static async processReport(reportData, buildName ) {
3842738676 try {
3842838677 const summary = core.summary;
3842938678 await summary.addHeading('BrowserStack Test Report');
3843038679
38431- // Process report content - both success and error cases come in report_html
3843238680 if (reportData?.report?.basic_html) {
38433- await summary.addRaw(reportData?.report?.basic_html);
38681+ await summary.addRaw(`<html>${reportData.report.basic_html}</html>`);
38682+
3843438683 } else {
3843538684 await summary.addRaw('⚠️ No report content available');
3843638685 }
3843738686
38687+ if(reportData?.report?.rich_html) {
38688+ const report = `<!DOCTYPE html> <html><head><style>${reportData?.report?.rich_css}</style></head> ${reportData?.report?.rich_html}</html>`;
38689+ await ArtifactManager.saveReportAsArtifact(report, buildName);
38690+ }
3843838691
3843938692 return summary.write();
3844038693 } catch (error) {
@@ -38554,6 +38807,68 @@ class ReportService {
3855438807module.exports = ReportService;
3855538808
3855638809
38810+ /***/ }),
38811+
38812+ /***/ 197:
38813+ /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
38814+
38815+ "use strict";
38816+
38817+
38818+ const fs = __nccwpck_require__(9896);
38819+ const path = __nccwpck_require__(6928);
38820+ const core = __nccwpck_require__(7484);
38821+ const artifact = __nccwpck_require__(1841);
38822+
38823+ class ArtifactManager {
38824+ static async saveReportAsArtifact(report, buildName) {
38825+ if (!report) {
38826+ core.debug('No HTML content available to save as artifact');
38827+ return '';
38828+ }
38829+
38830+ try {
38831+ // Create artifacts directory
38832+ const artifactDir = path.join(process.env.GITHUB_WORKSPACE || '.', 'browserstack-artifacts');
38833+ fs.mkdirSync(artifactDir, { recursive: true });
38834+
38835+ // Create HTML file
38836+ const sanitizedBuildName = buildName.replace(/[^a-z0-9]/gi, '_').toLowerCase();
38837+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
38838+ const fileName = `browserstack-report-${sanitizedBuildName}-${timestamp}.html`;
38839+ const filePath = path.join(artifactDir, fileName);
38840+
38841+ // Write content
38842+ fs.writeFileSync(filePath, report);
38843+
38844+ // Upload as artifact
38845+ const artifactClient = artifact.create();
38846+ const artifactName = `browserstack-report-${sanitizedBuildName}`;
38847+
38848+ const uploadResult = await artifactClient.uploadArtifact(
38849+ artifactName,
38850+ [filePath],
38851+ artifactDir,
38852+ { continueOnError: true }
38853+ );
38854+
38855+ if (uploadResult.failedItems.length > 0) {
38856+ core.warning(`Failed to upload artifacts: ${uploadResult.failedItems.join(', ')}`);
38857+ return '';
38858+ }
38859+
38860+ core.info(`Report saved as artifact: ${artifactName}`);
38861+ return `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts/${uploadResult.artifactId}`;
38862+ } catch (error) {
38863+ core.warning(`Failed to save artifact: ${error.message}`);
38864+ return '';
38865+ }
38866+ }
38867+ }
38868+
38869+ module.exports = ArtifactManager;
38870+
38871+
3855738872/***/ }),
3855838873
3855938874/***/ 933:
@@ -38578,6 +38893,14 @@ class TimeoutManager {
3857838893module.exports = TimeoutManager;
3857938894
3858038895
38896+ /***/ }),
38897+
38898+ /***/ 1841:
38899+ /***/ ((module) => {
38900+
38901+ module.exports = eval("require")("@actions/artifact");
38902+
38903+
3858138904/***/ }),
3858238905
3858338906/***/ 2078:
0 commit comments