ortoni-report 1.0.7 → 1.0.9

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.
Binary file
@@ -1,10 +1,17 @@
1
1
  import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
2
2
 
3
+ interface ReporterConfig {
4
+ projectName?: string;
5
+ authorName?: string;
6
+ testType?: string;
7
+ }
8
+
3
9
  declare class OrtoniReport implements Reporter {
4
10
  private results;
5
11
  private groupedResults;
6
12
  private suiteName;
7
- constructor();
13
+ private config;
14
+ constructor(config?: ReporterConfig);
8
15
  onBegin(config: FullConfig, suite: Suite): void;
9
16
  onTestBegin(test: TestCase, result: TestResult): void;
10
17
  onTestEnd(test: TestCase, result: TestResult): void;
@@ -34,31 +34,57 @@ __export(ortoni_report_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(ortoni_report_exports);
36
36
  var import_fs = __toESM(require("fs"));
37
- var import_path = __toESM(require("path"));
37
+ var import_path2 = __toESM(require("path"));
38
38
  var import_handlebars = __toESM(require("handlebars"));
39
39
  var import_safe = __toESM(require("colors/safe"));
40
+
41
+ // src/utils/time.ts
42
+ var import_path = __toESM(require("path"));
43
+ function msToTime(duration) {
44
+ const seconds = Math.floor(duration / 1e3 % 60);
45
+ const minutes = Math.floor(duration / (1e3 * 60) % 60);
46
+ 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(" ");
55
+ }
56
+ function normalizeFilePath(filePath) {
57
+ const normalizedPath = import_path.default.normalize(filePath);
58
+ return import_path.default.basename(normalizedPath);
59
+ }
60
+
61
+ // src/ortoni-report.ts
40
62
  var OrtoniReport = class {
41
- constructor() {
63
+ constructor(config = {}) {
42
64
  this.results = [];
65
+ this.config = config;
43
66
  }
44
67
  onBegin(config, suite) {
45
68
  this.results = [];
46
- const screenshotsDir = import_path.default.join(process.cwd(), "screenshots");
47
- if (!import_fs.default.existsSync(screenshotsDir)) {
48
- import_fs.default.mkdirSync(screenshotsDir);
69
+ const screenshotsDir = import_path2.default.resolve(process.cwd(), "screenshots");
70
+ if (import_fs.default.existsSync(screenshotsDir)) {
71
+ import_fs.default.rmSync(screenshotsDir, { recursive: true, force: true });
49
72
  }
73
+ import_fs.default.mkdirSync(screenshotsDir, { recursive: true });
50
74
  }
51
75
  onTestBegin(test, result) {
52
76
  }
53
77
  onTestEnd(test, result) {
54
78
  const testResult = {
79
+ totalDuration: "",
55
80
  projectName: test.titlePath()[1],
56
81
  // Get the project name
57
82
  suite: test.titlePath()[3],
58
83
  // Adjust the index based on your suite hierarchy
59
84
  title: test.title,
60
85
  status: result.status,
61
- duration: result.duration,
86
+ flaky: test.outcome(),
87
+ duration: msToTime(result.duration),
62
88
  errors: result.errors.map((e) => import_safe.default.strip(e.message || e.toString())),
63
89
  steps: result.steps.map((step) => ({
64
90
  title: step.title,
@@ -68,24 +94,25 @@ var OrtoniReport = class {
68
94
  })),
69
95
  logs: import_safe.default.strip(result.stdout.concat(result.stderr).map((log) => log).join("\n")),
70
96
  screenshotPath: null,
71
- filePath: test.titlePath()[2]
97
+ filePath: normalizeFilePath(test.titlePath()[2])
72
98
  };
73
99
  if (result.attachments) {
74
- const screenshotsDir = import_path.default.join(process.cwd(), "screenshots\\" + test.id);
100
+ const screenshotsDir = import_path2.default.resolve(process.cwd(), "screenshots", test.id);
75
101
  if (!import_fs.default.existsSync(screenshotsDir)) {
76
- import_fs.default.mkdirSync(screenshotsDir);
102
+ import_fs.default.mkdirSync(screenshotsDir, { recursive: true });
77
103
  }
78
104
  const screenshot = result.attachments.find((attachment) => attachment.name === "screenshot");
79
105
  if (screenshot && screenshot.path) {
80
106
  const screenshotContent = import_fs.default.readFileSync(screenshot.path, "base64");
81
- const screenshotFileName = `screenshots/${test.id}/${import_path.default.basename(screenshot.path)}`;
82
- import_fs.default.writeFileSync(import_path.default.join(process.cwd(), screenshotFileName), screenshotContent, "base64");
107
+ const screenshotFileName = import_path2.default.join("screenshots", test.id, import_path2.default.basename(screenshot.path));
108
+ import_fs.default.writeFileSync(import_path2.default.resolve(process.cwd(), screenshotFileName), screenshotContent, "base64");
83
109
  testResult.screenshotPath = screenshotFileName;
84
110
  }
85
111
  }
86
112
  this.results.push(testResult);
87
113
  }
88
114
  onEnd(result) {
115
+ this.results[0].totalDuration = msToTime(result.duration);
89
116
  this.groupedResults = this.results.reduce((acc, result2, index) => {
90
117
  const filePath = result2.filePath;
91
118
  const suiteName = result2.suite;
@@ -105,26 +132,30 @@ var OrtoniReport = class {
105
132
  import_handlebars.default.registerHelper("json", function(context) {
106
133
  return safeStringify(context);
107
134
  });
108
- import_handlebars.default.registerHelper("splitSuiteName", function(suiteName) {
109
- return suiteName.split(" - ");
110
- });
111
135
  const html = this.generateHTML();
112
- const outputPath = import_path.default.join(process.cwd(), "ortoni-report.html");
136
+ const outputPath = import_path2.default.resolve(process.cwd(), "ortoni-report.html");
113
137
  import_fs.default.writeFileSync(outputPath, html);
114
138
  console.log(`Ortoni HTML report generated at ${outputPath}`);
115
139
  }
116
140
  generateHTML() {
117
- const templateSource = import_fs.default.readFileSync(import_path.default.join(process.cwd(), "report-template.hbs"), "utf-8");
141
+ const templateSource = import_fs.default.readFileSync(import_path2.default.resolve(__dirname, "report-template.hbs"), "utf-8");
118
142
  const template = import_handlebars.default.compile(templateSource);
119
143
  const data = {
144
+ totalDuration: this.results[0].totalDuration,
120
145
  suiteName: this.suiteName,
121
146
  results: this.results,
122
147
  passCount: this.results.filter((r) => r.status === "passed").length,
123
148
  failCount: this.results.filter((r) => r.status === "failed").length,
124
149
  skipCount: this.results.filter((r) => r.status === "skipped").length,
125
- retryCount: this.results.filter((r) => r.status === "retry").length,
150
+ flakyCount: this.results.filter((r) => r.flaky === "flaky").length,
126
151
  totalCount: this.results.length,
127
- groupedResults: this.groupedResults
152
+ groupedResults: this.groupedResults,
153
+ projectName: this.config.projectName,
154
+ // Include project name
155
+ authorName: this.config.authorName,
156
+ // Include author name
157
+ testType: this.config.testType
158
+ // Include test type
128
159
  };
129
160
  return template(data);
130
161
  }
@@ -1,30 +1,56 @@
1
1
  // src/ortoni-report.ts
2
2
  import fs from "fs";
3
- import path from "path";
3
+ import path2 from "path";
4
4
  import Handlebars from "handlebars";
5
5
  import colors from "colors/safe";
6
+
7
+ // src/utils/time.ts
8
+ import path from "path";
9
+ function msToTime(duration) {
10
+ const seconds = Math.floor(duration / 1e3 % 60);
11
+ const minutes = Math.floor(duration / (1e3 * 60) % 60);
12
+ 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(" ");
21
+ }
22
+ function normalizeFilePath(filePath) {
23
+ const normalizedPath = path.normalize(filePath);
24
+ return path.basename(normalizedPath);
25
+ }
26
+
27
+ // src/ortoni-report.ts
6
28
  var OrtoniReport = class {
7
- constructor() {
29
+ constructor(config = {}) {
8
30
  this.results = [];
31
+ this.config = config;
9
32
  }
10
33
  onBegin(config, suite) {
11
34
  this.results = [];
12
- const screenshotsDir = path.join(process.cwd(), "screenshots");
13
- if (!fs.existsSync(screenshotsDir)) {
14
- fs.mkdirSync(screenshotsDir);
35
+ const screenshotsDir = path2.resolve(process.cwd(), "screenshots");
36
+ if (fs.existsSync(screenshotsDir)) {
37
+ fs.rmSync(screenshotsDir, { recursive: true, force: true });
15
38
  }
39
+ fs.mkdirSync(screenshotsDir, { recursive: true });
16
40
  }
17
41
  onTestBegin(test, result) {
18
42
  }
19
43
  onTestEnd(test, result) {
20
44
  const testResult = {
45
+ totalDuration: "",
21
46
  projectName: test.titlePath()[1],
22
47
  // Get the project name
23
48
  suite: test.titlePath()[3],
24
49
  // Adjust the index based on your suite hierarchy
25
50
  title: test.title,
26
51
  status: result.status,
27
- duration: result.duration,
52
+ flaky: test.outcome(),
53
+ duration: msToTime(result.duration),
28
54
  errors: result.errors.map((e) => colors.strip(e.message || e.toString())),
29
55
  steps: result.steps.map((step) => ({
30
56
  title: step.title,
@@ -34,24 +60,25 @@ var OrtoniReport = class {
34
60
  })),
35
61
  logs: colors.strip(result.stdout.concat(result.stderr).map((log) => log).join("\n")),
36
62
  screenshotPath: null,
37
- filePath: test.titlePath()[2]
63
+ filePath: normalizeFilePath(test.titlePath()[2])
38
64
  };
39
65
  if (result.attachments) {
40
- const screenshotsDir = path.join(process.cwd(), "screenshots\\" + test.id);
66
+ const screenshotsDir = path2.resolve(process.cwd(), "screenshots", test.id);
41
67
  if (!fs.existsSync(screenshotsDir)) {
42
- fs.mkdirSync(screenshotsDir);
68
+ fs.mkdirSync(screenshotsDir, { recursive: true });
43
69
  }
44
70
  const screenshot = result.attachments.find((attachment) => attachment.name === "screenshot");
45
71
  if (screenshot && screenshot.path) {
46
72
  const screenshotContent = fs.readFileSync(screenshot.path, "base64");
47
- const screenshotFileName = `screenshots/${test.id}/${path.basename(screenshot.path)}`;
48
- fs.writeFileSync(path.join(process.cwd(), screenshotFileName), screenshotContent, "base64");
73
+ const screenshotFileName = path2.join("screenshots", test.id, path2.basename(screenshot.path));
74
+ fs.writeFileSync(path2.resolve(process.cwd(), screenshotFileName), screenshotContent, "base64");
49
75
  testResult.screenshotPath = screenshotFileName;
50
76
  }
51
77
  }
52
78
  this.results.push(testResult);
53
79
  }
54
80
  onEnd(result) {
81
+ this.results[0].totalDuration = msToTime(result.duration);
55
82
  this.groupedResults = this.results.reduce((acc, result2, index) => {
56
83
  const filePath = result2.filePath;
57
84
  const suiteName = result2.suite;
@@ -71,26 +98,30 @@ var OrtoniReport = class {
71
98
  Handlebars.registerHelper("json", function(context) {
72
99
  return safeStringify(context);
73
100
  });
74
- Handlebars.registerHelper("splitSuiteName", function(suiteName) {
75
- return suiteName.split(" - ");
76
- });
77
101
  const html = this.generateHTML();
78
- const outputPath = path.join(process.cwd(), "ortoni-report.html");
102
+ const outputPath = path2.resolve(process.cwd(), "ortoni-report.html");
79
103
  fs.writeFileSync(outputPath, html);
80
104
  console.log(`Ortoni HTML report generated at ${outputPath}`);
81
105
  }
82
106
  generateHTML() {
83
- const templateSource = fs.readFileSync(path.join(process.cwd(), "report-template.hbs"), "utf-8");
107
+ const templateSource = fs.readFileSync(path2.resolve(__dirname, "report-template.hbs"), "utf-8");
84
108
  const template = Handlebars.compile(templateSource);
85
109
  const data = {
110
+ totalDuration: this.results[0].totalDuration,
86
111
  suiteName: this.suiteName,
87
112
  results: this.results,
88
113
  passCount: this.results.filter((r) => r.status === "passed").length,
89
114
  failCount: this.results.filter((r) => r.status === "failed").length,
90
115
  skipCount: this.results.filter((r) => r.status === "skipped").length,
91
- retryCount: this.results.filter((r) => r.status === "retry").length,
116
+ flakyCount: this.results.filter((r) => r.flaky === "flaky").length,
92
117
  totalCount: this.results.length,
93
- groupedResults: this.groupedResults
118
+ groupedResults: this.groupedResults,
119
+ projectName: this.config.projectName,
120
+ // Include project name
121
+ authorName: this.config.authorName,
122
+ // Include author name
123
+ testType: this.config.testType
124
+ // Include test type
94
125
  };
95
126
  return template(data);
96
127
  }
@@ -5,8 +5,9 @@
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
7
  <title>Playwright Test Report</title>
8
- <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.css">
8
+ <link rel="icon" href="node_modules/ortoni-report/dist/icon/32.png" type="image/x-icon">
9
+ <link rel="stylesheet" href="node_modules/ortoni-report/dist/css/pico.css">
10
+ {{!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.css"> --}}
10
11
  <style>
11
12
  main.container {
12
13
  display: grid;
@@ -24,27 +25,31 @@
24
25
  justify-content: space-evenly;
25
26
  }
26
27
 
28
+ .highlight {
29
+ background-color: var(--pico-primary-background)
30
+ }
31
+
27
32
  .text-success {
28
33
  color: #28a745;
29
34
  }
30
35
 
31
- .text-danger {
36
+ .text-failure {
32
37
  color: #dc3545;
33
38
  }
34
39
 
40
+ .text-skip {
41
+ color: #d5d4a1;
42
+ }
43
+
44
+ .text-flaky {
45
+ color: #d5d4a1;
46
+ }
47
+
35
48
  .sidebar {
36
49
  border-right: 1px solid #ddd;
37
50
  padding-right: 10px;
38
51
  }
39
52
 
40
- .card {
41
- padding: 1rem;
42
- border: 1px solid #ddd;
43
- border-radius: 0.5rem;
44
- background-color: #fff;
45
- box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
46
- }
47
-
48
53
  pre {
49
54
  background-color: #f8f9fa;
50
55
  padding: 1rem;
@@ -62,9 +67,11 @@
62
67
  <body>
63
68
  <header class="container">
64
69
  <div class="header">
70
+ {{!-- Custom Project Name --}}
65
71
  <div>
66
- <h1>Playwright Test Report</h1>
72
+ {{#if projectName}}<h1>{{projectName}}</h1>{{/if}}
67
73
  </div>
74
+ {{!-- Dummy for now --}}
68
75
  <div>
69
76
  <form role="search">
70
77
  <input name="search" type="search" placeholder="Search" />
@@ -74,6 +81,7 @@
74
81
  </div>
75
82
  </header>
76
83
  <main class="container">
84
+ {{!-- Test Scripts --}}
77
85
  <aside class="sidebar">
78
86
  <h2>Tests</h2>
79
87
  <div class="">
@@ -104,15 +112,13 @@
104
112
  {{/each}}
105
113
  </div>
106
114
  </aside>
107
-
108
-
109
-
110
115
  <section>
116
+ {{!-- Overall summar --}}
111
117
  <div id="summary">
112
118
  <section class="grid">
113
119
  <div>
114
120
  <article>
115
- <header>Total Tests</header>
121
+ <header>All Tests</header>
116
122
  <p>{{totalCount}}</p>
117
123
  </article>
118
124
  </div>
@@ -125,7 +131,7 @@
125
131
  <div>
126
132
  <article>
127
133
  <header>Failed</header>
128
- <p class="text-danger">{{failCount}}</p>
134
+ <p class="text-failure">{{failCount}}</p>
129
135
  </article>
130
136
  </div>
131
137
  </section>
@@ -133,24 +139,34 @@
133
139
  <div>
134
140
  <article>
135
141
  <header>Skipped</header>
136
- <p>{{skipCount}}</p>
142
+ <p class="text-skip">{{skipCount}}</p>
137
143
  </article>
138
144
  </div>
139
145
  <div>
140
146
  <article>
141
- <header>Retry</header>
142
- <p class="text-success">{{retryCount}}</p>
147
+ <header>Flaky</header>
148
+ <p class="text-flaky">{{flakyCount}}</p>
143
149
  </article>
144
150
  </div>
145
151
  </section>
152
+ {{!-- Suite details with chart --}}
146
153
  <section>
147
- <h2>Test Results</h2>
148
- <div class="chart-container">
149
- <canvas id="testChart"></canvas>
150
- </div>
154
+ <article>
155
+ <header>Suite</header>
156
+ <div class="grid">
157
+ <div>
158
+ {{#if authorName}}<h4>Author: {{authorName}}</h4>{{/if}}
159
+ {{#if testType}}<h4>Test Type: {{testType}}</h4>{{/if}}
160
+ {{#if totalDuration}}<h4>Duration: {{totalDuration}}</h4>{{/if}}
161
+ </div>
162
+ <div class="chart-container">
163
+ <canvas id="testChart"></canvas>
164
+ </div>
165
+ </div>
166
+ </article>
151
167
  </section>
152
168
  </div>
153
-
169
+ {{!-- Test details --}}
154
170
  <div id="testDetails" style="display: none;">
155
171
  <!-- Back button should be outside the dynamic content -->
156
172
  <button class="back-button" onclick="showSummary()">Back to Summary</button>
@@ -161,16 +177,36 @@
161
177
 
162
178
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
163
179
  <script>
180
+ function escapeHtml(unsafe) {
181
+ return unsafe.replace(/[&<"']/g, function (match) {
182
+ const escapeMap = {
183
+ '&': '&amp;',
184
+ '<': '&lt;',
185
+ '>': '&gt;',
186
+ '"': '&quot;',
187
+ "'": '&#039;'
188
+ };
189
+ return escapeMap[match];
190
+ });
191
+ }
192
+
164
193
  document.addEventListener('DOMContentLoaded', () => {
165
- const testData = {{{ json results }}};
194
+ const testData = {{{ json results }}};
166
195
  const testDetails = document.getElementById('testDetails');
167
196
  const summary = document.getElementById('summary');
168
197
  const backButton = document.querySelector('.back-button');
198
+ const testItems = document.querySelectorAll('[data-test-id]');
199
+ const searchInput = document.querySelector('input[name="search"]');
200
+ const searchForm = document.querySelector('form[role="search"]');
169
201
 
170
202
  function showSummary() {
171
203
  summary.style.display = 'block';
172
204
  testDetails.style.display = 'none';
173
205
  backButton.style.display = 'none';
206
+ clearHighlights();
207
+ }
208
+ function clearHighlights() {
209
+ testItems.forEach(item => item.classList.remove('highlight'));
174
210
  }
175
211
 
176
212
  window.showSummary = showSummary;
@@ -181,38 +217,71 @@
181
217
  backButton.style.display = 'block';
182
218
  testDetails.innerHTML = `
183
219
  <button class="back-button" style="display: block" onclick="showSummary()">Back to Summary</button>
184
- <h2>${test.title}</h2>
220
+ <h3>${test.title}</h3>
185
221
  <div class="grid">
186
222
  <div>
187
- <h3>Status</h3>
188
- <p class="${test.status === 'passed' ? 'text-success' : 'text-danger'}">${test.status}</p>
189
- <h3>Duration</h3>
190
- <p>${test.duration}ms</p>
191
- ${test.errors.length ? `
192
- <h3>Errors</h3>
193
- <pre>${test.errors.join('\n')}</pre>
194
- ` : ''}
223
+ <h4>Status</h4>
224
+ <p class="${test.status === 'passed' ? 'text-success' : 'text-failure'}">${test.status.toUpperCase()}</p>
225
+ ${test.duration != '0s' ? `
226
+ <h4>Duration</h4>
227
+ <p>${test.duration}</p>` : ""}
195
228
  </div>
196
229
  <div>
197
230
  ${test.screenshotPath ? `
198
- <h3>Screenshot</h3>
231
+ <h4>Screenshot</h4>
199
232
  <img src="${test.screenshotPath}" alt="Screenshot">
200
233
  ` : ''}
201
- ${test.logs ? `
202
- <h3>Logs</h3>
203
- <pre>${test.logs}</pre>
204
- ` : ''}
205
234
  </div>
206
235
  </div>
207
- `;
236
+ <div>
237
+ ${test.errors.length ? `
238
+ <h4>Errors</h4>
239
+ <pre>${escapeHtml(test.errors.join('\n'))}</pre>
240
+ ` : ''}
241
+ </div>
242
+ <div>
243
+ ${test.logs ? `
244
+ <h4>Logs</h4>
245
+ <pre>${escapeHtml(test.logs)}</pre>
246
+ ` : ''}
247
+ </div>
248
+ `;
249
+ }
250
+
251
+ function searchTests(query) {
252
+ const lowerCaseQuery = query.toLowerCase();
253
+ if (lowerCaseQuery === '') {
254
+ testItems.forEach(item => {
255
+ item.style.display = 'block';
256
+ });
257
+ } else {
258
+ testItems.forEach(item => {
259
+ const title = item.textContent.toLowerCase();
260
+ if (title.includes(lowerCaseQuery)) {
261
+ item.style.display = 'block';
262
+ } else {
263
+ item.style.display = 'none';
264
+ }
265
+ });
266
+ }
208
267
  }
209
268
 
210
- const testItems = document.querySelectorAll('[data-test-id]');
269
+ searchForm.addEventListener('submit', event => {
270
+ event.preventDefault();
271
+ searchTests(searchInput.value);
272
+ });
273
+ searchInput.addEventListener('input', () => {
274
+ searchTests(searchInput.value);
275
+ });
276
+
277
+
211
278
  testItems.forEach(item => {
212
279
  item.addEventListener('click', () => {
213
280
  const testId = item.getAttribute('data-test-id');
214
281
  const test = testData[testId];
215
282
  displayTestDetails(test);
283
+ clearHighlights();
284
+ item.classList.add('highlight');
216
285
  });
217
286
  });
218
287
 
@@ -223,23 +292,15 @@
223
292
  labels: ['Passed', 'Failed', 'Skipped'],
224
293
  datasets: [{
225
294
  data: [{{ passCount }}, {{ failCount }}, {{ skipCount }}],
226
- backgroundColor: ['#28a745', '#dc3545', '#f0f662']
295
+ backgroundColor: ['#28a745', '#dc3545', '#d5d4a1']
227
296
  }]
228
297
  },
229
298
  options: {
230
299
  responsive: true,
231
300
  maintainAspectRatio: false,
232
301
  plugins: {
233
- title: {
234
- display: true,
235
- text: 'Overall',
236
- font: {
237
- size: 18,
238
- weight: 'bold'
239
- }
240
- },
241
302
  legend: {
242
- position: 'right'
303
+ position: 'bottom'
243
304
  }
244
305
  }
245
306
  }
package/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "ortoni-report",
3
- "version": "1.0.7",
4
- "description": "Playwright Report By LetCode Koushik",
3
+ "version": "1.0.9",
4
+ "description": "Playwright Report By LetCode with Koushik",
5
5
  "scripts": {
6
+ "test": "npx playwright test",
6
7
  "build": "tsup",
7
8
  "release": "npm publish",
8
9
  "lint": "tsc"
9
10
  },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "CHANGELOG.md"
15
+ ],
10
16
  "repository": {
11
17
  "type": "git",
12
- "url": "git+https://github.com/ortoniKC/letcode-pw-report.git"
18
+ "url": "git+https://github.com/ortoniKC/ortoni-report"
13
19
  },
14
20
  "keywords": [
15
21
  "playwright report",
@@ -19,20 +25,21 @@
19
25
  "ortoni"
20
26
  ],
21
27
  "author": "Koushik Chatterjee (LetCode with Koushik)",
22
- "license": "ISC",
28
+ "license": "GPL-3.0-only",
23
29
  "bugs": {
24
- "url": "https://github.com/ortoniKC/letcode-pw-report/issues"
30
+ "url": "https://github.com/ortoniKC/ortoni-report/issues"
25
31
  },
26
- "homepage": "https://github.com/ortoniKC/letcode-pw-report#readme",
27
- "dependencies": {
28
- "hiq": "^4.2.3",
32
+ "homepage": "https://github.com/ortoniKC/ortoni-report#readme",
33
+ "dependencies": {
29
34
  "colors": "^1.4.0",
30
- "handlebars": "^4.7.8"
35
+ "handlebars": "^4.7.8",
36
+ "hiq": "^4.2.3",
37
+ "rimraf": "^5.0.7"
31
38
  },
32
39
  "devDependencies": {
40
+ "@changesets/cli": "^2.26.0",
33
41
  "@playwright/test": "^1.44.1",
34
42
  "@types/node": "^20.14.2",
35
- "@changesets/cli": "^2.26.0",
36
43
  "tsup": "^6.5.0",
37
44
  "typescript": "^4.9.4"
38
45
  },