testlens-playwright-reporter 0.2.5 → 0.2.7

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.d.ts CHANGED
@@ -11,6 +11,10 @@ export interface TestLensReporterConfig {
11
11
  enableGitInfo?: boolean;
12
12
  /** Enable artifact processing */
13
13
  enableArtifacts?: boolean;
14
+ /** Enable video capture - defaults to true */
15
+ enableVideo?: boolean;
16
+ /** Enable screenshot capture - defaults to true */
17
+ enableScreenshot?: boolean;
14
18
  /** Batch size for API requests */
15
19
  batchSize?: number;
16
20
  /** Flush interval in milliseconds */
@@ -36,6 +40,10 @@ export interface TestLensReporterOptions {
36
40
  enableGitInfo?: boolean;
37
41
  /** Enable artifact processing */
38
42
  enableArtifacts?: boolean;
43
+ /** Enable video capture - defaults to true */
44
+ enableVideo?: boolean;
45
+ /** Enable screenshot capture - defaults to true */
46
+ enableScreenshot?: boolean;
39
47
  /** Batch size for API requests */
40
48
  batchSize?: number;
41
49
  /** Flush interval in milliseconds */
@@ -55,8 +63,8 @@ export interface GitInfo {
55
63
  commit: string;
56
64
  shortCommit: string;
57
65
  author: string;
58
- commitMessage: string;
59
- commitTimestamp: string;
66
+ message: string;
67
+ timestamp: string;
60
68
  isDirty: boolean;
61
69
  remoteName: string;
62
70
  remoteUrl: string;
package/index.js CHANGED
@@ -27,6 +27,8 @@ class TestLensReporter {
27
27
  enableRealTimeStream: options.enableRealTimeStream !== undefined ? options.enableRealTimeStream : true,
28
28
  enableGitInfo: options.enableGitInfo !== undefined ? options.enableGitInfo : true,
29
29
  enableArtifacts: options.enableArtifacts !== undefined ? options.enableArtifacts : true,
30
+ enableVideo: options.enableVideo !== undefined ? options.enableVideo : true, // Default to true, override from config
31
+ enableScreenshot: options.enableScreenshot !== undefined ? options.enableScreenshot : true, // Default to true, override from config
30
32
  batchSize: options.batchSize || 10,
31
33
  flushInterval: options.flushInterval || 5000,
32
34
  retryAttempts: options.retryAttempts !== undefined ? options.retryAttempts : 0,
@@ -147,6 +149,13 @@ class TestLensReporter {
147
149
  // Collect Git information if enabled
148
150
  if (this.config.enableGitInfo) {
149
151
  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)`);
150
159
  }
151
160
 
152
161
  // Add shard information if available
@@ -309,8 +318,10 @@ class TestLensReporter {
309
318
  // Calculate final stats
310
319
  const totalTests = Array.from(this.testMap.values()).length;
311
320
  const passedTests = Array.from(this.testMap.values()).filter(t => t.status === 'passed').length;
321
+ // failedTests already includes timedOut tests since normalizeTestStatus converts 'timedOut' to 'failed'
312
322
  const failedTests = Array.from(this.testMap.values()).filter(t => t.status === 'failed').length;
313
323
  const skippedTests = Array.from(this.testMap.values()).filter(t => t.status === 'skipped').length;
324
+ // Track timedOut separately for reporting purposes only (not for count)
314
325
  const timedOutTests = Array.from(this.testMap.values()).filter(t => t.originalStatus === 'timedOut').length;
315
326
 
316
327
  // Normalize run status - if there are timeouts, treat run as failed
@@ -326,9 +337,9 @@ class TestLensReporter {
326
337
  ...this.runMetadata,
327
338
  totalTests,
328
339
  passedTests,
329
- failedTests: failedTests + timedOutTests, // Include timeouts in failed count
340
+ failedTests, // Already includes timedOut tests (normalized to 'failed')
330
341
  skippedTests,
331
- timedOutTests,
342
+ timedOutTests, // For informational purposes
332
343
  status: normalizedRunStatus
333
344
  }
334
345
  });
@@ -338,7 +349,7 @@ class TestLensReporter {
338
349
  await new Promise(resolve => setTimeout(resolve, 10000));
339
350
 
340
351
  console.log(`📊 TestLens Report completed - Run ID: ${this.runId}`);
341
- console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests + timedOutTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
352
+ console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
342
353
  }
343
354
 
344
355
  async sendToApi(payload) {
@@ -379,17 +390,70 @@ class TestLensReporter {
379
390
  for (let i = 0; i < attachments.length; i++) {
380
391
  const attachment = attachments[i];
381
392
  if (attachment.path) {
393
+ // Check if attachment should be processed based on config
394
+ const artifactType = this.getArtifactType(attachment.name);
395
+ const isVideo = artifactType === 'video' || (attachment.contentType && attachment.contentType.startsWith('video/'));
396
+ const isScreenshot = artifactType === 'screenshot' || (attachment.contentType && attachment.contentType.startsWith('image/'));
397
+
398
+ // Skip video if disabled in config
399
+ if (isVideo && !this.config.enableVideo) {
400
+ console.log(`â­ī¸ Skipping video artifact ${attachment.name} - video capture disabled in config`);
401
+ continue;
402
+ }
403
+
404
+ // Skip screenshot if disabled in config
405
+ if (isScreenshot && !this.config.enableScreenshot) {
406
+ console.log(`â­ī¸ Skipping screenshot artifact ${attachment.name} - screenshot capture disabled in config`);
407
+ continue;
408
+ }
409
+
382
410
  try {
383
411
  console.log(`📤 Processing ${attachment.name} asynchronously...`);
384
412
 
413
+ // Determine proper filename with extension
414
+ // Playwright attachment.name often doesn't have extension, so we need to derive it
415
+ let fileName = attachment.name;
416
+ const existingExt = path.extname(fileName);
417
+
418
+ if (!existingExt) {
419
+ // Get extension from the actual file path
420
+ const pathExt = path.extname(attachment.path);
421
+ if (pathExt) {
422
+ fileName = `${fileName}${pathExt}`;
423
+ } else if (attachment.contentType) {
424
+ // Fallback: derive extension from contentType
425
+ const mimeToExt = {
426
+ 'image/png': '.png',
427
+ 'image/jpeg': '.jpg',
428
+ 'image/gif': '.gif',
429
+ 'image/webp': '.webp',
430
+ 'video/webm': '.webm',
431
+ 'video/mp4': '.mp4',
432
+ 'application/zip': '.zip',
433
+ 'application/json': '.json',
434
+ 'text/plain': '.txt'
435
+ };
436
+ const ext = mimeToExt[attachment.contentType];
437
+ if (ext) {
438
+ fileName = `${fileName}${ext}`;
439
+ }
440
+ }
441
+ }
442
+
385
443
  // Upload to S3 first
386
- const s3Data = await this.uploadArtifactToS3(attachment.path, testId, attachment.name);
444
+ const s3Data = await this.uploadArtifactToS3(attachment.path, testId, fileName);
445
+
446
+ // Skip if upload failed or file was too large
447
+ if (!s3Data) {
448
+ console.log(`â­ī¸ Skipping artifact ${attachment.name} - upload failed or file too large`);
449
+ continue;
450
+ }
387
451
 
388
452
  const artifactData = {
389
453
  testId,
390
454
  type: this.getArtifactType(attachment.name),
391
455
  path: attachment.path,
392
- name: attachment.name,
456
+ name: fileName,
393
457
  contentType: attachment.contentType,
394
458
  fileSize: this.getFileSize(attachment.path),
395
459
  storageType: 's3',
@@ -405,7 +469,7 @@ class TestLensReporter {
405
469
  artifact: artifactData
406
470
  });
407
471
 
408
- console.log(`📎 Processed artifact: ${attachment.name} (uploaded to S3)`);
472
+ console.log(`📎 Processed artifact: ${fileName} (uploaded to S3)`);
409
473
  } catch (error) {
410
474
  console.error(`❌ Failed to process ${attachment.name}:`, error.message);
411
475
  }
@@ -543,8 +607,8 @@ class TestLensReporter {
543
607
  commit,
544
608
  shortCommit,
545
609
  author,
546
- commitMessage,
547
- commitTimestamp,
610
+ message: commitMessage,
611
+ timestamp: commitTimestamp,
548
612
  isDirty,
549
613
  remoteName,
550
614
  remoteUrl
package/index.ts CHANGED
@@ -32,6 +32,10 @@ export interface TestLensReporterConfig {
32
32
  enableGitInfo?: boolean;
33
33
  /** Enable artifact processing */
34
34
  enableArtifacts?: boolean;
35
+ /** Enable video capture - defaults to true */
36
+ enableVideo?: boolean;
37
+ /** Enable screenshot capture - defaults to true */
38
+ enableScreenshot?: boolean;
35
39
  /** Batch size for API requests */
36
40
  batchSize?: number;
37
41
  /** Flush interval in milliseconds */
@@ -57,6 +61,10 @@ export interface TestLensReporterOptions {
57
61
  enableGitInfo?: boolean;
58
62
  /** Enable artifact processing */
59
63
  enableArtifacts?: boolean;
64
+ /** Enable video capture - defaults to true */
65
+ enableVideo?: boolean;
66
+ /** Enable screenshot capture - defaults to true */
67
+ enableScreenshot?: boolean;
60
68
  /** Batch size for API requests */
61
69
  batchSize?: number;
62
70
  /** Flush interval in milliseconds */
@@ -76,8 +84,8 @@ export interface GitInfo {
76
84
  commit: string;
77
85
  shortCommit: string;
78
86
  author: string;
79
- commitMessage: string;
80
- commitTimestamp: string;
87
+ message: string;
88
+ timestamp: string;
81
89
  isDirty: boolean;
82
90
  remoteName: string;
83
91
  remoteUrl: string;
@@ -156,6 +164,8 @@ export class TestLensReporter implements Reporter {
156
164
  enableRealTimeStream: options.enableRealTimeStream !== undefined ? options.enableRealTimeStream : true,
157
165
  enableGitInfo: options.enableGitInfo !== undefined ? options.enableGitInfo : true,
158
166
  enableArtifacts: options.enableArtifacts !== undefined ? options.enableArtifacts : true,
167
+ enableVideo: options.enableVideo !== undefined ? options.enableVideo : true, // Default to true, override from config
168
+ enableScreenshot: options.enableScreenshot !== undefined ? options.enableScreenshot : true, // Default to true, override from config
159
169
  batchSize: options.batchSize || 10,
160
170
  flushInterval: options.flushInterval || 5000,
161
171
  retryAttempts: options.retryAttempts !== undefined ? options.retryAttempts : 0,
@@ -276,6 +286,13 @@ export class TestLensReporter implements Reporter {
276
286
  // Collect Git information if enabled
277
287
  if (this.config.enableGitInfo) {
278
288
  this.runMetadata.gitInfo = await this.collectGitInfo();
289
+ if (this.runMetadata.gitInfo) {
290
+ console.log(`đŸ“Ļ Git info collected: branch=${this.runMetadata.gitInfo.branch}, commit=${this.runMetadata.gitInfo.shortCommit}, author=${this.runMetadata.gitInfo.author}`);
291
+ } else {
292
+ console.log(`âš ī¸ Git info collection returned null - not in a git repository or git not available`);
293
+ }
294
+ } else {
295
+ console.log(`â„šī¸ Git info collection disabled (enableGitInfo: false)`);
279
296
  }
280
297
 
281
298
  // Add shard information if available
@@ -438,8 +455,10 @@ export class TestLensReporter implements Reporter {
438
455
  // Calculate final stats
439
456
  const totalTests = Array.from(this.testMap.values()).length;
440
457
  const passedTests = Array.from(this.testMap.values()).filter(t => t.status === 'passed').length;
458
+ // failedTests already includes timedOut tests since normalizeTestStatus converts 'timedOut' to 'failed'
441
459
  const failedTests = Array.from(this.testMap.values()).filter(t => t.status === 'failed').length;
442
460
  const skippedTests = Array.from(this.testMap.values()).filter(t => t.status === 'skipped').length;
461
+ // Track timedOut separately for reporting purposes only (not for count)
443
462
  const timedOutTests = Array.from(this.testMap.values()).filter(t => t.originalStatus === 'timedOut').length;
444
463
 
445
464
  // Normalize run status - if there are timeouts, treat run as failed
@@ -455,15 +474,15 @@ export class TestLensReporter implements Reporter {
455
474
  ...this.runMetadata,
456
475
  totalTests,
457
476
  passedTests,
458
- failedTests: failedTests + timedOutTests, // Include timeouts in failed count
477
+ failedTests, // Already includes timedOut tests (normalized to 'failed')
459
478
  skippedTests,
460
- timedOutTests,
479
+ timedOutTests, // For informational purposes
461
480
  status: normalizedRunStatus
462
481
  }
463
482
  });
464
483
 
465
484
  console.log(`📊 TestLens Report completed - Run ID: ${this.runId}`);
466
- console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests + timedOutTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
485
+ console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
467
486
  }
468
487
 
469
488
  private async sendToApi(payload: any): Promise<void> {
@@ -493,9 +512,56 @@ export class TestLensReporter implements Reporter {
493
512
 
494
513
  for (const attachment of attachments) {
495
514
  if (attachment.path) {
515
+ // Check if attachment should be processed based on config
516
+ const artifactType = this.getArtifactType(attachment.name);
517
+ const isVideo = artifactType === 'video' || attachment.contentType?.startsWith('video/');
518
+ const isScreenshot = artifactType === 'screenshot' || attachment.contentType?.startsWith('image/');
519
+
520
+ // Skip video if disabled in config
521
+ if (isVideo && !this.config.enableVideo) {
522
+ console.log(`â­ī¸ Skipping video artifact ${attachment.name} - video capture disabled in config`);
523
+ continue;
524
+ }
525
+
526
+ // Skip screenshot if disabled in config
527
+ if (isScreenshot && !this.config.enableScreenshot) {
528
+ console.log(`â­ī¸ Skipping screenshot artifact ${attachment.name} - screenshot capture disabled in config`);
529
+ continue;
530
+ }
531
+
496
532
  try {
533
+ // Determine proper filename with extension
534
+ // Playwright attachment.name often doesn't have extension, so we need to derive it
535
+ let fileName = attachment.name;
536
+ const existingExt = path.extname(fileName);
537
+
538
+ if (!existingExt) {
539
+ // Get extension from the actual file path
540
+ const pathExt = path.extname(attachment.path);
541
+ if (pathExt) {
542
+ fileName = `${fileName}${pathExt}`;
543
+ } else if (attachment.contentType) {
544
+ // Fallback: derive extension from contentType
545
+ const mimeToExt: Record<string, string> = {
546
+ 'image/png': '.png',
547
+ 'image/jpeg': '.jpg',
548
+ 'image/gif': '.gif',
549
+ 'image/webp': '.webp',
550
+ 'video/webm': '.webm',
551
+ 'video/mp4': '.mp4',
552
+ 'application/zip': '.zip',
553
+ 'application/json': '.json',
554
+ 'text/plain': '.txt'
555
+ };
556
+ const ext = mimeToExt[attachment.contentType];
557
+ if (ext) {
558
+ fileName = `${fileName}${ext}`;
559
+ }
560
+ }
561
+ }
562
+
497
563
  // Upload to S3 first
498
- const s3Data = await this.uploadArtifactToS3(attachment.path, testId, attachment.name);
564
+ const s3Data = await this.uploadArtifactToS3(attachment.path, testId, fileName);
499
565
 
500
566
  // Skip if upload failed or file was too large
501
567
  if (!s3Data) {
@@ -507,7 +573,7 @@ export class TestLensReporter implements Reporter {
507
573
  testId,
508
574
  type: this.getArtifactType(attachment.name),
509
575
  path: attachment.path,
510
- name: attachment.name,
576
+ name: fileName,
511
577
  contentType: attachment.contentType,
512
578
  fileSize: this.getFileSize(attachment.path),
513
579
  storageType: 's3',
@@ -523,7 +589,7 @@ export class TestLensReporter implements Reporter {
523
589
  artifact: artifactData
524
590
  });
525
591
 
526
- console.log(`📎 Processed artifact: ${attachment.name} (uploaded to S3)`);
592
+ console.log(`📎 Processed artifact: ${fileName} (uploaded to S3)`);
527
593
  } catch (error) {
528
594
  console.error(`❌ Failed to process artifact ${attachment.name}:`, (error as Error).message);
529
595
  }
@@ -657,8 +723,8 @@ export class TestLensReporter implements Reporter {
657
723
  commit,
658
724
  shortCommit,
659
725
  author,
660
- commitMessage,
661
- commitTimestamp,
726
+ message: commitMessage,
727
+ timestamp: commitTimestamp,
662
728
  isDirty,
663
729
  remoteName,
664
730
  remoteUrl
package/lib/index.js CHANGED
@@ -63,6 +63,8 @@ class TestLensReporter {
63
63
  enableRealTimeStream: options.enableRealTimeStream !== undefined ? options.enableRealTimeStream : true,
64
64
  enableGitInfo: options.enableGitInfo !== undefined ? options.enableGitInfo : true,
65
65
  enableArtifacts: options.enableArtifacts !== undefined ? options.enableArtifacts : true,
66
+ enableVideo: options.enableVideo !== undefined ? options.enableVideo : true, // Default to true, override from config
67
+ enableScreenshot: options.enableScreenshot !== undefined ? options.enableScreenshot : true, // Default to true, override from config
66
68
  batchSize: options.batchSize || 10,
67
69
  flushInterval: options.flushInterval || 5000,
68
70
  retryAttempts: options.retryAttempts !== undefined ? options.retryAttempts : 0,
@@ -168,6 +170,15 @@ class TestLensReporter {
168
170
  // Collect Git information if enabled
169
171
  if (this.config.enableGitInfo) {
170
172
  this.runMetadata.gitInfo = await this.collectGitInfo();
173
+ if (this.runMetadata.gitInfo) {
174
+ console.log(`đŸ“Ļ Git info collected: branch=${this.runMetadata.gitInfo.branch}, commit=${this.runMetadata.gitInfo.shortCommit}, author=${this.runMetadata.gitInfo.author}`);
175
+ }
176
+ else {
177
+ console.log(`âš ī¸ Git info collection returned null - not in a git repository or git not available`);
178
+ }
179
+ }
180
+ else {
181
+ console.log(`â„šī¸ Git info collection disabled (enableGitInfo: false)`);
171
182
  }
172
183
  // Add shard information if available
173
184
  if (config.shard) {
@@ -311,8 +322,10 @@ class TestLensReporter {
311
322
  // Calculate final stats
312
323
  const totalTests = Array.from(this.testMap.values()).length;
313
324
  const passedTests = Array.from(this.testMap.values()).filter(t => t.status === 'passed').length;
325
+ // failedTests already includes timedOut tests since normalizeTestStatus converts 'timedOut' to 'failed'
314
326
  const failedTests = Array.from(this.testMap.values()).filter(t => t.status === 'failed').length;
315
327
  const skippedTests = Array.from(this.testMap.values()).filter(t => t.status === 'skipped').length;
328
+ // Track timedOut separately for reporting purposes only (not for count)
316
329
  const timedOutTests = Array.from(this.testMap.values()).filter(t => t.originalStatus === 'timedOut').length;
317
330
  // Normalize run status - if there are timeouts, treat run as failed
318
331
  const hasTimeouts = timedOutTests > 0;
@@ -326,14 +339,14 @@ class TestLensReporter {
326
339
  ...this.runMetadata,
327
340
  totalTests,
328
341
  passedTests,
329
- failedTests: failedTests + timedOutTests, // Include timeouts in failed count
342
+ failedTests, // Already includes timedOut tests (normalized to 'failed')
330
343
  skippedTests,
331
- timedOutTests,
344
+ timedOutTests, // For informational purposes
332
345
  status: normalizedRunStatus
333
346
  }
334
347
  });
335
348
  console.log(`📊 TestLens Report completed - Run ID: ${this.runId}`);
336
- console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests + timedOutTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
349
+ console.log(`đŸŽ¯ Results: ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
337
350
  }
338
351
  async sendToApi(payload) {
339
352
  try {
@@ -360,9 +373,52 @@ class TestLensReporter {
360
373
  const attachments = result.attachments;
361
374
  for (const attachment of attachments) {
362
375
  if (attachment.path) {
376
+ // Check if attachment should be processed based on config
377
+ const artifactType = this.getArtifactType(attachment.name);
378
+ const isVideo = artifactType === 'video' || attachment.contentType?.startsWith('video/');
379
+ const isScreenshot = artifactType === 'screenshot' || attachment.contentType?.startsWith('image/');
380
+ // Skip video if disabled in config
381
+ if (isVideo && !this.config.enableVideo) {
382
+ console.log(`â­ī¸ Skipping video artifact ${attachment.name} - video capture disabled in config`);
383
+ continue;
384
+ }
385
+ // Skip screenshot if disabled in config
386
+ if (isScreenshot && !this.config.enableScreenshot) {
387
+ console.log(`â­ī¸ Skipping screenshot artifact ${attachment.name} - screenshot capture disabled in config`);
388
+ continue;
389
+ }
363
390
  try {
391
+ // Determine proper filename with extension
392
+ // Playwright attachment.name often doesn't have extension, so we need to derive it
393
+ let fileName = attachment.name;
394
+ const existingExt = path.extname(fileName);
395
+ if (!existingExt) {
396
+ // Get extension from the actual file path
397
+ const pathExt = path.extname(attachment.path);
398
+ if (pathExt) {
399
+ fileName = `${fileName}${pathExt}`;
400
+ }
401
+ else if (attachment.contentType) {
402
+ // Fallback: derive extension from contentType
403
+ const mimeToExt = {
404
+ 'image/png': '.png',
405
+ 'image/jpeg': '.jpg',
406
+ 'image/gif': '.gif',
407
+ 'image/webp': '.webp',
408
+ 'video/webm': '.webm',
409
+ 'video/mp4': '.mp4',
410
+ 'application/zip': '.zip',
411
+ 'application/json': '.json',
412
+ 'text/plain': '.txt'
413
+ };
414
+ const ext = mimeToExt[attachment.contentType];
415
+ if (ext) {
416
+ fileName = `${fileName}${ext}`;
417
+ }
418
+ }
419
+ }
364
420
  // Upload to S3 first
365
- const s3Data = await this.uploadArtifactToS3(attachment.path, testId, attachment.name);
421
+ const s3Data = await this.uploadArtifactToS3(attachment.path, testId, fileName);
366
422
  // Skip if upload failed or file was too large
367
423
  if (!s3Data) {
368
424
  console.log(`â­ī¸ Skipping artifact ${attachment.name} - upload failed or file too large`);
@@ -372,7 +428,7 @@ class TestLensReporter {
372
428
  testId,
373
429
  type: this.getArtifactType(attachment.name),
374
430
  path: attachment.path,
375
- name: attachment.name,
431
+ name: fileName,
376
432
  contentType: attachment.contentType,
377
433
  fileSize: this.getFileSize(attachment.path),
378
434
  storageType: 's3',
@@ -386,7 +442,7 @@ class TestLensReporter {
386
442
  timestamp: new Date().toISOString(),
387
443
  artifact: artifactData
388
444
  });
389
- console.log(`📎 Processed artifact: ${attachment.name} (uploaded to S3)`);
445
+ console.log(`📎 Processed artifact: ${fileName} (uploaded to S3)`);
390
446
  }
391
447
  catch (error) {
392
448
  console.error(`❌ Failed to process artifact ${attachment.name}:`, error.message);
@@ -507,8 +563,8 @@ class TestLensReporter {
507
563
  commit,
508
564
  shortCommit,
509
565
  author,
510
- commitMessage,
511
- commitTimestamp,
566
+ message: commitMessage,
567
+ timestamp: commitTimestamp,
512
568
  isDirty,
513
569
  remoteName,
514
570
  remoteUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testlens-playwright-reporter",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Universal Playwright reporter for TestLens - works with both TypeScript and JavaScript projects",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",