@arghajit/dummy 0.1.0-beta-19 → 0.1.0-beta-20
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/README.md
CHANGED
|
@@ -161,8 +161,8 @@ npx generate-report
|
|
|
161
161
|
1. Configure `.env`:
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
RECIPIENT_EMAIL_1=recipient1@example.com
|
|
165
|
+
RECIPIENT_EMAIL_2=recipient2@example.com
|
|
166
166
|
# ... up to 5 recipients
|
|
167
167
|
```
|
|
168
168
|
|
|
@@ -277,7 +277,7 @@ npm install @arghajit/playwright-pulse-report@latest
|
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
|
280
|
-
<img src="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images//pulse-logo.png" alt="pulse dashboard" title="pulse dashboard" height="
|
|
280
|
+
<img src="https://ocpaxmghzmfbuhxzxzae.supabase.co/storage/v1/object/public/images//pulse-logo.png" alt="pulse dashboard" title="pulse dashboard" height="35px" width="60px" align="left" padding="5px"/>
|
|
281
281
|
<h2>Pulse Dashboard</h2>
|
|
282
282
|
|
|
283
283
|
**Real-time Playwright Test Monitoring & Analysis**
|
|
@@ -300,13 +300,13 @@ npm run pulse-dashboard
|
|
|
300
300
|
|
|
301
301
|
*(Run from project root containing `pulse-report/` directory)*
|
|
302
302
|
|
|
303
|
-
**NPM Package**: [pulse-dashboard
|
|
303
|
+
**NPM Package**: [pulse-dashboard](https://www.npmjs.com/package/pulse-dashboard)
|
|
304
304
|
|
|
305
305
|
**Tech Stack**: Next.js, TypeScript, Tailwind CSS, Playwright
|
|
306
306
|
|
|
307
|
-
*Part of the Playwright Pulse Report ecosystem*
|
|
307
|
+
*Part of the Playwright Pulse Report ecosystem*
|
|
308
308
|
|
|
309
|
-
---
|
|
309
|
+
---
|
|
310
310
|
|
|
311
311
|
## 📬 Support
|
|
312
312
|
|
|
@@ -253,37 +253,47 @@ class PlaywrightPulseReporter {
|
|
|
253
253
|
codeSnippet: codeSnippet,
|
|
254
254
|
tags: test.tags.map((tag) => tag.startsWith("@") ? tag.substring(1) : tag),
|
|
255
255
|
screenshots: [],
|
|
256
|
-
videoPath: [],
|
|
256
|
+
videoPath: [],
|
|
257
257
|
tracePath: undefined,
|
|
258
|
-
attachments: [],
|
|
258
|
+
attachments: [],
|
|
259
259
|
stdout: stdoutMessages.length > 0 ? stdoutMessages : undefined,
|
|
260
260
|
stderr: stderrMessages.length > 0 ? stderrMessages : undefined,
|
|
261
261
|
...testSpecificData,
|
|
262
262
|
};
|
|
263
|
-
// ---
|
|
264
|
-
for (const attachment of result.attachments) {
|
|
263
|
+
// --- CORRECTED ATTACHMENT PROCESSING LOGIC ---
|
|
264
|
+
for (const [index, attachment] of result.attachments.entries()) {
|
|
265
265
|
if (!attachment.path)
|
|
266
266
|
continue;
|
|
267
267
|
try {
|
|
268
|
-
|
|
269
|
-
const
|
|
268
|
+
// Create a sanitized, unique folder name for this specific test
|
|
269
|
+
const testSubfolder = test.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
270
|
+
// Sanitize the original attachment name to create a safe filename
|
|
271
|
+
const safeAttachmentName = path
|
|
272
|
+
.basename(attachment.path)
|
|
273
|
+
.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
274
|
+
// Create a unique filename to prevent collisions, especially in retries
|
|
275
|
+
const uniqueFileName = `${index}-${Date.now()}-${safeAttachmentName}`;
|
|
276
|
+
// This is the relative path that will be stored in the JSON report
|
|
277
|
+
const relativeDestPath = path.join(ATTACHMENTS_SUBDIR, testSubfolder, uniqueFileName);
|
|
278
|
+
// This is the absolute path used for the actual file system operation
|
|
270
279
|
const absoluteDestPath = path.join(this.outputDir, relativeDestPath);
|
|
280
|
+
// Ensure the unique, test-specific attachment directory exists
|
|
271
281
|
await this._ensureDirExists(path.dirname(absoluteDestPath));
|
|
272
282
|
await fs.copyFile(attachment.path, absoluteDestPath);
|
|
283
|
+
// Categorize the attachment based on its content type
|
|
273
284
|
if (attachment.contentType.startsWith("image/")) {
|
|
274
285
|
(_j = pulseResult.screenshots) === null || _j === void 0 ? void 0 : _j.push(relativeDestPath);
|
|
275
286
|
}
|
|
276
287
|
else if (attachment.contentType.startsWith("video/")) {
|
|
277
|
-
(_k = pulseResult.videoPath) === null || _k === void 0 ? void 0 : _k.push(relativeDestPath);
|
|
288
|
+
(_k = pulseResult.videoPath) === null || _k === void 0 ? void 0 : _k.push(relativeDestPath);
|
|
278
289
|
}
|
|
279
290
|
else if (attachment.name === "trace") {
|
|
280
291
|
pulseResult.tracePath = relativeDestPath;
|
|
281
292
|
}
|
|
282
293
|
else {
|
|
283
|
-
// NEW: Handle all other file types
|
|
284
294
|
(_l = pulseResult.attachments) === null || _l === void 0 ? void 0 : _l.push({
|
|
285
|
-
name: attachment.name,
|
|
286
|
-
path: relativeDestPath,
|
|
295
|
+
name: attachment.name, // The original, human-readable name
|
|
296
|
+
path: relativeDestPath, // The safe, relative path for linking
|
|
287
297
|
contentType: attachment.contentType,
|
|
288
298
|
});
|
|
289
299
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arghajit/dummy",
|
|
3
3
|
"author": "Arghajit Singha",
|
|
4
|
-
"version": "0.1.0-beta-
|
|
4
|
+
"version": "0.1.0-beta-20",
|
|
5
5
|
"description": "A Playwright reporter and dashboard for visualizing test results.",
|
|
6
|
+
"homepage": "https://playwright-pulse-report.netlify.app/",
|
|
6
7
|
"keywords": [
|
|
7
8
|
"playwright",
|
|
8
9
|
"reporter",
|
|
@@ -15,7 +16,9 @@
|
|
|
15
16
|
"report",
|
|
16
17
|
"email-report",
|
|
17
18
|
"send-report",
|
|
18
|
-
"email"
|
|
19
|
+
"email",
|
|
20
|
+
"playwright-report",
|
|
21
|
+
"pulse"
|
|
19
22
|
],
|
|
20
23
|
"main": "dist/reporter/index.js",
|
|
21
24
|
"types": "dist/reporter/index.d.ts",
|
|
@@ -1409,6 +1409,11 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1409
1409
|
</div>
|
|
1410
1410
|
<div class="test-case-content" style="display: none;">
|
|
1411
1411
|
<p><strong>Full Path:</strong> ${sanitizeHTML(test.name)}</p>
|
|
1412
|
+
<p><strong>Test run Worker ID:</strong> ${sanitizeHTML(
|
|
1413
|
+
test.workerId
|
|
1414
|
+
)} [<strong>Total No. of Workers:</strong> ${sanitizeHTML(
|
|
1415
|
+
test.totalWorkers
|
|
1416
|
+
)}]</p>
|
|
1412
1417
|
${
|
|
1413
1418
|
test.errorMessage
|
|
1414
1419
|
? `<div class="test-error-summary">${formatPlaywrightError(
|
|
@@ -1441,15 +1446,15 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1441
1446
|
${
|
|
1442
1447
|
test.stdout && test.stdout.length > 0
|
|
1443
1448
|
? `<div class="console-output-section"><h4>Console Output (stdout)</h4><pre class="console-log stdout-log" style="background-color: #2d2d2d; color: wheat; padding: 1.25em; border-radius: 0.85em; line-height: 1.2;">${formatPlaywrightError(
|
|
1444
|
-
test.stdout.join("\n")
|
|
1449
|
+
test.stdout.map((line) => sanitizeHTML(line)).join("\n")
|
|
1445
1450
|
)}</pre></div>`
|
|
1446
1451
|
: ""
|
|
1447
1452
|
}
|
|
1448
1453
|
${
|
|
1449
1454
|
test.stderr && test.stderr.length > 0
|
|
1450
|
-
? `<div class="console-output-section"><h4>Console Output (stderr)</h4><pre class="console-log stderr-log" style="background-color: #2d2d2d; color: indianred; padding: 1.25em; border-radius: 0.85em; line-height: 1.2;">${
|
|
1451
|
-
.map((line) => sanitizeHTML(line))
|
|
1452
|
-
|
|
1455
|
+
? `<div class="console-output-section"><h4>Console Output (stderr)</h4><pre class="console-log stderr-log" style="background-color: #2d2d2d; color: indianred; padding: 1.25em; border-radius: 0.85em; line-height: 1.2;">${formatPlaywrightError(
|
|
1456
|
+
test.stderr.map((line) => sanitizeHTML(line)).join("\n")
|
|
1457
|
+
)}</pre></div>`
|
|
1453
1458
|
: ""
|
|
1454
1459
|
}
|
|
1455
1460
|
${
|
|
@@ -1480,11 +1485,7 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1480
1485
|
}
|
|
1481
1486
|
${
|
|
1482
1487
|
test.videoPath && test.videoPath.length > 0
|
|
1483
|
-
?
|
|
1484
|
-
<div class="attachments-section">
|
|
1485
|
-
<h4>Videos</h4>
|
|
1486
|
-
<div class="attachments-grid">
|
|
1487
|
-
${test.videoPath
|
|
1488
|
+
? `<div class="attachments-section"><h4>Videos</h4><div class="attachments-grid">${test.videoPath
|
|
1488
1489
|
.map((videoUrl, index) => {
|
|
1489
1490
|
const fileExtension = String(videoUrl)
|
|
1490
1491
|
.split(".")
|
|
@@ -1498,8 +1499,7 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1498
1499
|
mov: "video/quicktime",
|
|
1499
1500
|
avi: "video/x-msvideo",
|
|
1500
1501
|
}[fileExtension] || "video/mp4";
|
|
1501
|
-
return
|
|
1502
|
-
<div class="attachment-item video-item">
|
|
1502
|
+
return `<div class="attachment-item video-item">
|
|
1503
1503
|
<video controls width="100%" height="auto" title="Video ${
|
|
1504
1504
|
index + 1
|
|
1505
1505
|
}">
|
|
@@ -1517,10 +1517,7 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1517
1517
|
</div>
|
|
1518
1518
|
</div>`;
|
|
1519
1519
|
})
|
|
1520
|
-
.join("")}
|
|
1521
|
-
</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
`
|
|
1520
|
+
.join("")}</div></div>`
|
|
1524
1521
|
: ""
|
|
1525
1522
|
}
|
|
1526
1523
|
${
|
|
@@ -1592,8 +1589,8 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1592
1589
|
}
|
|
1593
1590
|
${
|
|
1594
1591
|
test.codeSnippet
|
|
1595
|
-
? `<div class="code-section"><h4>Code Snippet</h4><pre><code>${
|
|
1596
|
-
test.codeSnippet
|
|
1592
|
+
? `<div class="code-section"><h4>Code Snippet</h4><pre><code>${formatPlaywrightError(
|
|
1593
|
+
sanitizeHTML(test.codeSnippet)
|
|
1597
1594
|
)}</code></pre></div>`
|
|
1598
1595
|
: ""
|
|
1599
1596
|
}
|
|
@@ -1377,6 +1377,11 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1377
1377
|
<p><strong>Full Path:</strong> ${sanitizeHTML(
|
|
1378
1378
|
test.name
|
|
1379
1379
|
)}</p>
|
|
1380
|
+
<p><strong>Test run Worker ID:</strong> ${sanitizeHTML(
|
|
1381
|
+
test.workerId
|
|
1382
|
+
)} [<strong>Total No. of Workers:</strong> ${sanitizeHTML(
|
|
1383
|
+
test.totalWorkers
|
|
1384
|
+
)}]</p>
|
|
1380
1385
|
${
|
|
1381
1386
|
test.errorMessage
|
|
1382
1387
|
? `<div class="test-error-summary">${formatPlaywrightError(
|
|
@@ -1535,6 +1540,14 @@ function generateHTML(reportData, trendData = null) {
|
|
|
1535
1540
|
})
|
|
1536
1541
|
.join("")}</div></div>`;
|
|
1537
1542
|
})()}
|
|
1543
|
+
|
|
1544
|
+
${
|
|
1545
|
+
test.codeSnippet
|
|
1546
|
+
? `<div class="code-section"><h4>Code Snippet</h4><pre><code>${sanitizeHTML(
|
|
1547
|
+
test.codeSnippet
|
|
1548
|
+
)}</code></pre></div>`
|
|
1549
|
+
: ""
|
|
1550
|
+
}
|
|
1538
1551
|
</div>
|
|
1539
1552
|
</div>`;
|
|
1540
1553
|
})
|
package/scripts/sendReport.mjs
CHANGED
|
@@ -265,11 +265,11 @@ const sendEmail = async (credentials) => {
|
|
|
265
265
|
const mailOptions = {
|
|
266
266
|
from: credentials.username,
|
|
267
267
|
to: [
|
|
268
|
-
process.env.
|
|
269
|
-
process.env.
|
|
270
|
-
process.env.
|
|
271
|
-
process.env.
|
|
272
|
-
process.env.
|
|
268
|
+
process.env.RECIPIENT_EMAIL_1 || "",
|
|
269
|
+
process.env.RECIPIENT_EMAIL_2 || "",
|
|
270
|
+
process.env.RECIPIENT_EMAIL_3 || "",
|
|
271
|
+
process.env.RECIPIENT_EMAIL_4 || "",
|
|
272
|
+
process.env.RECIPIENT_EMAIL_5 || "",
|
|
273
273
|
].filter((email) => email), // Filter out empty strings
|
|
274
274
|
subject: "Pulse Report " + new Date().toLocaleString(),
|
|
275
275
|
html: htmlContent,
|