@sentinelqa/playwright-reporter 0.1.13 → 0.1.15
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/localReport.js +133 -15
- package/package.json +1 -1
package/dist/localReport.js
CHANGED
|
@@ -252,6 +252,27 @@ const summarizeTests = (tests) => {
|
|
|
252
252
|
const renderArtifact = (artifact) => {
|
|
253
253
|
const href = escapeHtml(artifact.relativePath);
|
|
254
254
|
const label = escapeHtml(artifact.label);
|
|
255
|
+
if (artifact.kind === "trace") {
|
|
256
|
+
return `
|
|
257
|
+
<div class="artifact-link artifact-link-trace">
|
|
258
|
+
<div class="artifact-trace-row">
|
|
259
|
+
<div class="artifact-trace-meta">
|
|
260
|
+
<span class="artifact-kind">Trace</span>
|
|
261
|
+
<a href="${href}" target="_blank" rel="noreferrer">${label}</a>
|
|
262
|
+
</div>
|
|
263
|
+
<a
|
|
264
|
+
class="trace-button"
|
|
265
|
+
href="${href}"
|
|
266
|
+
target="_blank"
|
|
267
|
+
rel="noreferrer"
|
|
268
|
+
data-trace-path="${href}"
|
|
269
|
+
>
|
|
270
|
+
View Trace
|
|
271
|
+
</a>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
`;
|
|
275
|
+
}
|
|
255
276
|
if (artifact.kind === "screenshot") {
|
|
256
277
|
return `
|
|
257
278
|
<div class="artifact-card">
|
|
@@ -321,7 +342,7 @@ const renderTestCard = (test) => {
|
|
|
321
342
|
};
|
|
322
343
|
const renderAdditionalArtifacts = (artifacts) => {
|
|
323
344
|
if (artifacts.length === 0) {
|
|
324
|
-
return
|
|
345
|
+
return "";
|
|
325
346
|
}
|
|
326
347
|
return `
|
|
327
348
|
<div class="artifact-list">
|
|
@@ -338,6 +359,27 @@ const renderAdditionalArtifacts = (artifacts) => {
|
|
|
338
359
|
</div>
|
|
339
360
|
`;
|
|
340
361
|
};
|
|
362
|
+
const tryMapRemainingArtifactsToTests = (tests, artifactPaths, reportDir, usedRelativePaths, claimedSourcePaths) => {
|
|
363
|
+
const candidateTests = tests.filter((test) => ["failed", "timedOut", "interrupted"].includes(test.status));
|
|
364
|
+
const preferredKinds = ["screenshot", "video", "trace", "log", "network"];
|
|
365
|
+
for (const kind of preferredKinds) {
|
|
366
|
+
const pathsForKind = artifactPaths.filter((filePath) => !claimedSourcePaths.has(path_1.default.resolve(filePath)) && classifyArtifact(filePath) === kind);
|
|
367
|
+
let cursor = 0;
|
|
368
|
+
for (const test of candidateTests) {
|
|
369
|
+
const alreadyHasKind = test.artifacts.some((artifact) => artifact.kind === kind);
|
|
370
|
+
if (alreadyHasKind)
|
|
371
|
+
continue;
|
|
372
|
+
const nextPath = pathsForKind[cursor];
|
|
373
|
+
if (!nextPath)
|
|
374
|
+
break;
|
|
375
|
+
const resolved = path_1.default.resolve(nextPath);
|
|
376
|
+
const artifact = copyArtifact(resolved, kind, reportDir, usedRelativePaths, test.id);
|
|
377
|
+
test.artifacts.push(artifact);
|
|
378
|
+
claimedSourcePaths.add(resolved);
|
|
379
|
+
cursor += 1;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
341
383
|
const buildHtml = (tests, summary, extraArtifacts) => {
|
|
342
384
|
const failedTests = tests.filter((test) => ["failed", "timedOut", "interrupted"].includes(test.status));
|
|
343
385
|
const generatedAt = new Date().toLocaleString();
|
|
@@ -514,6 +556,9 @@ const buildHtml = (tests, summary, extraArtifacts) => {
|
|
|
514
556
|
background: rgba(9, 13, 20, 0.9);
|
|
515
557
|
padding: 12px;
|
|
516
558
|
}
|
|
559
|
+
.artifact-link-trace {
|
|
560
|
+
padding: 14px;
|
|
561
|
+
}
|
|
517
562
|
.artifact-card img, .artifact-card video {
|
|
518
563
|
width: 100%;
|
|
519
564
|
border-radius: 10px;
|
|
@@ -538,11 +583,49 @@ const buildHtml = (tests, summary, extraArtifacts) => {
|
|
|
538
583
|
text-transform: uppercase;
|
|
539
584
|
letter-spacing: 0.08em;
|
|
540
585
|
}
|
|
586
|
+
.artifact-trace-row {
|
|
587
|
+
display: flex;
|
|
588
|
+
justify-content: space-between;
|
|
589
|
+
gap: 12px;
|
|
590
|
+
align-items: center;
|
|
591
|
+
}
|
|
592
|
+
.artifact-trace-meta {
|
|
593
|
+
display: flex;
|
|
594
|
+
gap: 10px;
|
|
595
|
+
align-items: center;
|
|
596
|
+
flex-wrap: wrap;
|
|
597
|
+
}
|
|
598
|
+
.trace-button {
|
|
599
|
+
display: inline-flex;
|
|
600
|
+
align-items: center;
|
|
601
|
+
justify-content: center;
|
|
602
|
+
padding: 8px 12px;
|
|
603
|
+
border-radius: 999px;
|
|
604
|
+
border: 1px solid rgba(125, 211, 252, 0.28);
|
|
605
|
+
background: rgba(125, 211, 252, 0.08);
|
|
606
|
+
color: var(--accent);
|
|
607
|
+
font-size: 12px;
|
|
608
|
+
font-weight: 600;
|
|
609
|
+
text-transform: uppercase;
|
|
610
|
+
letter-spacing: 0.06em;
|
|
611
|
+
white-space: nowrap;
|
|
612
|
+
}
|
|
613
|
+
.trace-button:hover {
|
|
614
|
+
text-decoration: none;
|
|
615
|
+
background: rgba(125, 211, 252, 0.14);
|
|
616
|
+
}
|
|
541
617
|
.artifact-list {
|
|
542
618
|
display: grid;
|
|
543
619
|
gap: 12px;
|
|
544
620
|
margin-top: 16px;
|
|
545
621
|
}
|
|
622
|
+
.section-shell ul {
|
|
623
|
+
margin: 12px 0 0 18px;
|
|
624
|
+
color: var(--text);
|
|
625
|
+
}
|
|
626
|
+
.section-shell li {
|
|
627
|
+
margin-top: 6px;
|
|
628
|
+
}
|
|
546
629
|
.empty-state {
|
|
547
630
|
color: var(--muted);
|
|
548
631
|
border: 1px dashed rgba(39, 48, 66, 0.9);
|
|
@@ -571,6 +654,10 @@ const buildHtml = (tests, summary, extraArtifacts) => {
|
|
|
571
654
|
}
|
|
572
655
|
.test-summary { flex-direction: column; }
|
|
573
656
|
.meta-stack { min-width: 0; }
|
|
657
|
+
.artifact-trace-row {
|
|
658
|
+
flex-direction: column;
|
|
659
|
+
align-items: flex-start;
|
|
660
|
+
}
|
|
574
661
|
}
|
|
575
662
|
</style>
|
|
576
663
|
</head>
|
|
@@ -617,26 +704,49 @@ const buildHtml = (tests, summary, extraArtifacts) => {
|
|
|
617
704
|
<section class="section-shell">
|
|
618
705
|
<h2>Additional Artifacts</h2>
|
|
619
706
|
<p>Artifacts collected from Playwright output folders that were not directly attached to a single test.</p>
|
|
620
|
-
${
|
|
707
|
+
${extraArtifacts.length > 0
|
|
708
|
+
? renderAdditionalArtifacts(extraArtifacts)
|
|
709
|
+
: `<div class="empty-state">All detected artifacts were mapped onto failed tests.</div>`}
|
|
621
710
|
</section>
|
|
622
711
|
|
|
623
712
|
<section class="section-shell">
|
|
624
713
|
<h2>Optional: Sentinel Cloud</h2>
|
|
625
|
-
<
|
|
626
|
-
|
|
627
|
-
<
|
|
628
|
-
<
|
|
629
|
-
<
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
</
|
|
633
|
-
</
|
|
714
|
+
<p>Upload runs to Sentinel Cloud for:</p>
|
|
715
|
+
<ul>
|
|
716
|
+
<li>CI history</li>
|
|
717
|
+
<li>shareable run links</li>
|
|
718
|
+
<li>AI failure summaries</li>
|
|
719
|
+
</ul>
|
|
720
|
+
<p>
|
|
721
|
+
<a href="${SENTINEL_URL}" target="_blank" rel="noreferrer">More on sentinelqa.com</a>
|
|
722
|
+
</p>
|
|
634
723
|
</section>
|
|
635
724
|
|
|
636
725
|
<footer>
|
|
637
726
|
Generated by <a href="${SENTINEL_URL}" target="_blank" rel="noreferrer">Sentinel Playwright Reporter</a>.
|
|
638
727
|
</footer>
|
|
639
728
|
</div>
|
|
729
|
+
<script>
|
|
730
|
+
(function () {
|
|
731
|
+
var traceButtons = document.querySelectorAll("[data-trace-path]");
|
|
732
|
+
traceButtons.forEach(function (button) {
|
|
733
|
+
var tracePath = button.getAttribute("data-trace-path");
|
|
734
|
+
if (!tracePath) return;
|
|
735
|
+
|
|
736
|
+
try {
|
|
737
|
+
if (window.location.protocol === "http:" || window.location.protocol === "https:") {
|
|
738
|
+
var traceUrl = new URL(tracePath, window.location.href).href;
|
|
739
|
+
button.setAttribute(
|
|
740
|
+
"href",
|
|
741
|
+
"https://trace.playwright.dev/?trace=" + encodeURIComponent(traceUrl)
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
} catch (_error) {
|
|
745
|
+
// Fall back to the raw trace zip link when URL construction fails.
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
})();
|
|
749
|
+
</script>
|
|
640
750
|
</body>
|
|
641
751
|
</html>`;
|
|
642
752
|
};
|
|
@@ -686,17 +796,25 @@ function generateLocalDebugReport(options) {
|
|
|
686
796
|
}
|
|
687
797
|
}
|
|
688
798
|
}
|
|
689
|
-
const
|
|
799
|
+
const discoveredArtifactPaths = [];
|
|
690
800
|
for (const sourceDir of sourceDirs) {
|
|
691
801
|
for (const filePath of listFilesRecursive(sourceDir)) {
|
|
692
802
|
const resolved = path_1.default.resolve(filePath);
|
|
693
803
|
if (claimedSourcePaths.has(resolved))
|
|
694
804
|
continue;
|
|
695
|
-
|
|
696
|
-
claimedSourcePaths.add(resolved);
|
|
697
|
-
extraArtifacts.push(artifact);
|
|
805
|
+
discoveredArtifactPaths.push(resolved);
|
|
698
806
|
}
|
|
699
807
|
}
|
|
808
|
+
tryMapRemainingArtifactsToTests(tests, discoveredArtifactPaths, reportDir, usedRelativePaths, claimedSourcePaths);
|
|
809
|
+
const extraArtifacts = [];
|
|
810
|
+
for (const filePath of discoveredArtifactPaths) {
|
|
811
|
+
const resolved = path_1.default.resolve(filePath);
|
|
812
|
+
if (claimedSourcePaths.has(resolved))
|
|
813
|
+
continue;
|
|
814
|
+
const artifact = copyArtifact(resolved, classifyArtifact(resolved), reportDir, usedRelativePaths, null);
|
|
815
|
+
claimedSourcePaths.add(resolved);
|
|
816
|
+
extraArtifacts.push(artifact);
|
|
817
|
+
}
|
|
700
818
|
const summary = summarizeTests(tests);
|
|
701
819
|
const html = buildHtml(tests, summary, extraArtifacts);
|
|
702
820
|
fs_1.default.writeFileSync(reportHtmlPath, html, "utf8");
|