ortoni-report 3.0.1 → 3.0.3

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.
@@ -0,0 +1,103 @@
1
+ <h1 class="title is-3">Analytics</h1>
2
+ <div class="columns is-multiline has-text-centered">
3
+ {{> summaryCard bg="hsl(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l)) !important"
4
+ statusHeader="Total Runs" statusCount=reportAnalyticsData.summary.totalRuns}}
5
+ {{> summaryCard bg="hsl(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l)) !important"
6
+ statusHeader="Total Tests" statusCount=reportAnalyticsData.summary.totalTests}}
7
+ {{> summaryCard bg="hsl(var(--bulma-success-h), var(--bulma-success-s), var(--bulma-success-l)) !important"
8
+ status="Passed" statusHeader="Passed" statusCount=reportAnalyticsData.summary.passed}}
9
+ {{> summaryCard bg="hsl(var(--bulma-danger-h), var(--bulma-danger-s), var(--bulma-danger-l)) !important"
10
+ status="Failed"
11
+ statusHeader="Failed" statusCount=reportAnalyticsData.summary.failed}}
12
+ {{> summaryCard bg="hsl(var(--bulma-info-h), var(--bulma-info-s), var(--bulma-info-l)) !important"
13
+ statusHeader="Pass Rate: %" statusCount=reportAnalyticsData.summary.passRate}}
14
+ {{> summaryCard bg="#69748c" statusHeader="Avg Duration (ms)" statusCount=reportAnalyticsData.summary.avgDuration}}
15
+ </div>
16
+
17
+ <section class="box">
18
+ <h2 class="title is-4">Trends Over Time</h2>
19
+ <canvas id="trendChart" height="100"></canvas>
20
+ </section>
21
+
22
+ <section class="box">
23
+ <h2 class="title is-4">Top Flaky Tests</h2>
24
+ <table class="table is-striped is-fullwidth">
25
+ <thead>
26
+ <tr>
27
+ <th>Test ID</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ {{#each reportAnalyticsData.flakyTests}}
32
+ <tr>
33
+ <td>{{this.test_id}}</td>
34
+ </tr>
35
+ {{/each}}
36
+ </tbody>
37
+ </table>
38
+ </section>
39
+
40
+ <section class="box">
41
+ <h2 class="title is-4">Slowest Tests</h2>
42
+ <table class="table is-striped is-fullwidth">
43
+ <thead>
44
+ <tr>
45
+ <th>Test ID</th>
46
+ <th>Avg Duration (ms)</th>
47
+ </tr>
48
+ </thead>
49
+ <tbody>
50
+ {{#each reportAnalyticsData.slowTests}}
51
+ <tr>
52
+ <td>{{this.test_id}}</td>
53
+ <td>{{this.avg_duration}}</td>
54
+ </tr>
55
+ {{/each}}
56
+ </tbody>
57
+ </table>
58
+ </section>
59
+ <script>
60
+ const ctx = document.getElementById('trendChart').getContext('2d');
61
+ const trendChart = new Chart(ctx, {
62
+ type: 'line',
63
+ data: {
64
+ labels: {{{ json chartData.labels }}},
65
+ datasets: [
66
+ {
67
+ label: 'Passed',
68
+ data: {{ json chartData.passed }},
69
+ borderColor: 'green',
70
+ fill: false
71
+ },
72
+ {
73
+ label: 'Failed',
74
+ data: {{ json chartData.failed }},
75
+ borderColor: 'red',
76
+ fill: false
77
+ },
78
+ {
79
+ label: 'Avg Duration (ms)',
80
+ data: {{ json chartData.avgDuration }},
81
+ borderColor: 'blue',
82
+ fill: false,
83
+ yAxisID: 'y1'
84
+ }
85
+ ]
86
+ },
87
+ options: {
88
+ responsive: true,
89
+ scales: {
90
+ y: {
91
+ beginAtZero: true,
92
+ title: { display: true, text: 'Count' }
93
+ },
94
+ y1: {
95
+ beginAtZero: true,
96
+ position: 'right',
97
+ title: { display: true, text: 'Duration (ms)' },
98
+ grid: { drawOnChartArea: false }
99
+ }
100
+ }
101
+ }
102
+ });
103
+ </script>
@@ -1,7 +1,7 @@
1
1
  <head>
2
2
  <meta charset="UTF-8" />
3
3
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
4
- <meta name="description" content="Playwright HTML report by LetCode Koushik - V3.0.1" />
4
+ <meta name="description" content="Ortoni Report - V3.0.3" />
5
5
  <title>{{title}}</title>
6
6
  <link rel="icon" href="https://raw.githubusercontent.com/ortoniKC/ortoni-report/refs/heads/main/favicon.png"
7
7
  type="image/x-icon" />
@@ -48,6 +48,9 @@
48
48
  </div>
49
49
  </div>
50
50
  </div>
51
+ <div id="analytics-section" class="content-section" style="display: none;">
52
+ {{> analytics}}
53
+ </div>
51
54
  </main>
52
55
  </div>
53
56
  <script>
@@ -119,6 +122,21 @@
119
122
  return `${origin}${directoryPath}`;
120
123
  }
121
124
  return origin;
125
+ },
126
+
127
+ /**
128
+ * Copy file path to clipboard
129
+ * @param {HTMLElement} button - Button element
130
+ * @param {string} text - Text to copy
131
+ */
132
+ copyFilePath(button, text) {
133
+ navigator.clipboard.writeText(text).then(() => {
134
+ const originalIcon = button.innerHTML;
135
+ button.innerHTML = '<i class="fa fa-check"></i>';
136
+ setTimeout(() => {
137
+ button.innerHTML = originalIcon;
138
+ }, 1500);
139
+ });
122
140
  }
123
141
  };
124
142
 
@@ -135,6 +153,7 @@
135
153
  this.sidebarLinks = document.querySelectorAll('.sidebar-menu-link');
136
154
  this.sections = document.querySelectorAll('.content-section');
137
155
  this.testDetailsSection = document.getElementById('testDetails');
156
+ this.analyticsSection = document.getElementById('analytics-section');
138
157
  this.sidebar = document.getElementById('sidebar');
139
158
  this.mainContent = document.querySelector('.main-content');
140
159
  this.init();
@@ -178,6 +197,7 @@
178
197
  showSection(sectionId) {
179
198
  // Hide test details if showing a main section
180
199
  this.testDetailsSection.style.display = 'none';
200
+ this.analyticsSection.style.display = 'none';
181
201
 
182
202
  // Show the selected section
183
203
  this.sections.forEach(section => {
@@ -381,7 +401,12 @@
381
401
  <div class="card-content">
382
402
  <div class="content has-text-centered">
383
403
  <h1 class="title is-4">${test.title}</h1>
384
- <p class="subtitle is-5" id="filepath">${test.location}</p>
404
+ <div class="is-flex is-justify-content-center is-align-items-center">
405
+ <p class="subtitle is-5 mb-0" id="filepath">${test.location}</p>
406
+ <button class="button has-text-primary is-small is-ghost ml-2" onclick="copyFilePath(this, '${test.location}')" title="Copy to clipboard">
407
+ <i class="fa-regular fa-clipboard"></i>
408
+ </button>
409
+ </div>
385
410
  </div>
386
411
  </div>
387
412
  <footer class="card-footer">
@@ -412,7 +437,7 @@
412
437
  ${test.projectName ? `
413
438
  <div class="card-footer-item">
414
439
  <div class="is-flex is-align-items-center">
415
- <span class="icon status-icon has-text-link">
440
+ <span class="icon status-icon has-text-info">
416
441
  ${projectIcon}
417
442
  </span>
418
443
  <span> ${test.projectName}</span>
@@ -518,10 +543,20 @@
518
543
  </button>
519
544
  </div>
520
545
  ` : ''}
521
- </div>
522
546
  `;
523
-
524
- content += '</div></div>';
547
+ if (test.markdownPath) {
548
+ content += `
549
+ <div class="column">
550
+ <button
551
+ onclick="window.open('${test.markdownPath}', '_blank')"
552
+ class="button is-primary is-fullwidth mt-3">
553
+ <span class="icon"><i class="fa-solid fa-file-lines"></i></span>
554
+ <span class="has-text-white pl-2">Open Markdown</span>
555
+ </button>
556
+ </div>
557
+ `;
558
+ }
559
+ content += '</div></div></div>';
525
560
  return content;
526
561
  }
527
562
 
@@ -1237,6 +1272,7 @@
1237
1272
  }
1238
1273
  };
1239
1274
  window.getAdjustedBaseUrl = Utils.getAdjustedBaseUrl;
1275
+ window.copyFilePath = Utils.copyFilePath
1240
1276
  window.openHistory = () => {
1241
1277
  historyManager.setCurrentHistory(testDetailsManager.testHistoriesMap, testDetailsManager.testHistoryTitle);
1242
1278
  historyManager.openHistory();
@@ -222,6 +222,14 @@
222
222
  <span class="sidebar-menu-text">Tests</span>
223
223
  </a>
224
224
  </li>
225
+ <li class="sidebar-menu-item">
226
+ <a class="sidebar-menu-link" data-section="analytics">
227
+ <span class="icon">
228
+ <i class="fa fa-chart-line"></i>
229
+ </span>
230
+ <span class="sidebar-menu-text">Analytics</span>
231
+ </a>
232
+ </li>
225
233
  </ul>
226
234
  <a class="theme" data-theme-status="{{preferredTheme}}" id="toggle-theme">
227
235
  <span class="icon">
@@ -113,49 +113,38 @@
113
113
  <script>
114
114
  const overallChart = document.getElementById('testChart');
115
115
  new Chart(overallChart, {
116
- type: "polarArea",
116
+ type: '{{ chartType }}',
117
117
  data: {
118
- labels: ['Passed', 'Failed', 'Skipped', 'Flaky'],
118
+ labels: ['Passed', 'Failed', 'Skipped', 'Flaky', 'Retry'],
119
119
  datasets: [{
120
120
  data: [{{ passCount }}, {{ failCount }}, {{ skipCount }}, {{ flakyCount }}, {{ retryCount }}],
121
121
  backgroundColor: ['#28a745', '#ff6685', '#66d1ff', '#ffb70f', '#69748c']}]
122
122
  },
123
123
  options: {
124
- scales: {
125
- r: {
126
- ticks: {
127
- display: false
128
- },
129
- grid: {
130
- color: '#e0e0e0'
131
- }
132
- }
133
- },
134
- responsive: true,
135
- maintainAspectRatio: false,
136
- borderJoinStyle: 'bevel',
137
- plugins: {
138
- legend: {
139
- position: 'bottom',
140
- labels: {
141
- filter: function (legendItem, chartData) {
142
- const value = chartData.datasets[0].data[legendItem.index];
143
- return value !== 0;
124
+ responsive: true,
125
+ maintainAspectRatio: false,
126
+ plugins: {
127
+ legend: {
128
+ position: 'bottom',
129
+ labels: {
130
+ filter: function (legendItem, chartData) {
131
+ const value = chartData.datasets[0].data[legendItem.index];
132
+ return value !== 0;
133
+ }
144
134
  }
145
- }
146
- },
147
- tooltip: {
148
- callbacks: {
149
- label: function (tooltipItem) {
150
- const total = tooltipItem.dataset.data.reduce((a, b) => a + b, 0);
151
- const value = tooltipItem.raw;
152
- const percentage = ((value / total) * 100).toFixed(2);
153
- return `${tooltipItem.label}: ${value} tests (${percentage}%)`;
135
+ },
136
+ tooltip: {
137
+ callbacks: {
138
+ label: function (tooltipItem) {
139
+ const total = tooltipItem.dataset.data.reduce((a, b) => a + b, 0);
140
+ const value = tooltipItem.raw;
141
+ const percentage = ((value / total) * 100).toFixed(2);
142
+ return `${tooltipItem.label}: ${value} tests (${percentage}%)`;
143
+ }
154
144
  }
155
145
  }
156
146
  }
157
147
  }
158
- }
159
148
  });
160
149
 
161
150
  const projectChart = document.getElementById('projectChart');
@@ -173,7 +162,7 @@
173
162
  }
174
163
  const backgroundColors = totalTests.map(() => generateRandomColor());
175
164
  new Chart(projectChart, {
176
- type: 'doughnut',
165
+ type: '{{ chartType }}',
177
166
  data: {
178
167
  labels: projectNames,
179
168
  datasets: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ortoni-report",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Playwright Report By LetCode with Koushik",
5
5
  "scripts": {
6
6
  "tsc": "tsc",
@@ -35,14 +35,15 @@
35
35
  },
36
36
  "homepage": "https://github.com/ortoniKC/ortoni-report#readme",
37
37
  "devDependencies": {
38
- "@playwright/test": "^1.49.0",
39
38
  "@types/express": "^5.0.0",
40
39
  "@types/node": "^22.0.2",
41
40
  "@types/sqlite3": "^3.1.11",
42
41
  "tsup": "^8.4.0",
43
- "typescript": "^4.9.4"
42
+ "typescript": "^4.9.4",
43
+ "marked": "^16.0.0"
44
44
  },
45
45
  "peerDependencies": {
46
+ "@playwright/test": "<2.0.0",
46
47
  "ansi-to-html": "^0.7.2",
47
48
  "commander": "^12.1.0",
48
49
  "express": "^4.21.1",
@@ -53,4 +54,4 @@
53
54
  "main": "dist/ortoni-report.js",
54
55
  "module": "dist/ortoni-report.mjs",
55
56
  "types": "dist/ortoni-report.d.ts"
56
- }
57
+ }
package/readme.md CHANGED
@@ -12,41 +12,54 @@ A comprehensive and visually appealing HTML report generator tailored for Playwr
12
12
 
13
13
  ### 1. **Organization & Navigation**
14
14
 
15
- - **Sidebar Navigation**: Offering a more structured and intuitive navigation experience.
16
- - **Sidebar Sections**:
17
- - **Dashboard**: View overall test statistics and summaries.
18
- - **Tests**: Browse detailed test results, including logs, screenshots, and errors.
19
- - **Hierarchical Grouping**: Tests are structured by filename, suite, and project, providing an organized overview.
20
- - **Test History & Detailed Breakdown**: Support for displaying up to 10 recent executions, categorized by suite and project for easy navigation.
21
- - **Integration and Configuration**: Easy integration with Playwright using TypeScript/JavaScript, with configurable preferences.
22
- - **Advanced Filtering**: Filters for project, tags, and status, with the ability to reset for a full view.
15
+ - **Sidebar Navigation**: Enjoy a clean and structured layout for seamless navigation.
16
+ - **Sections**:
17
+ - **Dashboard**: High-level overview of test analytics and trends.
18
+ - **Tests**: Dive into individual test details including logs, screenshots, and errors.
19
+ - **Analytics**: Track overall execution metrics, trends, and flaky/slow test insights.
20
+ - **Hierarchical Grouping**: Tests are organized by filename, suite, and project for better traceability.
21
+ - **Test History View**: Access up to 10 recent executions, categorized by suite and project.
22
+ - **Configurable Integration**: Easy setup with Playwright using TypeScript/JavaScript, along with customizable preferences.
23
+ - **Advanced Filtering**: Filter by project, tags, and status — with a reset option for full visibility.
23
24
 
24
25
  ### 2. **Detailed Reporting**
25
26
 
26
- - **Comprehensive Test Details**: Status, duration, tags, errors, logs, screenshots, videos, and trace data.
27
- - **Test Attachments**: Screenshots, videos, trace viewer, steps, error stack trace, and console logs.
28
- - **Selected Status Display**: The UI highlights the active status filter for clarity.
27
+ - **Comprehensive Test Data**: Includes status, duration, tags, logs, errors, screenshots, videos, and trace viewer.
28
+ - **Native Trace Viewer**: Directly open the trace viewer within the reporter.
29
29
 
30
30
  ### 3. **Visualization & Insights**
31
31
 
32
- - **Summary Statistics**: Total tests and distribution of passed, failed, skipped, and flaky tests with success rates.
33
- - **Chart Visualizations**: Plotarea chart for overall status, doghnut for projects and bar charts for project-specific comparisons.
34
- - **All-New Colorful UI**: A vibrant, redesigned interface with better contrast and readability.
32
+ - **Test Analytics Dashboard** 🌟 **(New!)**
33
+
34
+ - Summary of total test runs, passed/failed counts, pass rate, and average duration.
35
+ - **Trends Over Time**: Line chart showing test results across the last 30 runs.
36
+ - **Top Flaky Tests**: Identify unstable tests quickly.
37
+ - **Slowest Tests**: View tests with highest average durations.
38
+
39
+ - **Chart Visualizations**:
40
+
41
+ - Pie or doughnut charts for test summary and per-project breakdowns **(Improved!)**
42
+ - Bar charts for project-specific comparisons.
43
+ - **Line Chart for Trends**: Visualize execution status progression over time.
44
+
45
+ - **Colorful UI**: Redesigned with vibrant, high-contrast visuals for improved readability and engagement.
35
46
 
36
47
  ### 4. **Customization & Personalization**
37
48
 
38
- - **New Color Scheme**: Supports both **light and dark themes**, ensuring a comfortable viewing experience.
39
- - **Add Your Logo**: Configurable logo for brand personalization.
40
- - **Flexibility with Attachments**: Choose Base64 or file paths for screenshots.
41
- - **Custom Report Paths**: Set custom filenames and folder paths for reports.
49
+ - **Theme Support**: Switch between **light** and **dark** themes for a comfortable viewing experience.
50
+ - **Custom Branding**: Add your company or project logo for a branded look.
51
+ - **Flexible Attachments**: Choose between Base64 or file path formats for media files.
52
+ - **Custom Paths**: Define report filenames and output folders as needed.
42
53
 
43
54
  ### 5. **User Experience & Usability**
44
55
 
45
- - **Advanced Search and Reset**: Search tests with keywords or criteria, with reset options.
46
- - **Hide Skipped Tests by Default**: Simplifies view by hiding skipped tests initially.
47
- - **Share Reports**: Self-contained reports for easy sharing and review.
48
- - **Comprehensive Filters**: Apply multiple filters simultaneously for focused insights.
49
- - **Meta**: Add user meta information to the reporter
56
+ - **Search & Reset**: Quickly search by keyword or status, with easy reset controls.
57
+ - **Skip Management**: Skipped tests are hidden by default to declutter views.
58
+ - **Self-Contained Reports**: Easily share and review offline-friendly reports.
59
+ - **Multi-Filters**: Combine filters for targeted test analysis.
60
+ - **Meta Information**: Add custom user or environment metadata to reports.
61
+ - **CLI**: Open the reporter anytime using the builin CLI
62
+ - **Open Markdown**: View markdown as HTML - Copy and use it in your AI prompt
50
63
 
51
64
  ---
52
65
 
@@ -67,6 +80,7 @@ Set up **Ortoni Report** in your Playwright configuration file with the followin
67
80
  ```typescript
68
81
  import { defineConfig } from "@playwright/test";
69
82
  import { OrtoniReportConfig } from "ortoni-report";
83
+ import * as os from "os";
70
84
 
71
85
  const reportConfig: OrtoniReportConfig = {
72
86
  open: process.env.CI ? "never" : "always", // default to never
@@ -76,18 +90,19 @@ const reportConfig: OrtoniReportConfig = {
76
90
  title: "Ortoni Test Report",
77
91
  showProject: !true,
78
92
  projectName: "Ortoni-Report",
79
- testType: "e2e",
80
- authorName: "Koushik",
93
+ testType: "Functional",
94
+ authorName: os.userInfo().username,
81
95
  base64Image: false,
82
96
  stdIO: false,
83
97
  preferredTheme: "light",
98
+ chartType: "doughnut" | "pie";
84
99
  meta: {
85
100
  project: "Playwright",
86
- version: "3.0.0",
101
+ version: "3",
87
102
  description: "Playwright test report",
88
- testCycle: "1",
89
- release: "1.0.0",
90
- platform: "Windows",
103
+ testCycle: "04121994",
104
+ release: "0.3",
105
+ platform: os.type(),
91
106
  },
92
107
  };
93
108
 
@@ -115,6 +130,7 @@ const reportConfig = {
115
130
  base64Image: false,
116
131
  stdIO: false,
117
132
  preferredTheme: "light",
133
+ chartType: "doughnut" | "pie";
118
134
  meta: {
119
135
  project: "Playwright",
120
136
  version: "3.0.0",
@@ -152,6 +168,7 @@ This command starts a local Express server and serves the generated Ortoni repor
152
168
  ```
153
169
 
154
170
  This will:
171
+
155
172
  - Look for the report file `ortoni-report.html` in the `ortoni-report` folder.
156
173
  - Start the server on port `2004`.
157
174
 
@@ -206,7 +223,8 @@ If you'd like to support this project, you can donate via UPI:
206
223
  Thank you for using **Ortoni Report**! I'm committed to providing you with a superior Playwright testing experience.
207
224
 
208
225
  ---
226
+
209
227
  **Developer & Designer**
210
228
  [Koushik Chatterjee](https://letcode.in/contact)
211
229
 
212
- **LetCode with Koushik**
230
+ **LetCode with Koushik**