ortoni-report 3.0.2 → 3.0.4

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.
@@ -1,105 +1,103 @@
1
- <div> 
2
- <h1 class="title is-3">Analytics</h1>
3
- <div class="columns is-multiline has-text-centered">
4
- {{> summaryCard bg="hsl(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l)) !important"
5
- statusHeader="Total Runs" statusCount=reportAnalyticsData.summary.totalRuns}}
6
- {{> summaryCard bg="hsl(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l)) !important"
7
- statusHeader="Total Tests" statusCount=reportAnalyticsData.summary.totalTests}}
8
- {{> summaryCard bg="hsl(var(--bulma-success-h), var(--bulma-success-s), var(--bulma-success-l)) !important"
9
- status="Passed" statusHeader="Passed" statusCount=reportAnalyticsData.summary.passed}}
10
- {{> summaryCard bg="hsl(var(--bulma-danger-h), var(--bulma-danger-s), var(--bulma-danger-l)) !important"
11
- status="Failed"
12
- statusHeader="Failed" statusCount=reportAnalyticsData.summary.failed}}
13
- {{> summaryCard bg="hsl(var(--bulma-info-h), var(--bulma-info-s), var(--bulma-info-l)) !important"
14
- statusHeader="Pass Rate: %" statusCount=reportAnalyticsData.summary.passRate}}
15
- {{> summaryCard bg="#69748c" statusHeader="Avg Duration (ms)" statusCount=reportAnalyticsData.summary.avgDuration}}
16
- </div>
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>
17
16
 
18
- <section class="box">
19
- <h2 class="title is-4">Trends Over Time</h2>
20
- <canvas id="trendChart" height="100"></canvas>
21
- </section>
17
+ <section class="box">
18
+ <h2 class="title is-4">Trends Over Time</h2>
19
+ <canvas id="trendChart" height="100"></canvas>
20
+ </section>
22
21
 
23
- <section class="box">
24
- <h2 class="title is-4">Top Flaky Tests</h2>
25
- <table class="table is-striped is-fullwidth">
26
- <thead>
27
- <tr>
28
- <th>Test ID</th>
29
- </tr>
30
- </thead>
31
- <tbody>
32
- {{#each reportAnalyticsData.flakyTests}}
33
- <tr>
34
- <td>{{this.test_id}}</td>
35
- </tr>
36
- {{/each}}
37
- </tbody>
38
- </table>
39
- </section>
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>
40
39
 
41
- <section class="box">
42
- <h2 class="title is-4">Slowest Tests</h2>
43
- <table class="table is-striped is-fullwidth">
44
- <thead>
45
- <tr>
46
- <th>Test ID</th>
47
- <th>Avg Duration (ms)</th>
48
- </tr>
49
- </thead>
50
- <tbody>
51
- {{#each reportAnalyticsData.slowTests}}
52
- <tr>
53
- <td>{{this.test_id}}</td>
54
- <td>{{this.avg_duration}}</td>
55
- </tr>
56
- {{/each}}
57
- </tbody>
58
- </table>
59
- </section>
60
- <script>
61
- const ctx = document.getElementById('trendChart').getContext('2d');
62
- const trendChart = new Chart(ctx, {
63
- type: 'line',
64
- data: {
65
- labels: {{{ json chartData.labels }}},
66
- datasets: [
67
- {
68
- label: 'Passed',
69
- data: {{ json chartData.passed }},
70
- borderColor: 'green',
71
- fill: false
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
72
71
  },
73
- {
74
- label: 'Failed',
75
- data: {{ json chartData.failed }},
76
- borderColor: 'red',
77
- fill: false
72
+ {
73
+ label: 'Failed',
74
+ data: {{ json chartData.failed }},
75
+ borderColor: 'red',
76
+ fill: false
78
77
  },
79
- {
80
- label: 'Avg Duration (ms)',
81
- data: {{ json chartData.avgDuration }},
82
- borderColor: 'blue',
83
- fill: false,
84
- yAxisID: 'y1'
78
+ {
79
+ label: 'Avg Duration (ms)',
80
+ data: {{ json chartData.avgDuration }},
81
+ borderColor: 'blue',
82
+ fill: false,
83
+ yAxisID: 'y1'
85
84
  }
86
- ]
85
+ ]
87
86
  },
88
- options: {
89
- responsive: true,
90
- scales: {
91
- y: {
92
- beginAtZero: true,
93
- title: { display: true, text: 'Count' }
94
- },
95
- y1: {
96
- beginAtZero: true,
97
- position: 'right',
98
- title: { display: true, text: 'Duration (ms)' },
99
- grid: { drawOnChartArea: false }
100
- }
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 }
101
99
  }
102
100
  }
101
+ }
103
102
  });
104
- </script>
105
- </div>
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.2" />
4
+ <meta name="description" content="Ortoni Report - V3.0.4" />
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" />
@@ -122,6 +122,21 @@
122
122
  return `${origin}${directoryPath}`;
123
123
  }
124
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
+ });
125
140
  }
126
141
  };
127
142
 
@@ -386,7 +401,12 @@
386
401
  <div class="card-content">
387
402
  <div class="content has-text-centered">
388
403
  <h1 class="title is-4">${test.title}</h1>
389
- <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>
390
410
  </div>
391
411
  </div>
392
412
  <footer class="card-footer">
@@ -417,7 +437,7 @@
417
437
  ${test.projectName ? `
418
438
  <div class="card-footer-item">
419
439
  <div class="is-flex is-align-items-center">
420
- <span class="icon status-icon has-text-link">
440
+ <span class="icon status-icon has-text-info">
421
441
  ${projectIcon}
422
442
  </span>
423
443
  <span> ${test.projectName}</span>
@@ -523,10 +543,20 @@
523
543
  </button>
524
544
  </div>
525
545
  ` : ''}
526
- </div>
527
546
  `;
528
-
529
- 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>';
530
560
  return content;
531
561
  }
532
562
 
@@ -1242,6 +1272,7 @@
1242
1272
  }
1243
1273
  };
1244
1274
  window.getAdjustedBaseUrl = Utils.getAdjustedBaseUrl;
1275
+ window.copyFilePath = Utils.copyFilePath
1245
1276
  window.openHistory = () => {
1246
1277
  historyManager.setCurrentHistory(testDetailsManager.testHistoriesMap, testDetailsManager.testHistoryTitle);
1247
1278
  historyManager.openHistory();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ortoni-report",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
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
@@ -30,12 +30,14 @@ A comprehensive and visually appealing HTML report generator tailored for Playwr
30
30
  ### 3. **Visualization & Insights**
31
31
 
32
32
  - **Test Analytics Dashboard** 🌟 **(New!)**
33
+
33
34
  - Summary of total test runs, passed/failed counts, pass rate, and average duration.
34
35
  - **Trends Over Time**: Line chart showing test results across the last 30 runs.
35
36
  - **Top Flaky Tests**: Identify unstable tests quickly.
36
37
  - **Slowest Tests**: View tests with highest average durations.
37
38
 
38
39
  - **Chart Visualizations**:
40
+
39
41
  - Pie or doughnut charts for test summary and per-project breakdowns **(Improved!)**
40
42
  - Bar charts for project-specific comparisons.
41
43
  - **Line Chart for Trends**: Visualize execution status progression over time.
@@ -57,6 +59,7 @@ A comprehensive and visually appealing HTML report generator tailored for Playwr
57
59
  - **Multi-Filters**: Combine filters for targeted test analysis.
58
60
  - **Meta Information**: Add custom user or environment metadata to reports.
59
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
60
63
 
61
64
  ---
62
65
 
@@ -77,6 +80,7 @@ Set up **Ortoni Report** in your Playwright configuration file with the followin
77
80
  ```typescript
78
81
  import { defineConfig } from "@playwright/test";
79
82
  import { OrtoniReportConfig } from "ortoni-report";
83
+ import * as os from "os";
80
84
 
81
85
  const reportConfig: OrtoniReportConfig = {
82
86
  open: process.env.CI ? "never" : "always", // default to never
@@ -86,19 +90,19 @@ const reportConfig: OrtoniReportConfig = {
86
90
  title: "Ortoni Test Report",
87
91
  showProject: !true,
88
92
  projectName: "Ortoni-Report",
89
- testType: "e2e",
90
- authorName: "Koushik",
93
+ testType: "Functional",
94
+ authorName: os.userInfo().username,
91
95
  base64Image: false,
92
96
  stdIO: false,
93
97
  preferredTheme: "light",
94
98
  chartType: "doughnut" | "pie";
95
99
  meta: {
96
100
  project: "Playwright",
97
- version: "3.0.0",
101
+ version: "3",
98
102
  description: "Playwright test report",
99
- testCycle: "1",
100
- release: "1.0.0",
101
- platform: "Windows",
103
+ testCycle: "04121994",
104
+ release: "0.3",
105
+ platform: os.type(),
102
106
  },
103
107
  };
104
108
 
@@ -164,6 +168,7 @@ This command starts a local Express server and serves the generated Ortoni repor
164
168
  ```
165
169
 
166
170
  This will:
171
+
167
172
  - Look for the report file `ortoni-report.html` in the `ortoni-report` folder.
168
173
  - Start the server on port `2004`.
169
174
 
@@ -218,7 +223,8 @@ If you'd like to support this project, you can donate via UPI:
218
223
  Thank you for using **Ortoni Report**! I'm committed to providing you with a superior Playwright testing experience.
219
224
 
220
225
  ---
226
+
221
227
  **Developer & Designer**
222
228
  [Koushik Chatterjee](https://letcode.in/contact)
223
229
 
224
- **LetCode with Koushik**
230
+ **LetCode with Koushik**