ortoni-report 1.1.1 → 1.1.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/changelog.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Change Log:
2
2
 
3
+ ## Version 1.1.2
4
+
5
+ **New Features:**
6
+ - **Ellipsis Styling for Test Names:** Long test names are now truncated with ellipsis for better readability.
7
+ - **Retry, Pass, Fail, and Skip Indicators:** Added visual indicators (images) to denote the status of each test, including retries.
8
+ - **Enhanced `msToTime` Function:** Duration now includes milliseconds for more precise time tracking.
9
+ - **Summary Filters:** Clicking on summary filters (passed, failed & other) to display the selected filter.
10
+
11
+ **Improvements:**
12
+ - **Unified Status Handling:** The `applyFilter` function now treats `failed` and `timedOut` statuses as the same for consistent filtering.
13
+ - **Date and Time Formatting:** Passed date in the format `DD-MMM-YYYY` and included time for more detailed reporting.
14
+ - **Success Rate and Last Run Data:** Added the ability to pass `successRate` and `lastRun` data to the `onEnd` method for comprehensive report details.
15
+
16
+ **Bug Fixes:**
17
+ - Fixed issues with conditionals in Handlebars for status checking.
18
+ - Improved event listener attachment for filtering and search functionalities.
19
+
20
+ **Notes:**
21
+ - Screenshot handling has been enhanced with modal dialogs, using Pico.css for styling.
22
+
23
+ This release includes several visual and functional enhancements aimed at improving the usability and readability of the Playwright test reports. The added features and improvements will help users better understand test outcomes and statuses at a glance.
24
+
3
25
  ### Version 1.1.0
4
26
 
5
27
  ## New Features
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -15,6 +15,7 @@ declare class OrtoniReport implements Reporter {
15
15
  onBegin(config: FullConfig, suite: Suite): void;
16
16
  onTestBegin(test: TestCase, result: TestResult): void;
17
17
  onTestEnd(test: TestCase, result: TestResult): void;
18
+ private _successRate;
18
19
  onEnd(result: FullResult): void;
19
20
  generateHTML(): string;
20
21
  }
@@ -38,30 +38,36 @@ var import_path2 = __toESM(require("path"));
38
38
  var import_handlebars = __toESM(require("handlebars"));
39
39
  var import_safe = __toESM(require("colors/safe"));
40
40
 
41
- // src/utils/time.ts
41
+ // src/utils/utils.ts
42
42
  var import_path = __toESM(require("path"));
43
43
  function msToTime(duration) {
44
+ const milliseconds = Math.floor(duration % 1e3);
44
45
  const seconds = Math.floor(duration / 1e3 % 60);
45
46
  const minutes = Math.floor(duration / (1e3 * 60) % 60);
46
47
  const hours = Math.floor(duration / (1e3 * 60 * 60) % 24);
47
- const parts = [];
48
- if (hours > 0)
49
- parts.push(hours + "h");
50
- if (minutes > 0)
51
- parts.push(minutes + "m");
52
- if (seconds > 0 || parts.length === 0)
53
- parts.push(seconds + "s");
54
- return parts.join(" ");
48
+ const hoursStr = hours < 10 ? "0" + hours : hours;
49
+ const minutesStr = minutes < 10 ? "0" + minutes : minutes;
50
+ const secondsStr = seconds < 10 ? "0" + seconds : seconds;
51
+ const millisecondsStr = milliseconds < 100 ? "0" + milliseconds : milliseconds;
52
+ return `${hoursStr}:${minutesStr}:${secondsStr}.${millisecondsStr}`;
55
53
  }
56
54
  function normalizeFilePath(filePath) {
57
55
  const normalizedPath = import_path.default.normalize(filePath);
58
56
  return import_path.default.basename(normalizedPath);
59
57
  }
58
+ function formatDate(date) {
59
+ const day = String(date.getDate()).padStart(2, "0");
60
+ const month = date.toLocaleString("default", { month: "short" });
61
+ const year = date.getFullYear();
62
+ const time = date.toLocaleTimeString();
63
+ return `${day}-${month}-${year} ${time}`;
64
+ }
60
65
 
61
66
  // src/ortoni-report.ts
62
67
  var OrtoniReport = class {
63
68
  constructor(config = {}) {
64
69
  this.results = [];
70
+ this._successRate = "";
65
71
  this.config = config;
66
72
  }
67
73
  onBegin(config, suite) {
@@ -75,14 +81,19 @@ var OrtoniReport = class {
75
81
  onTestBegin(test, result) {
76
82
  }
77
83
  onTestEnd(test, result) {
84
+ let status = result.status;
85
+ if (test.outcome() === "flaky") {
86
+ status = "flaky";
87
+ }
78
88
  const testResult = {
89
+ isRetry: result.retry,
79
90
  totalDuration: "",
80
91
  projectName: test.titlePath()[1],
81
92
  // Get the project name
82
93
  suite: test.titlePath()[3],
83
94
  // Adjust the index based on your suite hierarchy
84
95
  title: test.title,
85
- status: result.status,
96
+ status,
86
97
  flaky: test.outcome(),
87
98
  duration: msToTime(result.duration),
88
99
  errors: result.errors.map((e) => import_safe.default.strip(e.message || e.toString())),
@@ -112,6 +123,7 @@ var OrtoniReport = class {
112
123
  this.results.push(testResult);
113
124
  }
114
125
  onEnd(result) {
126
+ this._successRate = (this.results.filter((r) => r.status === "passed").length / this.results.length * 100).toFixed(2);
115
127
  this.results[0].totalDuration = msToTime(result.duration);
116
128
  this.groupedResults = this.results.reduce((acc, result2, index) => {
117
129
  const filePath = result2.filePath;
@@ -132,6 +144,22 @@ var OrtoniReport = class {
132
144
  import_handlebars.default.registerHelper("json", function(context) {
133
145
  return safeStringify(context);
134
146
  });
147
+ import_handlebars.default.registerHelper("eq", function(actualStatus, expectedStatus) {
148
+ return actualStatus === expectedStatus;
149
+ });
150
+ import_handlebars.default.registerHelper("or", () => {
151
+ var args = Array.prototype.slice.call(arguments);
152
+ var options = args.pop();
153
+ for (var i = 0; i < args.length; i++) {
154
+ if (args[i]) {
155
+ return options.fn(this);
156
+ }
157
+ }
158
+ return options.inverse(this);
159
+ });
160
+ import_handlebars.default.registerHelper("gt", function(a, b) {
161
+ return a > b;
162
+ });
135
163
  const html = this.generateHTML();
136
164
  const outputPath = import_path2.default.resolve(process.cwd(), "ortoni-report.html");
137
165
  import_fs.default.writeFileSync(outputPath, html);
@@ -151,11 +179,10 @@ var OrtoniReport = class {
151
179
  totalCount: this.results.length,
152
180
  groupedResults: this.groupedResults,
153
181
  projectName: this.config.projectName,
154
- // Include project name
155
182
  authorName: this.config.authorName,
156
- // Include author name
157
- testType: this.config.testType
158
- // Include test type
183
+ testType: this.config.testType,
184
+ successRate: this._successRate,
185
+ lastRunDate: formatDate(/* @__PURE__ */ new Date())
159
186
  };
160
187
  return template(data);
161
188
  }
@@ -4,30 +4,36 @@ import path2 from "path";
4
4
  import Handlebars from "handlebars";
5
5
  import colors from "colors/safe";
6
6
 
7
- // src/utils/time.ts
7
+ // src/utils/utils.ts
8
8
  import path from "path";
9
9
  function msToTime(duration) {
10
+ const milliseconds = Math.floor(duration % 1e3);
10
11
  const seconds = Math.floor(duration / 1e3 % 60);
11
12
  const minutes = Math.floor(duration / (1e3 * 60) % 60);
12
13
  const hours = Math.floor(duration / (1e3 * 60 * 60) % 24);
13
- const parts = [];
14
- if (hours > 0)
15
- parts.push(hours + "h");
16
- if (minutes > 0)
17
- parts.push(minutes + "m");
18
- if (seconds > 0 || parts.length === 0)
19
- parts.push(seconds + "s");
20
- return parts.join(" ");
14
+ const hoursStr = hours < 10 ? "0" + hours : hours;
15
+ const minutesStr = minutes < 10 ? "0" + minutes : minutes;
16
+ const secondsStr = seconds < 10 ? "0" + seconds : seconds;
17
+ const millisecondsStr = milliseconds < 100 ? "0" + milliseconds : milliseconds;
18
+ return `${hoursStr}:${minutesStr}:${secondsStr}.${millisecondsStr}`;
21
19
  }
22
20
  function normalizeFilePath(filePath) {
23
21
  const normalizedPath = path.normalize(filePath);
24
22
  return path.basename(normalizedPath);
25
23
  }
24
+ function formatDate(date) {
25
+ const day = String(date.getDate()).padStart(2, "0");
26
+ const month = date.toLocaleString("default", { month: "short" });
27
+ const year = date.getFullYear();
28
+ const time = date.toLocaleTimeString();
29
+ return `${day}-${month}-${year} ${time}`;
30
+ }
26
31
 
27
32
  // src/ortoni-report.ts
28
33
  var OrtoniReport = class {
29
34
  constructor(config = {}) {
30
35
  this.results = [];
36
+ this._successRate = "";
31
37
  this.config = config;
32
38
  }
33
39
  onBegin(config, suite) {
@@ -41,14 +47,19 @@ var OrtoniReport = class {
41
47
  onTestBegin(test, result) {
42
48
  }
43
49
  onTestEnd(test, result) {
50
+ let status = result.status;
51
+ if (test.outcome() === "flaky") {
52
+ status = "flaky";
53
+ }
44
54
  const testResult = {
55
+ isRetry: result.retry,
45
56
  totalDuration: "",
46
57
  projectName: test.titlePath()[1],
47
58
  // Get the project name
48
59
  suite: test.titlePath()[3],
49
60
  // Adjust the index based on your suite hierarchy
50
61
  title: test.title,
51
- status: result.status,
62
+ status,
52
63
  flaky: test.outcome(),
53
64
  duration: msToTime(result.duration),
54
65
  errors: result.errors.map((e) => colors.strip(e.message || e.toString())),
@@ -78,6 +89,7 @@ var OrtoniReport = class {
78
89
  this.results.push(testResult);
79
90
  }
80
91
  onEnd(result) {
92
+ this._successRate = (this.results.filter((r) => r.status === "passed").length / this.results.length * 100).toFixed(2);
81
93
  this.results[0].totalDuration = msToTime(result.duration);
82
94
  this.groupedResults = this.results.reduce((acc, result2, index) => {
83
95
  const filePath = result2.filePath;
@@ -98,6 +110,22 @@ var OrtoniReport = class {
98
110
  Handlebars.registerHelper("json", function(context) {
99
111
  return safeStringify(context);
100
112
  });
113
+ Handlebars.registerHelper("eq", function(actualStatus, expectedStatus) {
114
+ return actualStatus === expectedStatus;
115
+ });
116
+ Handlebars.registerHelper("or", () => {
117
+ var args = Array.prototype.slice.call(arguments);
118
+ var options = args.pop();
119
+ for (var i = 0; i < args.length; i++) {
120
+ if (args[i]) {
121
+ return options.fn(this);
122
+ }
123
+ }
124
+ return options.inverse(this);
125
+ });
126
+ Handlebars.registerHelper("gt", function(a, b) {
127
+ return a > b;
128
+ });
101
129
  const html = this.generateHTML();
102
130
  const outputPath = path2.resolve(process.cwd(), "ortoni-report.html");
103
131
  fs.writeFileSync(outputPath, html);
@@ -117,11 +145,10 @@ var OrtoniReport = class {
117
145
  totalCount: this.results.length,
118
146
  groupedResults: this.groupedResults,
119
147
  projectName: this.config.projectName,
120
- // Include project name
121
148
  authorName: this.config.authorName,
122
- // Include author name
123
- testType: this.config.testType
124
- // Include test type
149
+ testType: this.config.testType,
150
+ successRate: this._successRate,
151
+ lastRunDate: formatDate(/* @__PURE__ */ new Date())
125
152
  };
126
153
  return template(data);
127
154
  }