@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.
Files changed (2) hide show
  1. package/dist/localReport.js +133 -15
  2. package/package.json +1 -1
@@ -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 `<div class="empty-state">No additional Playwright artifacts were detected.</div>`;
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
- ${renderAdditionalArtifacts(extraArtifacts)}
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
- <div class="artifact-list">
626
- <div class="artifact-link">Upload runs to Sentinel Cloud for:</div>
627
- <div class="artifact-link">• CI history</div>
628
- <div class="artifact-link">• shareable run links</div>
629
- <div class="artifact-link">• AI failure summaries</div>
630
- <div class="artifact-link">
631
- <a href="${SENTINEL_URL}" target="_blank" rel="noreferrer">More on sentinelqa.com</a>
632
- </div>
633
- </div>
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 extraArtifacts = [];
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
- const artifact = copyArtifact(resolved, classifyArtifact(resolved), reportDir, usedRelativePaths, null);
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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentinelqa/playwright-reporter",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "private": false,
5
5
  "description": "Playwright reporter for CI debugging with optional Sentinel cloud dashboards",
6
6
  "license": "MIT",