odhin-reports-playwright 1.1.8 → 1.2.2

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/README.md CHANGED
@@ -18,10 +18,31 @@
18
18
  </div>
19
19
  </div>
20
20
 
21
+ ## Report layout
22
+
23
+ The reporter generates one self-contained report by default:
24
+
25
+ ```ts
26
+ reporter: [["odhin-reports-playwright", {
27
+ singleFile: true,
28
+ embedAssets: true,
29
+ embedAttachments: true,
30
+ }]]
31
+ ```
32
+
33
+ Set `singleFile: false` to keep each test detail, screenshot, video, and trace in `tests/<test-id>/`. In this mode, `embedAssets` and `embedAttachments` are always disabled and the report can be opened directly from disk.
34
+
35
+ ```ts
36
+ reporter: [["odhin-reports-playwright", {
37
+ singleFile: false,
38
+ }]]
39
+ ```
40
+
21
41
  &nbsp;
22
42
  &nbsp;
23
43
  &nbsp;
24
44
 
45
+
25
46
  ### [Full documentation](https://odhin-reports.gitlab.io/playwright/#/v1/)
26
47
 
27
48
  &nbsp;
package/lib/generate.js CHANGED
@@ -19,7 +19,7 @@ class Generate {
19
19
  this.TEST_FOLDER = "tests";
20
20
  this.THEME = "light";
21
21
  this.INDEX_FILE = "index.html";
22
- this.CURRENT_VERSION = "1.1.8";
22
+ this.CURRENT_VERSION = "1.2.2";
23
23
  this.execOptions = execOptions;
24
24
  this.totalDuration = 0;
25
25
  this.help = new help_1.default(this.execOptions);
@@ -54,14 +54,22 @@ class Generate {
54
54
  this.execOptions.project !== undefined ? this.execOptions.project : "";
55
55
  this.execOptions.release =
56
56
  this.execOptions.release !== undefined ? this.execOptions.release : "";
57
+ this.execOptions.singleFile =
58
+ this.execOptions.singleFile !== undefined
59
+ ? this.execOptions.singleFile
60
+ : true;
57
61
  this.execOptions.embedAssets =
58
- this.execOptions.embedAssets !== undefined
62
+ this.execOptions.singleFile && this.execOptions.embedAssets !== undefined
59
63
  ? this.execOptions.embedAssets
60
64
  : true;
61
65
  this.execOptions.embedAttachments =
62
- this.execOptions.embedAttachments !== undefined
66
+ this.execOptions.singleFile && this.execOptions.embedAttachments !== undefined
63
67
  ? this.execOptions.embedAttachments
64
68
  : true;
69
+ if (this.execOptions.singleFile === false) {
70
+ this.execOptions.embedAssets = false;
71
+ this.execOptions.embedAttachments = false;
72
+ }
65
73
  this.execOptions.outputFolder =
66
74
  this.execOptions.outputFolder !== undefined
67
75
  ? this.execOptions.outputFolder
@@ -742,6 +750,12 @@ class Generate {
742
750
  let testCaseId = testCase.testCase.id + "-" + testCase.result.retry;
743
751
  let testCaseHtml = this.testCaseTemplate;
744
752
  testCaseHtml = testCaseHtml.replaceAll("{{.ModalID}}", testCaseId);
753
+ testCaseHtml = testCaseHtml.replaceAll("{{.TestDetailsAttributes}}", this.execOptions.singleFile
754
+ ? `data-bs-toggle="modal" data-bs-target="#${testCaseId}"`
755
+ : `data-modal-id="${testCaseId}" data-test-details-url="tests/${encodeURIComponent(testCaseId)}/details.js"`);
756
+ testCaseHtml = testCaseHtml.replaceAll("{{.TestDetailsAction}}", this.execOptions.singleFile
757
+ ? "showHideScroll('hide')"
758
+ : "showTestDetails(this)");
745
759
  if (showRetries) {
746
760
  testCaseHtml = testCaseHtml.replaceAll("{{.Retry}}", '<td class="{{.TDClassesCss}}">' +
747
761
  (testCase.result.retry > 0
@@ -956,7 +970,18 @@ class Generate {
956
970
  testCaseDetailsHtml = testCaseDetailsHtml.replaceAll("{{.StderrTabButton}}", "");
957
971
  testCaseDetailsHtml = testCaseDetailsHtml.replaceAll("{{.Stderr}}", "");
958
972
  }
959
- testCasesDetails += testCaseDetailsHtml;
973
+ if (this.execOptions.singleFile) {
974
+ testCasesDetails += testCaseDetailsHtml;
975
+ }
976
+ else {
977
+ const externalTestDetails = testCaseDetailsHtml
978
+ .replaceAll(`screenshots/${testCaseId}/`, `tests/${encodeURIComponent(testCaseId)}/screenshots/`)
979
+ .replaceAll(`videos/${testCaseId}/`, `tests/${encodeURIComponent(testCaseId)}/videos/`)
980
+ .replaceAll(`traces/${testCaseId}/`, `tests/${encodeURIComponent(testCaseId)}/traces/`);
981
+ const externalTestDetailsScript = "window.odhinTestDetails = window.odhinTestDetails || {};" +
982
+ `window.odhinTestDetails[${JSON.stringify(testCaseId)}] = ${JSON.stringify(externalTestDetails)};`;
983
+ this.help.createFile(path_1.default.join(this.execOptions.outputFolder, "tests", encodeURIComponent(testCaseId), "details.js"), externalTestDetailsScript);
984
+ }
960
985
  });
961
986
  this.content = this.content.replace("{{.TestCases}}", testCases);
962
987
  this.content = this.content.replaceAll("{{.TestCasesDetails}}", testCasesDetails);
package/lib/help.js CHANGED
@@ -474,6 +474,14 @@ class Help {
474
474
  return output;
475
475
  }
476
476
  base64ToFile(base64data, filePath, index) {
477
+ if (this.execOptions.singleFile === false) {
478
+ const relativePath = path_1.default.relative(this.execOptions.outputFolder, filePath);
479
+ const [attachmentType, testId, ...filenameParts] = relativePath.split(path_1.default.sep);
480
+ if (["screenshots", "videos", "traces"].includes(attachmentType) &&
481
+ testId !== undefined) {
482
+ filePath = path_1.default.join(this.execOptions.outputFolder, "tests", encodeURIComponent(testId), attachmentType, ...filenameParts);
483
+ }
484
+ }
477
485
  if (fs_1.default.existsSync(filePath)) {
478
486
  let newIndex = index !== undefined && index > 0 ? index + 1 : 1;
479
487
  let filename = filePath.split("/").pop();
@@ -58,4 +58,34 @@ function openMainTab(evt, tabName) {
58
58
  }
59
59
  document.getElementById(tabName).style.display = "block";
60
60
  evt.currentTarget.className += " active";
61
+ }
62
+
63
+ function showTestDetails(row) {
64
+ const modalId = row.dataset.modalId;
65
+ const modal = document.getElementById(modalId);
66
+
67
+ if (modal) {
68
+ openTestDetailsModal(modal);
69
+ return;
70
+ }
71
+
72
+ const script = document.createElement("script");
73
+ script.src = row.dataset.testDetailsUrl;
74
+ script.onload = function () {
75
+ const details = window.odhinTestDetails && window.odhinTestDetails[modalId];
76
+ if (!details) {
77
+ return;
78
+ }
79
+ document.getElementById("test-case-details").insertAdjacentHTML("beforeend", details);
80
+ openTestDetailsModal(document.getElementById(modalId));
81
+ };
82
+ document.head.appendChild(script);
83
+ }
84
+
85
+ function openTestDetailsModal(modal) {
86
+ if (!modal) {
87
+ return;
88
+ }
89
+ showHideScroll("hide");
90
+ bootstrap.Modal.getOrCreateInstance(modal).show();
61
91
  }
@@ -1 +1 @@
1
- function showHideScroll(e){let t=document.getElementById("body-content");"show"===e?t.classList.contains("hide-scroll")&&t.classList.remove("hide-scroll"):"hide"===e&&(t.classList.contains("hide-scroll")||t.classList.add("hide-scroll"))}function hideLoader(){document.getElementById("loading").style.visibility="visibility",document.getElementById("loading").style.opacity="0",document.getElementById("loading").style.transition="all .3s linear",document.getElementById("loading").style.zIndex="0",setTimeout(function(){document.getElementById("loading").style.display="none"},1800)}function openResultTab(e,t,n){for(var l,a=document.getElementsByClassName("result-tabcontent-"+n),s=0;s<a.length;s++)a[s].style.display="none";for(l=document.getElementsByClassName("result-tablinks-"+n),s=0;s<l.length;s++)l[s].className=l[s].className.replace(" active","");document.getElementById(t).style.display="block",e.currentTarget.className+=" active"}function openMainTab(e,t){for(var n,l=document.getElementsByClassName("main-tabcontent"),a=0;a<l.length;a++)l[a].style.display="none";for(n=document.getElementsByClassName("main-tablinks"),a=0;a<n.length;a++)n[a].className=n[a].className.replace(" active","");document.getElementById(t).style.display="block",e.currentTarget.className+=" active"}window.addEventListener?window.addEventListener("load",hideLoader):window.attachEvent?window.attachEvent("onload",hideLoader):window.onload=hideLoader;
1
+ function showHideScroll(e){let t=document.getElementById("body-content");"show"===e?t.classList.contains("hide-scroll")&&t.classList.remove("hide-scroll"):"hide"===e&&(t.classList.contains("hide-scroll")||t.classList.add("hide-scroll"))}function hideLoader(){document.getElementById("loading").style.visibility="visibility",document.getElementById("loading").style.opacity="0",document.getElementById("loading").style.transition="all .3s linear",document.getElementById("loading").style.zIndex="0",setTimeout(function(){document.getElementById("loading").style.display="none"},1800)}function openResultTab(e,t,n){for(var l,a=document.getElementsByClassName("result-tabcontent-"+n),s=0;s<a.length;s++)a[s].style.display="none";for(l=document.getElementsByClassName("result-tablinks-"+n),s=0;s<l.length;s++)l[s].className=l[s].className.replace(" active","");document.getElementById(t).style.display="block",e.currentTarget.className+=" active"}function openMainTab(e,t){for(var n,l=document.getElementsByClassName("main-tabcontent"),a=0;a<l.length;a++)l[a].style.display="none";for(n=document.getElementsByClassName("main-tablinks"),a=0;a<n.length;a++)n[a].className=n[a].className.replace(" active","");document.getElementById(t).style.display="block",e.currentTarget.className+=" active"}function showTestDetails(e){const t=e.dataset.modalId,n=document.getElementById(t);if(n)return void openTestDetailsModal(n);const l=document.createElement("script");l.src=e.dataset.testDetailsUrl,l.onload=function(){const n=window.odhinTestDetails&&window.odhinTestDetails[t];n&&(document.getElementById("test-case-details").insertAdjacentHTML("beforeend",n),openTestDetailsModal(document.getElementById(t)))},document.head.appendChild(l)}function openTestDetailsModal(e){e&&(showHideScroll("hide"),bootstrap.Modal.getOrCreateInstance(e).show())}window.addEventListener?window.addEventListener("load",hideLoader):window.attachEvent?window.attachEvent("onload",hideLoader):window.onload=hideLoader;
@@ -28,5 +28,5 @@
28
28
  </tfoot>
29
29
  </table>
30
30
  </div>
31
- {{.TestCasesDetails}}
31
+ <div id="test-case-details">{{.TestCasesDetails}}</div>
32
32
  </div>
@@ -1,7 +1,6 @@
1
1
  <tr class="test-row-result row-{{.TRClassesCss}} {{.TRClassesCss}}"
2
- data-bs-toggle="modal"
3
- data-bs-target="#{{.ModalID}}"
4
- onclick="showHideScroll('hide')"
2
+ {{.TestDetailsAttributes}}
3
+ onclick="{{.TestDetailsAction}}"
5
4
  >
6
5
  <td class="{{.TDClassesCss}}">{{.Title}}</td>
7
6
  <td class="text-capitalize {{.TDClassesCss}}">{{.Status}}</td>
@@ -4,6 +4,7 @@ export interface ExecOptions {
4
4
  testEnvironment: string;
5
5
  project: string;
6
6
  release: string;
7
+ singleFile: boolean;
7
8
  embedAssets: boolean;
8
9
  embedAttachments: boolean;
9
10
  outputFolder: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odhin-reports-playwright",
3
- "version": "1.1.8",
3
+ "version": "1.2.2",
4
4
  "description": "Odhin Reports for Playwright",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -32,7 +32,8 @@
32
32
  },
33
33
  "homepage": "https://gitlab.com/odhin-reports/playwright/-/blob/main/README.md?ref_type=heads",
34
34
  "devDependencies": {
35
- "@playwright/test": "^1.49.0"
35
+ "@playwright/test": "^1.49.0",
36
+ "@types/node": "^26.2.0"
36
37
  },
37
38
  "dependencies": {
38
39
  "ansi-to-html": "^0.7.2",