@arghajit/dummy 0.1.0

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.
Files changed (33) hide show
  1. package/README.md +259 -0
  2. package/dist/index.d.ts +5 -0
  3. package/dist/index.js +26 -0
  4. package/dist/lib/report-types.d.ts +8 -0
  5. package/dist/lib/report-types.js +2 -0
  6. package/dist/playwright-pulse-reporter.d.ts +26 -0
  7. package/dist/playwright-pulse-reporter.js +304 -0
  8. package/dist/reporter/attachment-utils.d.ts +10 -0
  9. package/dist/reporter/attachment-utils.js +192 -0
  10. package/dist/reporter/index.d.ts +5 -0
  11. package/dist/reporter/index.js +9 -0
  12. package/dist/reporter/lib/report-types.d.ts +8 -0
  13. package/dist/reporter/lib/report-types.js +2 -0
  14. package/dist/reporter/playwright-pulse-reporter.d.ts +27 -0
  15. package/dist/reporter/playwright-pulse-reporter.js +454 -0
  16. package/dist/reporter/reporter/playwright-pulse-reporter.d.ts +1 -0
  17. package/dist/reporter/reporter/playwright-pulse-reporter.js +398 -0
  18. package/dist/reporter/types/index.d.ts +52 -0
  19. package/dist/reporter/types/index.js +2 -0
  20. package/dist/types/index.d.ts +65 -0
  21. package/dist/types/index.js +2 -0
  22. package/package.json +73 -0
  23. package/screenshots/127-0-0-1-5500-pulse-report-output-playwright-pulse-static-report-html-i-Phone-14-Pro-Max-1.png +0 -0
  24. package/screenshots/127-0-0-1-5500-pulse-report-output-playwright-pulse-static-report-html-i-Phone-14-Pro-Max.png +0 -0
  25. package/screenshots/Email-report.jpg +0 -0
  26. package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html-1.png +0 -0
  27. package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html-2.png +0 -0
  28. package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html.png +0 -0
  29. package/screenshots/image.png +0 -0
  30. package/scripts/generate-static-report.mjs +2279 -0
  31. package/scripts/generate-trend.mjs +165 -0
  32. package/scripts/merge-pulse-report.js +81 -0
  33. package/scripts/sendReport.js +335 -0
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const fs = __importStar(require("fs/promises"));
46
+ const path = __importStar(require("path"));
47
+ // Helper to convert Playwright status to Pulse status
48
+ const convertStatus = (status) => {
49
+ if (status === "passed")
50
+ return "passed";
51
+ if (status === "failed" || status === "timedOut" || status === "interrupted")
52
+ return "failed";
53
+ return "skipped";
54
+ };
55
+ const TEMP_SHARD_FILE_PREFIX = ".pulse-shard-results-";
56
+ class PlaywrightPulseReporter {
57
+ constructor(options = {}) {
58
+ var _a;
59
+ this.results = []; // Holds results *per process* (main or shard)
60
+ this.baseOutputFile = "playwright-pulse-report.json";
61
+ this.isSharded = false;
62
+ this.shardIndex = undefined;
63
+ this.baseOutputFile = (_a = options.outputFile) !== null && _a !== void 0 ? _a : this.baseOutputFile;
64
+ // Resolve outputDir relative to playwright config directory or cwd if not specified
65
+ // Ensure options.outputDir exists before trying to resolve
66
+ const baseDir = options.outputDir
67
+ ? path.resolve(options.outputDir)
68
+ : process.cwd();
69
+ this.outputDir = baseDir;
70
+ // Note: Final resolution happens in onBegin after config is available
71
+ console.log(`PlaywrightPulseReporter: Initial Output dir configured to ${this.outputDir}`);
72
+ }
73
+ printsToStdio() {
74
+ // Prevent shard processes other than the first from printing duplicate status updates
75
+ // The main process (index undefined) or the first shard (index 0) can print.
76
+ return this.shardIndex === undefined || this.shardIndex === 0;
77
+ }
78
+ onBegin(config, suite) {
79
+ this.config = config;
80
+ this.suite = suite;
81
+ this.runStartTime = Date.now();
82
+ // Determine sharding configuration
83
+ const totalShards = parseInt(
84
+ process.env.PLAYWRIGHT_SHARD_TOTAL || "1",
85
+ 10
86
+ );
87
+ this.isSharded = totalShards > 1;
88
+ if (process.env.PLAYWRIGHT_SHARD_INDEX !== undefined) {
89
+ this.shardIndex = parseInt(process.env.PLAYWRIGHT_SHARD_INDEX, 10);
90
+ }
91
+ // Resolve outputDir relative to playwright config directory if possible, otherwise use cwd
92
+ // This needs the config object, so it's done in onBegin
93
+ const configDir = this.config.rootDir; // Playwright config directory
94
+ // Use outputDir from options if provided and resolve it relative to configDir, otherwise default
95
+ this.outputDir = this.outputDir
96
+ ? path.resolve(configDir, this.outputDir)
97
+ : path.resolve(configDir, "pulse-report"); // Default to 'pulse-report' relative to config
98
+ console.log(
99
+ `PlaywrightPulseReporter: Final Output dir resolved to ${this.outputDir}`
100
+ );
101
+ if (this.shardIndex === undefined) {
102
+ // Main process
103
+ console.log(
104
+ `PlaywrightPulseReporter: Starting test run with ${
105
+ suite.allTests().length
106
+ } tests${
107
+ this.isSharded ? ` across ${totalShards} shards` : ""
108
+ }. Outputting to ${this.outputDir}`
109
+ );
110
+ // Clean up any leftover temp files from previous runs in the main process
111
+ this._cleanupTemporaryFiles().catch((err) =>
112
+ console.error("Pulse Reporter: Error cleaning up temp files:", err)
113
+ );
114
+ } else {
115
+ // Shard process
116
+ console.log(
117
+ `PlaywrightPulseReporter: Shard ${
118
+ this.shardIndex + 1
119
+ }/${totalShards} starting. Outputting temp results to ${
120
+ this.outputDir
121
+ }`
122
+ );
123
+ }
124
+ }
125
+ onTestBegin(test) {
126
+ // Optional: Log test start (maybe only in main process or first shard?)
127
+ // if (this.printsToStdio()) {
128
+ // console.log(`Starting test: ${test.title}`);
129
+ // }
130
+ }
131
+ processStep(step, parentStatus) {
132
+ var _a;
133
+ // If parent failed or was skipped, all child steps inherit that status
134
+ const inherentStatus = parentStatus === "failed" || parentStatus === "skipped"
135
+ ? parentStatus
136
+ : convertStatus(step.error ? "failed" : "passed");
137
+ const duration = step.duration;
138
+ const startTime = new Date(step.startTime);
139
+ // Ensure endTime is calculated correctly, respecting duration might be 0
140
+ const endTime = new Date(startTime.getTime() + Math.max(0, duration));
141
+ return {
142
+ // Create a somewhat unique ID combining title and timing details
143
+ id: `${step.title}-${startTime.toISOString()}-${duration}-${Math.random()
144
+ .toString(16)
145
+ .slice(2)}`, // Add random suffix for uniqueness
146
+ title: step.title,
147
+ status: inherentStatus,
148
+ duration: duration,
149
+ startTime: startTime,
150
+ endTime: endTime,
151
+ errorMessage: (_a = step.error) === null || _a === void 0 ? void 0 : _a.message,
152
+ // We won't embed screenshots directly, maybe paths later
153
+ screenshot: undefined, // Placeholder for potential future enhancement
154
+ };
155
+ }
156
+ onTestEnd(test, result) {
157
+ // This runs in each SHARD PROCESS
158
+ var _a, _b, _c, _d, _e;
159
+ const testStatus = convertStatus(result.status);
160
+ const startTime = new Date(result.startTime);
161
+ const endTime = new Date(startTime.getTime() + result.duration);
162
+ const processAllSteps = (steps, parentTestStatus) => {
163
+ let processed = [];
164
+ for (const step of steps) {
165
+ // Pass the overall test status down, as a step cannot pass if the test failed/skipped
166
+ const processedStep = this.processStep(step, parentTestStatus);
167
+ processed.push(processedStep);
168
+ if (step.steps.length > 0) {
169
+ // Use the processed step's status for its children
170
+ processed = processed.concat(processAllSteps(step.steps, processedStep.status));
171
+ }
172
+ }
173
+ return processed;
174
+ };
175
+ // Extract code snippet if available (experimental, might not be reliable)
176
+ let codeSnippet = undefined;
177
+ try {
178
+ if ((_a = test.location) === null || _a === void 0 ? void 0 : _a.file) {
179
+ // This requires reading the file, which might be slow or have permissions issues
180
+ // const fileContent = fs.readFileSync(test.location.file, 'utf-8');
181
+ // const lines = fileContent.split('\n');
182
+ // // Extract lines around the test definition (this is a rough guess)
183
+ // const startLine = Math.max(0, test.location.line - 5);
184
+ // const endLine = Math.min(lines.length, test.location.line + 10);
185
+ // codeSnippet = lines.slice(startLine, endLine).join('\n');
186
+ codeSnippet = `Test defined at: ${test.location.file}:${test.location.line}:${test.location.column}`; // Simpler placeholder
187
+ }
188
+ }
189
+ catch (e) {
190
+ console.warn(`Pulse Reporter: Could not extract code snippet for ${test.title}`, e);
191
+ }
192
+ const pulseResult = {
193
+ id: test.id ||
194
+ `${test.title}-${startTime.toISOString()}-${Math.random()
195
+ .toString(16)
196
+ .slice(2)}`, // Fallback ID if test.id is missing
197
+ runId: "TBD", // Placeholder, will be set by main process later
198
+ name: test.titlePath().join(" > "), // Use full title path
199
+ suiteName: test.parent.title,
200
+ status: testStatus,
201
+ duration: result.duration,
202
+ startTime: startTime,
203
+ endTime: endTime,
204
+ retries: result.retry,
205
+ // Process steps recursively, passing the final test status
206
+ steps: processAllSteps(result.steps, testStatus),
207
+ errorMessage: (_b = result.error) === null || _b === void 0 ? void 0 : _b.message,
208
+ stackTrace: (_c = result.error) === null || _c === void 0 ? void 0 : _c.stack,
209
+ codeSnippet: codeSnippet,
210
+ // Get relative paths for attachments if possible, otherwise use absolute
211
+ screenshot: (_d = result.attachments.find((a) => a.name === "screenshot")) === null || _d === void 0 ? void 0 : _d.path,
212
+ video: (_e = result.attachments.find((a) => a.name === "video")) === null || _e === void 0 ? void 0 : _e.path,
213
+ tags: test.tags.map((tag) => tag.startsWith("@") ? tag.substring(1) : tag),
214
+ };
215
+ this.results.push(pulseResult);
216
+ // console.log(`Finished test: ${test.title} - ${result.status}`); // Optional: Log test end per shard
217
+ }
218
+ onError(error) {
219
+ var _a;
220
+ // This can run in shards or main process
221
+ console.error(`PlaywrightPulseReporter: Error encountered (Shard: ${(_a = this.shardIndex) !== null && _a !== void 0 ? _a : "Main"}):`, error);
222
+ }
223
+ _writeShardResults() {
224
+ return __awaiter(this, void 0, void 0, function* () {
225
+ // Writes the results gathered in *this specific shard process* to a temp file
226
+ if (this.shardIndex === undefined) {
227
+ console.warn("Pulse Reporter: _writeShardResults called in main process. Skipping.");
228
+ return;
229
+ }
230
+ const tempFilePath = path.join(this.outputDir, `${TEMP_SHARD_FILE_PREFIX}${this.shardIndex}.json`);
231
+ try {
232
+ yield this._ensureDirExists(this.outputDir);
233
+ yield fs.writeFile(tempFilePath, JSON.stringify(this.results, null, 2));
234
+ // console.log(`Pulse Reporter: Shard ${this.shardIndex} results written to ${tempFilePath}`);
235
+ }
236
+ catch (error) {
237
+ console.error(`Pulse Reporter: Shard ${this.shardIndex} failed to write temporary results to ${tempFilePath}`, error);
238
+ }
239
+ });
240
+ }
241
+ _mergeShardResults(finalRunData) {
242
+ return __awaiter(this, void 0, void 0, function* () {
243
+ // Runs *only* in the main process to merge results from all shards
244
+ console.log("Pulse Reporter: Merging results from shards...");
245
+ let allResults = [];
246
+ const totalShards = parseInt(process.env.PLAYWRIGHT_SHARD_TOTAL || "1", 10);
247
+ for (let i = 0; i < totalShards; i++) {
248
+ const tempFilePath = path.join(this.outputDir, `${TEMP_SHARD_FILE_PREFIX}${i}.json`);
249
+ try {
250
+ const content = yield fs.readFile(tempFilePath, "utf-8");
251
+ const shardResults = JSON.parse(content);
252
+ // Assign the final runId to results from this shard
253
+ shardResults.forEach((r) => (r.runId = finalRunData.id));
254
+ allResults = allResults.concat(shardResults);
255
+ // console.log(`Pulse Reporter: Merged ${shardResults.length} results from shard ${i}`);
256
+ }
257
+ catch (error) {
258
+ if (error &&
259
+ typeof error === "object" &&
260
+ "code" in error &&
261
+ error.code === "ENOENT") {
262
+ console.warn(`Pulse Reporter: Shard results file not found: ${tempFilePath}. This might happen if a shard had no tests or failed early.`);
263
+ }
264
+ else {
265
+ console.warn(`Pulse Reporter: Could not read or parse results from shard ${i} (${tempFilePath}). Error: ${error}`);
266
+ }
267
+ }
268
+ }
269
+ console.log(`Pulse Reporter: Merged a total of ${allResults.length} results from ${totalShards} shards.`);
270
+ // Recalculate final counts based on merged results
271
+ finalRunData.passed = allResults.filter((r) => r.status === "passed").length;
272
+ finalRunData.failed = allResults.filter((r) => r.status === "failed").length;
273
+ finalRunData.skipped = allResults.filter((r) => r.status === "skipped").length;
274
+ finalRunData.totalTests = allResults.length;
275
+ return {
276
+ run: finalRunData,
277
+ results: allResults,
278
+ metadata: { generatedAt: new Date().toISOString() },
279
+ };
280
+ });
281
+ }
282
+ _cleanupTemporaryFiles() {
283
+ return __awaiter(this, void 0, void 0, function* () {
284
+ // Runs *only* in the main process after merging or on error
285
+ try {
286
+ yield this._ensureDirExists(this.outputDir); // Ensure dir exists before reading
287
+ const files = yield fs.readdir(this.outputDir);
288
+ const tempFiles = files.filter((f) => f.startsWith(TEMP_SHARD_FILE_PREFIX));
289
+ if (tempFiles.length > 0) {
290
+ console.log(`Pulse Reporter: Cleaning up ${tempFiles.length} temporary shard files...`);
291
+ yield Promise.all(tempFiles.map((f) => fs.unlink(path.join(this.outputDir, f))));
292
+ }
293
+ }
294
+ catch (error) {
295
+ // Ignore ENOENT (directory not found) errors, log others
296
+ if (error &&
297
+ typeof error === "object" &&
298
+ "code" in error &&
299
+ error.code !== "ENOENT") {
300
+ console.error("Pulse Reporter: Error cleaning up temporary files:", error);
301
+ }
302
+ }
303
+ });
304
+ }
305
+ _ensureDirExists(dirPath) {
306
+ return __awaiter(this, void 0, void 0, function* () {
307
+ try {
308
+ yield fs.mkdir(dirPath, { recursive: true });
309
+ }
310
+ catch (error) {
311
+ // Ignore EEXIST errors (directory already exists)
312
+ if (error &&
313
+ typeof error === "object" &&
314
+ "code" in error &&
315
+ error.code !== "EEXIST") {
316
+ console.error(`Pulse Reporter: Failed to ensure directory exists: ${dirPath}`, error); // Log error if mkdir fails unexpectedly
317
+ throw error; // Re-throw other errors
318
+ }
319
+ }
320
+ });
321
+ }
322
+ onEnd(result) {
323
+ return __awaiter(this, void 0, void 0, function* () {
324
+ var _a, _b, _c, _d, _e, _f;
325
+ if (this.shardIndex !== undefined) {
326
+ // This is a shard process, write its results to a temp file and exit
327
+ yield this._writeShardResults();
328
+ console.log(`PlaywrightPulseReporter: Shard ${this.shardIndex + 1} finished.`);
329
+ return;
330
+ }
331
+ // ---- This is the MAIN PROCESS ----
332
+ const runEndTime = Date.now();
333
+ const duration = runEndTime - this.runStartTime;
334
+ // The main process result.status might not be accurate with sharding, recalculate later
335
+ // const runStatus = convertStatus(result.status);
336
+ const runId = `run-${this.runStartTime}-${Math.random()
337
+ .toString(16)
338
+ .slice(2)}`; // Add randomness to run ID for uniqueness
339
+ // Initial run data (counts will be recalculated after merging)
340
+ const runData = {
341
+ id: runId,
342
+ timestamp: new Date(this.runStartTime),
343
+ totalTests: 0, // Placeholder
344
+ passed: 0, // Placeholder
345
+ failed: 0, // Placeholder
346
+ skipped: 0, // Placeholder
347
+ duration,
348
+ };
349
+ let finalReport;
350
+ if (this.isSharded) {
351
+ // Merge results from all shard temp files
352
+ finalReport = yield this._mergeShardResults(runData);
353
+ }
354
+ else {
355
+ // No sharding, use the results gathered in this main process
356
+ this.results.forEach((r) => (r.runId = runId)); // Assign runId
357
+ runData.passed = this.results.filter((r) => r.status === "passed").length;
358
+ runData.failed = this.results.filter((r) => r.status === "failed").length;
359
+ runData.skipped = this.results.filter((r) => r.status === "skipped").length;
360
+ runData.totalTests = this.results.length;
361
+ finalReport = {
362
+ run: runData,
363
+ results: this.results,
364
+ metadata: { generatedAt: new Date().toISOString() },
365
+ };
366
+ }
367
+ // Log final summary from the main process
368
+ const finalRunStatus = ((_b = (_a = finalReport.run) === null || _a === void 0 ? void 0 : _a.failed) !== null && _b !== void 0 ? _b : 0 > 0) ? "failed" : "passed"; // Simplified overall status
369
+ console.log(`PlaywrightPulseReporter: Test run finished with overall status: ${finalRunStatus}`);
370
+ console.log(` Passed: ${(_c = finalReport.run) === null || _c === void 0 ? void 0 : _c.passed}, Failed: ${(_d = finalReport.run) === null || _d === void 0 ? void 0 : _d.failed}, Skipped: ${(_e = finalReport.run) === null || _e === void 0 ? void 0 : _e.skipped}`);
371
+ console.log(` Total tests: ${(_f = finalReport.run) === null || _f === void 0 ? void 0 : _f.totalTests}`);
372
+ console.log(` Total time: ${(duration / 1000).toFixed(2)}s`);
373
+ const finalOutputPath = path.join(this.outputDir, this.baseOutputFile);
374
+ try {
375
+ yield this._ensureDirExists(this.outputDir);
376
+ yield fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
377
+ // Custom replacer to handle Date objects -> ISO strings
378
+ if (value instanceof Date) {
379
+ return value.toISOString();
380
+ }
381
+ return value;
382
+ }, 2));
383
+ console.log(`PlaywrightPulseReporter: Final report written to ${finalOutputPath}`);
384
+ }
385
+ catch (error) {
386
+ console.error(`PlaywrightPulseReporter: Failed to write final report to ${finalOutputPath}`, error);
387
+ }
388
+ finally {
389
+ // Clean up temporary shard files after merging (or if merge failed)
390
+ if (this.isSharded) {
391
+ yield this._cleanupTemporaryFiles();
392
+ }
393
+ }
394
+ });
395
+ }
396
+ }
397
+ // Use CommonJS export for compatibility
398
+ module.exports = PlaywrightPulseReporter;
@@ -0,0 +1,52 @@
1
+ import type { LucideIcon } from 'lucide-react';
2
+ export type TestStatus = 'passed' | 'failed' | 'skipped';
3
+ export interface TestStep {
4
+ id: string;
5
+ title: string;
6
+ status: TestStatus;
7
+ duration: number;
8
+ startTime: Date;
9
+ endTime: Date;
10
+ errorMessage?: string;
11
+ screenshot?: string;
12
+ videoTimestamp?: number;
13
+ }
14
+ export interface TestResult {
15
+ id: string;
16
+ name: string;
17
+ status: TestStatus;
18
+ duration: number;
19
+ startTime: Date;
20
+ endTime: Date;
21
+ retries: number;
22
+ steps: TestStep[];
23
+ errorMessage?: string;
24
+ stackTrace?: string;
25
+ codeSnippet?: string;
26
+ screenshot?: string;
27
+ video?: string;
28
+ tags?: string[];
29
+ suiteName?: string;
30
+ runId: string;
31
+ }
32
+ export interface TestRun {
33
+ id: string;
34
+ timestamp: Date;
35
+ totalTests: number;
36
+ passed: number;
37
+ failed: number;
38
+ skipped: number;
39
+ duration: number;
40
+ }
41
+ export interface TrendDataPoint {
42
+ date: string;
43
+ passed: number;
44
+ failed: number;
45
+ skipped: number;
46
+ }
47
+ export interface SummaryMetric {
48
+ label: string;
49
+ value: string | number;
50
+ icon: LucideIcon;
51
+ color?: string;
52
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,65 @@
1
+ import type { LucideIcon } from 'lucide-react';
2
+ export type TestStatus = "passed" | "failed" | "skipped" | "expected-failure" | "unexpected-success" | "explicitly-skipped";
3
+ export interface TestStep {
4
+ id: string;
5
+ title: string;
6
+ status: TestStatus;
7
+ duration: number;
8
+ startTime: Date;
9
+ endTime: Date;
10
+ browser: string;
11
+ errorMessage?: string;
12
+ stackTrace?: string;
13
+ codeLocation?: string;
14
+ isHook?: boolean;
15
+ hookType?: "before" | "after";
16
+ steps?: TestStep[];
17
+ }
18
+ export interface TestResult {
19
+ id: string;
20
+ name: string;
21
+ status: TestStatus;
22
+ duration: number;
23
+ startTime: Date;
24
+ endTime: Date;
25
+ retries: number;
26
+ steps: TestStep[];
27
+ errorMessage?: string;
28
+ stackTrace?: string;
29
+ codeSnippet?: string;
30
+ tags?: string[];
31
+ suiteName?: string;
32
+ runId: string;
33
+ browser: string;
34
+ screenshots?: string[];
35
+ videoPath?: string;
36
+ tracePath?: string;
37
+ stdout?: string[];
38
+ stderr?: string[];
39
+ }
40
+ export interface TestRun {
41
+ id: string;
42
+ timestamp: Date;
43
+ totalTests: number;
44
+ passed: number;
45
+ failed: number;
46
+ skipped: number;
47
+ duration: number;
48
+ }
49
+ export interface TrendDataPoint {
50
+ date: string;
51
+ passed: number;
52
+ failed: number;
53
+ skipped: number;
54
+ }
55
+ export interface SummaryMetric {
56
+ label: string;
57
+ value: string | number;
58
+ icon: LucideIcon;
59
+ color?: string;
60
+ }
61
+ export interface PlaywrightPulseReporterOptions {
62
+ outputFile?: string;
63
+ outputDir?: string;
64
+ base64Images?: boolean;
65
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@arghajit/dummy",
3
+ "author": "Arghajit Singha",
4
+ "version": "0.1.0",
5
+ "description": "A Playwright reporter and dashboard for visualizing test results.",
6
+ "keywords": [
7
+ "playwright",
8
+ "reporter",
9
+ "dashboard",
10
+ "test",
11
+ "reporting",
12
+ "nextjs",
13
+ "playwright-pulse",
14
+ "report",
15
+ "email-report",
16
+ "send-report",
17
+ "email"
18
+ ],
19
+ "main": "dist/reporter/index.js",
20
+ "types": "dist/reporter/index.d.ts",
21
+ "files": [
22
+ "dist",
23
+ "screenshots",
24
+ "scripts/generate-static-report.mjs"
25
+ ],
26
+ "license": "MIT",
27
+ "bin": {
28
+ "generate-pulse-report": "./scripts/generate-static-report.mjs",
29
+ "merge-pulse-report": "./scripts/merge-pulse-report.js",
30
+ "send-email": "./scripts/sendReport.js",
31
+ "generate-trend": "./scripts/generate-trend.mjs"
32
+ },
33
+ "exports": {
34
+ ".": {
35
+ "import": "./dist/reporter/index.js",
36
+ "require": "./dist/reporter/index.js"
37
+ }
38
+ },
39
+ "scripts": {
40
+ "build:reporter": "tsc -p tsconfig.reporter.json",
41
+ "typecheck": "tsc --noEmit",
42
+ "prepublishOnly": "npm run build:reporter",
43
+ "report:static": "node ./scripts/generate-static-report.mjs",
44
+ "report:merge": "node ./scripts/merge-pulse-report.js",
45
+ "report:email": "node ./scripts/sendReport.js"
46
+ },
47
+ "dependencies": {
48
+ "archiver": "^7.0.1",
49
+ "class-variance-authority": "^0.7.1",
50
+ "clsx": "^2.1.1",
51
+ "d3": "^7.9.0",
52
+ "date-fns": "^3.6.0",
53
+ "dotenv": "^16.5.0",
54
+ "highcharts": "^12.2.0",
55
+ "jsdom": "^26.1.0",
56
+ "lucide-react": "^0.475.0",
57
+ "nodemailer": "^7.0.3",
58
+ "patch-package": "^8.0.0",
59
+ "recharts": "^2.15.1",
60
+ "zod": "^3.24.2"
61
+ },
62
+ "devDependencies": {
63
+ "@types/node": "^20",
64
+ "eslint": "9.25.1",
65
+ "typescript": "^5"
66
+ },
67
+ "engines": {
68
+ "node": ">=16"
69
+ },
70
+ "peerDependencies": {
71
+ "@playwright/test": ">=1.40.0"
72
+ }
73
+ }
Binary file
Binary file