testlens-playwright-reporter 0.2.9 → 0.3.1
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/index.js +6 -50
- package/index.ts +6 -2
- package/lib/index.js +6 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -46,15 +46,12 @@ class TestLensReporter {
|
|
|
46
46
|
if (this.config.ignoreSslErrors) {
|
|
47
47
|
// Explicit configuration option
|
|
48
48
|
rejectUnauthorized = false;
|
|
49
|
-
console.log('⚠️ SSL certificate validation disabled via ignoreSslErrors option');
|
|
50
49
|
} else if (this.config.rejectUnauthorized === false) {
|
|
51
50
|
// Explicit configuration option
|
|
52
51
|
rejectUnauthorized = false;
|
|
53
|
-
console.log('⚠️ SSL certificate validation disabled via rejectUnauthorized option');
|
|
54
52
|
} else if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0') {
|
|
55
53
|
// Environment variable override
|
|
56
54
|
rejectUnauthorized = false;
|
|
57
|
-
console.log('⚠️ SSL certificate validation disabled via NODE_TLS_REJECT_UNAUTHORIZED environment variable');
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
// Set up axios instance with retry logic and enhanced SSL handling
|
|
@@ -144,18 +141,9 @@ class TestLensReporter {
|
|
|
144
141
|
}
|
|
145
142
|
|
|
146
143
|
async onBegin(config, suite) {
|
|
147
|
-
console.log(`🚀 TestLens Reporter starting - Run ID: ${this.runId}`);
|
|
148
|
-
|
|
149
144
|
// Collect Git information if enabled
|
|
150
145
|
if (this.config.enableGitInfo) {
|
|
151
146
|
this.runMetadata.gitInfo = await this.collectGitInfo();
|
|
152
|
-
if (this.runMetadata.gitInfo) {
|
|
153
|
-
console.log(`📦 Git info collected: branch=${this.runMetadata.gitInfo.branch}, commit=${this.runMetadata.gitInfo.shortCommit}, author=${this.runMetadata.gitInfo.author}`);
|
|
154
|
-
} else {
|
|
155
|
-
console.log(`⚠️ Git info collection returned null - not in a git repository or git not available`);
|
|
156
|
-
}
|
|
157
|
-
} else {
|
|
158
|
-
console.log(`ℹ️ Git info collection disabled (enableGitInfo: false)`);
|
|
159
147
|
}
|
|
160
148
|
|
|
161
149
|
// Add shard information if available
|
|
@@ -252,11 +240,8 @@ class TestLensReporter {
|
|
|
252
240
|
const testId = this.getTestId(test);
|
|
253
241
|
let testData = this.testMap.get(testId);
|
|
254
242
|
|
|
255
|
-
console.log(`[TestLens] onTestEnd called for test: ${test.title}, status: ${result.status}, testData exists: ${!!testData}`);
|
|
256
|
-
|
|
257
243
|
// For skipped tests, onTestBegin might not be called, so we need to create the test data here
|
|
258
244
|
if (!testData) {
|
|
259
|
-
console.log(`[TestLens] Creating test data for skipped/uncreated test: ${test.title}`);
|
|
260
245
|
// Create spec data if not exists (skipped tests might not have spec data either)
|
|
261
246
|
const specPath = test.location.file;
|
|
262
247
|
const specKey = `${specPath}-${test.parent.title}`;
|
|
@@ -422,7 +407,6 @@ class TestLensReporter {
|
|
|
422
407
|
const isFinalAttempt = result.status === 'passed' || result.status === 'skipped' || result.retry >= test.retries;
|
|
423
408
|
|
|
424
409
|
if (isFinalAttempt) {
|
|
425
|
-
console.log(`[TestLens] Sending testEnd - testId: ${testData.id}, status: ${testData.status}, originalStatus: ${testData.originalStatus}`);
|
|
426
410
|
// Send test end event to API
|
|
427
411
|
await this.sendToApi({
|
|
428
412
|
type: 'testEnd',
|
|
@@ -508,19 +492,16 @@ class TestLensReporter {
|
|
|
508
492
|
});
|
|
509
493
|
|
|
510
494
|
// Wait for background artifact processing to complete (up to 10 seconds)
|
|
511
|
-
console.log('⏳ Waiting for background artifact processing to complete...');
|
|
512
495
|
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
513
|
-
|
|
514
|
-
console.log(`📊 TestLens Report completed - Run ID: ${this.runId}`);
|
|
515
|
-
console.log(`🎯 Results: ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
|
|
516
496
|
}
|
|
517
497
|
|
|
518
498
|
async sendToApi(payload) {
|
|
519
499
|
try {
|
|
520
|
-
const response = await this.axiosInstance.post('', payload
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
500
|
+
const response = await this.axiosInstance.post('', payload, {
|
|
501
|
+
headers: {
|
|
502
|
+
'X-API-Key': this.config.apiKey
|
|
503
|
+
}
|
|
504
|
+
});
|
|
524
505
|
} catch (error) {
|
|
525
506
|
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
526
507
|
message: error?.message || 'Unknown error',
|
|
@@ -534,19 +515,10 @@ class TestLensReporter {
|
|
|
534
515
|
|
|
535
516
|
async processArtifacts(testId, result) {
|
|
536
517
|
const attachments = result.attachments;
|
|
537
|
-
console.log(`🔍 Processing artifacts for test ${testId}: ${attachments ? attachments.length : 0} attachments found`);
|
|
538
|
-
|
|
539
|
-
if (attachments && attachments.length > 0) {
|
|
540
|
-
console.log('📎 Attachment details:');
|
|
541
|
-
attachments.forEach((attachment, index) => {
|
|
542
|
-
console.log(` ${index + 1}. ${attachment.name} (${attachment.contentType}) - Path: ${attachment.path}`);
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
518
|
|
|
546
519
|
// Process artifacts with controlled async handling to ensure uploads complete
|
|
547
520
|
if (attachments && attachments.length > 0) {
|
|
548
521
|
// Process all artifacts asynchronously but track completion
|
|
549
|
-
console.log(`🔄 Processing ${attachments.length} artifacts asynchronously...`);
|
|
550
522
|
|
|
551
523
|
// Use process.nextTick to defer processing to next event loop iteration
|
|
552
524
|
process.nextTick(async () => {
|
|
@@ -560,18 +532,15 @@ class TestLensReporter {
|
|
|
560
532
|
|
|
561
533
|
// Skip video if disabled in config
|
|
562
534
|
if (isVideo && !this.config.enableVideo) {
|
|
563
|
-
console.log(`⏭️ Skipping video artifact ${attachment.name} - video capture disabled in config`);
|
|
564
535
|
continue;
|
|
565
536
|
}
|
|
566
537
|
|
|
567
538
|
// Skip screenshot if disabled in config
|
|
568
539
|
if (isScreenshot && !this.config.enableScreenshot) {
|
|
569
|
-
console.log(`⏭️ Skipping screenshot artifact ${attachment.name} - screenshot capture disabled in config`);
|
|
570
540
|
continue;
|
|
571
541
|
}
|
|
572
542
|
|
|
573
543
|
try {
|
|
574
|
-
console.log(`📤 Processing ${attachment.name} asynchronously...`);
|
|
575
544
|
|
|
576
545
|
// Determine proper filename with extension
|
|
577
546
|
// Playwright attachment.name often doesn't have extension, so we need to derive it
|
|
@@ -608,7 +577,6 @@ class TestLensReporter {
|
|
|
608
577
|
|
|
609
578
|
// Skip if upload failed or file was too large
|
|
610
579
|
if (!s3Data) {
|
|
611
|
-
console.log(`⏭️ Skipping artifact ${attachment.name} - upload failed or file too large`);
|
|
612
580
|
continue;
|
|
613
581
|
}
|
|
614
582
|
|
|
@@ -631,8 +599,6 @@ class TestLensReporter {
|
|
|
631
599
|
timestamp: new Date().toISOString(),
|
|
632
600
|
artifact: artifactData
|
|
633
601
|
});
|
|
634
|
-
|
|
635
|
-
console.log(`📎 Processed artifact: ${fileName} (uploaded to S3)`);
|
|
636
602
|
} catch (error) {
|
|
637
603
|
console.error(`❌ Failed to process ${attachment.name}:`, error.message);
|
|
638
604
|
}
|
|
@@ -665,8 +631,6 @@ class TestLensReporter {
|
|
|
665
631
|
codeBlocks,
|
|
666
632
|
testSuiteName: path.basename(specPath).replace(/\.(spec|test)\.(js|ts)$/, '')
|
|
667
633
|
});
|
|
668
|
-
|
|
669
|
-
console.log(`📝 Sent ${codeBlocks.length} code blocks for: ${path.basename(specPath)}`);
|
|
670
634
|
} catch (error) {
|
|
671
635
|
console.error('Failed to send spec code blocks:', error?.response?.data || error?.message || 'Unknown error');
|
|
672
636
|
}
|
|
@@ -760,7 +724,6 @@ class TestLensReporter {
|
|
|
760
724
|
}
|
|
761
725
|
} catch (e) {
|
|
762
726
|
// Remote info is optional - handle gracefully
|
|
763
|
-
console.log('ℹ️ No git remote configured, skipping remote info');
|
|
764
727
|
}
|
|
765
728
|
|
|
766
729
|
const isDirty = execSync('git status --porcelain', { encoding: 'utf-8' }).trim().length > 0;
|
|
@@ -828,8 +791,6 @@ class TestLensReporter {
|
|
|
828
791
|
// Check file size first
|
|
829
792
|
const fileSize = this.getFileSize(filePath);
|
|
830
793
|
const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(2);
|
|
831
|
-
|
|
832
|
-
console.log(`📤 Uploading ${fileName} (${fileSizeMB}MB) directly to S3...`);
|
|
833
794
|
|
|
834
795
|
const baseUrl = this.config.apiEndpoint.replace('/api/v1/webhook/playwright', '');
|
|
835
796
|
|
|
@@ -854,8 +815,6 @@ class TestLensReporter {
|
|
|
854
815
|
const { uploadUrl, s3Key, metadata } = presignedResponse.data;
|
|
855
816
|
|
|
856
817
|
// Step 2: Upload directly to S3 using presigned URL
|
|
857
|
-
console.log(`⬆️ Uploading ${fileName} directly to S3 (bypass server)...`);
|
|
858
|
-
|
|
859
818
|
const fileBuffer = fs.readFileSync(filePath);
|
|
860
819
|
|
|
861
820
|
// IMPORTANT: When using presigned URLs, we MUST include exactly the headers that were signed
|
|
@@ -867,7 +826,7 @@ class TestLensReporter {
|
|
|
867
826
|
},
|
|
868
827
|
maxContentLength: Infinity,
|
|
869
828
|
maxBodyLength: Infinity,
|
|
870
|
-
timeout: Math.max(
|
|
829
|
+
timeout: Math.max(600000, Math.ceil(fileSize / (1024 * 1024)) * 10000), // 10s per MB, min 10 minutes - increased for large trace files
|
|
871
830
|
// Don't use custom HTTPS agent for S3 uploads
|
|
872
831
|
httpsAgent: undefined
|
|
873
832
|
});
|
|
@@ -876,8 +835,6 @@ class TestLensReporter {
|
|
|
876
835
|
throw new Error(`S3 upload failed with status ${uploadResponse.status}`);
|
|
877
836
|
}
|
|
878
837
|
|
|
879
|
-
console.log(`✅ S3 direct upload completed for ${fileName}`);
|
|
880
|
-
|
|
881
838
|
// Step 3: Confirm upload with server to save metadata
|
|
882
839
|
const confirmEndpoint = `${baseUrl}/api/v1/artifacts/public/confirm-upload`;
|
|
883
840
|
const confirmResponse = await this.axiosInstance.post(confirmEndpoint, {
|
|
@@ -895,7 +852,6 @@ class TestLensReporter {
|
|
|
895
852
|
|
|
896
853
|
if (confirmResponse.status === 201 && confirmResponse.data.success) {
|
|
897
854
|
const artifact = confirmResponse.data.artifact;
|
|
898
|
-
console.log(`✅ Upload confirmed and saved to database`);
|
|
899
855
|
return {
|
|
900
856
|
key: s3Key,
|
|
901
857
|
url: artifact.s3Url,
|
package/index.ts
CHANGED
|
@@ -673,7 +673,11 @@ export class TestLensReporter implements Reporter {
|
|
|
673
673
|
private async sendToApi(payload: any): Promise<void> {
|
|
674
674
|
try {
|
|
675
675
|
console.log(`📤 Sending ${payload.type} event to ${this.config.apiEndpoint}`);
|
|
676
|
-
const response = await this.axiosInstance.post('', payload
|
|
676
|
+
const response = await this.axiosInstance.post('', payload, {
|
|
677
|
+
headers: {
|
|
678
|
+
'X-API-Key': this.config.apiKey
|
|
679
|
+
}
|
|
680
|
+
});
|
|
677
681
|
if (this.config.enableRealTimeStream) {
|
|
678
682
|
console.log(`✅ Sent ${payload.type} event to TestLens (HTTP ${response.status})`);
|
|
679
683
|
}
|
|
@@ -996,7 +1000,7 @@ export class TestLensReporter implements Reporter {
|
|
|
996
1000
|
},
|
|
997
1001
|
maxContentLength: Infinity,
|
|
998
1002
|
maxBodyLength: Infinity,
|
|
999
|
-
timeout: Math.max(
|
|
1003
|
+
timeout: Math.max(600000, Math.ceil(fileSize / (1024 * 1024)) * 10000), // 10s per MB, min 10 minutes - increased for large trace files
|
|
1000
1004
|
// Don't use custom HTTPS agent for S3 uploads
|
|
1001
1005
|
httpsAgent: undefined
|
|
1002
1006
|
});
|
package/lib/index.js
CHANGED
|
@@ -493,7 +493,11 @@ class TestLensReporter {
|
|
|
493
493
|
async sendToApi(payload) {
|
|
494
494
|
try {
|
|
495
495
|
console.log(`📤 Sending ${payload.type} event to ${this.config.apiEndpoint}`);
|
|
496
|
-
const response = await this.axiosInstance.post('', payload
|
|
496
|
+
const response = await this.axiosInstance.post('', payload, {
|
|
497
|
+
headers: {
|
|
498
|
+
'X-API-Key': this.config.apiKey
|
|
499
|
+
}
|
|
500
|
+
});
|
|
497
501
|
if (this.config.enableRealTimeStream) {
|
|
498
502
|
console.log(`✅ Sent ${payload.type} event to TestLens (HTTP ${response.status})`);
|
|
499
503
|
}
|
|
@@ -781,7 +785,7 @@ class TestLensReporter {
|
|
|
781
785
|
},
|
|
782
786
|
maxContentLength: Infinity,
|
|
783
787
|
maxBodyLength: Infinity,
|
|
784
|
-
timeout: Math.max(
|
|
788
|
+
timeout: Math.max(600000, Math.ceil(fileSize / (1024 * 1024)) * 10000), // 10s per MB, min 10 minutes - increased for large trace files
|
|
785
789
|
// Don't use custom HTTPS agent for S3 uploads
|
|
786
790
|
httpsAgent: undefined
|
|
787
791
|
});
|
package/package.json
CHANGED