@alternative-path/testlens-playwright-reporter 0.4.6 → 0.4.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.
Files changed (5) hide show
  1. package/README.md +163 -163
  2. package/index.js +28 -28
  3. package/index.ts +1587 -1587
  4. package/package.json +1 -1
  5. package/postinstall.js +18 -0
package/README.md CHANGED
@@ -1,163 +1,163 @@
1
- # TestLens Playwright Reporter
2
-
3
- A Playwright reporter for [TestLens](https://testlens.qa-path.com) - real-time test monitoring dashboard.
4
-
5
- ## Features
6
-
7
- - 🚀 **Real-time streaming** - Watch test results as they happen in the dashboard
8
- - 📸 **Artifact support** - Shows screenshots, videos, and traces
9
- - 🔄 **Retry tracking** - Monitor test retries and identify flaky tests
10
- - ⚡ **Cross-platform** - Works on Windows, macOS, and Linux
11
-
12
- ## Installation
13
-
14
- ```bash
15
- npm i @alternative-path/testlens-playwright-reporter
16
- ```
17
-
18
- ## Configuration
19
-
20
- ### Quick Start (Recommended)
21
-
22
- The simplest config - API key and metadata are passed via environment variables:
23
-
24
- **TypeScript (`playwright.config.ts`)**
25
- ```typescript
26
- import { defineConfig } from '@playwright/test';
27
-
28
- export default defineConfig({
29
- use: {
30
- screenshot: 'on',
31
- video: 'on',
32
- trace: 'on',
33
- },
34
- reporter: [
35
- ['testlens-playwright-reporter']
36
- // API key is auto-detected from TESTLENS_API_KEY env var
37
- // Build metadata is auto-detected from testlensBuildName/testlensBuildTag env vars
38
- ],
39
- });
40
- ```
41
-
42
- **JavaScript (`playwright.config.js`)**
43
- ```javascript
44
- const { defineConfig } = require('@playwright/test');
45
-
46
- module.exports = defineConfig({
47
- use: {
48
- screenshot: 'on',
49
- video: 'on',
50
- trace: 'on',
51
- },
52
- reporter: [
53
- ['testlens-playwright-reporter']
54
- // API key is auto-detected from TESTLENS_API_KEY env var
55
- // Build metadata is auto-detected from testlensBuildName/testlensBuildTag env vars
56
- ],
57
- });
58
- ```
59
-
60
- ### Advanced Configuration (Optional)
61
-
62
- If you prefer to set API key or metadata explicitly in config:
63
-
64
- **TypeScript (`playwright.config.ts`)**
65
- ```typescript
66
- import { defineConfig } from '@playwright/test';
67
-
68
- export default defineConfig({
69
- use: {
70
- screenshot: 'on',
71
- video: 'on',
72
- trace: 'on',
73
- },
74
- reporter: [
75
- ['@alternative-path/testlens-playwright-reporter', {
76
- apiKey: process.env.TESTLENS_API_KEY || 'your-api-key-here',
77
-
78
- // Optional: explicitly forward build metadata from env vars
79
- customMetadata: {
80
- testlensBuildName: process.env.testlensBuildName,
81
- testlensBuildTag: process.env.testlensBuildTag,
82
- },
83
- }]
84
- ],
85
- });
86
- ```
87
-
88
- **JavaScript (`playwright.config.js`)**
89
- ```javascript
90
- const { defineConfig } = require('@playwright/test');
91
-
92
- module.exports = defineConfig({
93
- use: {
94
- screenshot: 'on',
95
- video: 'on',
96
- trace: 'on',
97
- },
98
- reporter: [
99
- ['@alternative-path/testlens-playwright-reporter', {
100
- apiKey: process.env.TESTLENS_API_KEY || 'your-api-key-here',
101
-
102
- // Optional: explicitly forward build metadata from env vars
103
- customMetadata: {
104
- testlensBuildName: process.env.testlensBuildName,
105
- testlensBuildTag: process.env.testlensBuildTag,
106
- },
107
- }]
108
- ],
109
- });
110
- ```
111
-
112
- ## Run With Build Name & Tag (UI Mode)
113
-
114
- Use `testlens-cross-env` (bundled with this package) to set API key and metadata cross-platform, including Windows.
115
-
116
- ### Command
117
-
118
- ```bash
119
- npx testlens-cross-env TESTLENS_API_KEY="<your-api-key>" testlensBuildName="Testing Build Local Environment" testlensBuildTag="smoke" playwright test --ui
120
- ```
121
-
122
- ### What Gets Auto-Detected
123
-
124
- The reporter automatically reads these environment variables (no config changes needed):
125
-
126
- - **API Key**: `TESTLENS_API_KEY` (also checks: `testlens_api_key`, `TESTLENS_KEY`, `testlensApiKey`, `PLAYWRIGHT_API_KEY`, `PW_API_KEY`)
127
- - **Build Name**: `testlensBuildName` (also checks: `TESTLENS_BUILD_NAME`, `BUILDNAME`, `BUILD_NAME`)
128
- - **Build Tag**: `testlensBuildTag` (also checks: `TESTLENS_BUILD_TAG`, `BUILDTAG`, `BUILD_TAG`)
129
-
130
- ### Notes
131
-
132
- - No config changes required - just pass env vars in the command
133
- - `testlensBuildName` and `testlensBuildTag` are sent to TestLens as run `custom_metadata`
134
- - Multiple tags: use comma-separated list `testlensBuildTag="smoke,regression"`
135
-
136
- > 💡 **Tip:** Keep `screenshot`, `video`, and `trace` set to `'on'` for better debugging experience. TestLens automatically uploads these artifacts for failed tests, making it easier to identify issues.
137
-
138
- ### Configuration Options
139
-
140
- | Option | Type | Default | Description |
141
- |--------|------|---------|-------------|
142
- | `apiKey` | `string` | **Required** | Your TestLens API key |
143
-
144
- ## Artifacts
145
-
146
- TestLens automatically captures and uploads:
147
-
148
- | Artifact | Description |
149
- |----------|-------------|
150
- | **Screenshots** | Visual snapshots of test failures |
151
- | **Videos** | Full video recording of test execution |
152
- | **Traces** | Playwright trace files for step-by-step debugging |
153
-
154
- These artifacts are viewable directly in the TestLens dashboard for easy debugging.
155
-
156
- ## Requirements
157
-
158
- - Node.js >= 16.0.0
159
- - Playwright >= 1.40.0
160
-
161
- ## License
162
-
163
- MIT License
1
+ # TestLens Playwright Reporter
2
+
3
+ A Playwright reporter for [TestLens](https://testlens.qa-path.com) - real-time test monitoring dashboard.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Real-time streaming** - Watch test results as they happen in the dashboard
8
+ - 📸 **Artifact support** - Shows screenshots, videos, and traces
9
+ - 🔄 **Retry tracking** - Monitor test retries and identify flaky tests
10
+ - ⚡ **Cross-platform** - Works on Windows, macOS, and Linux
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm i @alternative-path/testlens-playwright-reporter
16
+ ```
17
+
18
+ ## Configuration
19
+
20
+ ### Quick Start (Recommended)
21
+
22
+ The simplest config - API key and metadata are passed via environment variables:
23
+
24
+ **TypeScript (`playwright.config.ts`)**
25
+ ```typescript
26
+ import { defineConfig } from '@playwright/test';
27
+
28
+ export default defineConfig({
29
+ use: {
30
+ screenshot: 'on',
31
+ video: 'on',
32
+ trace: 'on',
33
+ },
34
+ reporter: [
35
+ ['testlens-playwright-reporter']
36
+ // API key is auto-detected from TESTLENS_API_KEY env var
37
+ // Build metadata is auto-detected from testlensBuildName/testlensBuildTag env vars
38
+ ],
39
+ });
40
+ ```
41
+
42
+ **JavaScript (`playwright.config.js`)**
43
+ ```javascript
44
+ const { defineConfig } = require('@playwright/test');
45
+
46
+ module.exports = defineConfig({
47
+ use: {
48
+ screenshot: 'on',
49
+ video: 'on',
50
+ trace: 'on',
51
+ },
52
+ reporter: [
53
+ ['testlens-playwright-reporter']
54
+ // API key is auto-detected from TESTLENS_API_KEY env var
55
+ // Build metadata is auto-detected from testlensBuildName/testlensBuildTag env vars
56
+ ],
57
+ });
58
+ ```
59
+
60
+ ### Advanced Configuration (Optional)
61
+
62
+ If you prefer to set API key or metadata explicitly in config:
63
+
64
+ **TypeScript (`playwright.config.ts`)**
65
+ ```typescript
66
+ import { defineConfig } from '@playwright/test';
67
+
68
+ export default defineConfig({
69
+ use: {
70
+ screenshot: 'on',
71
+ video: 'on',
72
+ trace: 'on',
73
+ },
74
+ reporter: [
75
+ ['@alternative-path/testlens-playwright-reporter', {
76
+ apiKey: process.env.TESTLENS_API_KEY || 'your-api-key-here',
77
+
78
+ // Optional: explicitly forward build metadata from env vars
79
+ customMetadata: {
80
+ testlensBuildName: process.env.testlensBuildName,
81
+ testlensBuildTag: process.env.testlensBuildTag,
82
+ },
83
+ }]
84
+ ],
85
+ });
86
+ ```
87
+
88
+ **JavaScript (`playwright.config.js`)**
89
+ ```javascript
90
+ const { defineConfig } = require('@playwright/test');
91
+
92
+ module.exports = defineConfig({
93
+ use: {
94
+ screenshot: 'on',
95
+ video: 'on',
96
+ trace: 'on',
97
+ },
98
+ reporter: [
99
+ ['@alternative-path/testlens-playwright-reporter', {
100
+ apiKey: process.env.TESTLENS_API_KEY || 'your-api-key-here',
101
+
102
+ // Optional: explicitly forward build metadata from env vars
103
+ customMetadata: {
104
+ testlensBuildName: process.env.testlensBuildName,
105
+ testlensBuildTag: process.env.testlensBuildTag,
106
+ },
107
+ }]
108
+ ],
109
+ });
110
+ ```
111
+
112
+ ## Run With Build Name & Tag (UI Mode)
113
+
114
+ Use `testlens-cross-env` (bundled with this package) to set API key and metadata cross-platform, including Windows.
115
+
116
+ ### Command
117
+
118
+ ```bash
119
+ npx testlens-cross-env TESTLENS_API_KEY="<your-api-key>" testlensBuildName="Testing Build Local Environment" testlensBuildTag="smoke" playwright test --ui
120
+ ```
121
+
122
+ ### What Gets Auto-Detected
123
+
124
+ The reporter automatically reads these environment variables (no config changes needed):
125
+
126
+ - **API Key**: `TESTLENS_API_KEY` (also checks: `testlens_api_key`, `TESTLENS_KEY`, `testlensApiKey`, `PLAYWRIGHT_API_KEY`, `PW_API_KEY`)
127
+ - **Build Name**: `testlensBuildName` (also checks: `TESTLENS_BUILD_NAME`, `BUILDNAME`, `BUILD_NAME`)
128
+ - **Build Tag**: `testlensBuildTag` (also checks: `TESTLENS_BUILD_TAG`, `BUILDTAG`, `BUILD_TAG`)
129
+
130
+ ### Notes
131
+
132
+ - No config changes required - just pass env vars in the command
133
+ - `testlensBuildName` and `testlensBuildTag` are sent to TestLens as run `custom_metadata`
134
+ - Multiple tags: use comma-separated list `testlensBuildTag="smoke,regression"`
135
+
136
+ > 💡 **Tip:** Keep `screenshot`, `video`, and `trace` set to `'on'` for better debugging experience. TestLens automatically uploads these artifacts for failed tests, making it easier to identify issues.
137
+
138
+ ### Configuration Options
139
+
140
+ | Option | Type | Default | Description |
141
+ |--------|------|---------|-------------|
142
+ | `apiKey` | `string` | **Required** | Your TestLens API key |
143
+
144
+ ## Artifacts
145
+
146
+ TestLens automatically captures and uploads:
147
+
148
+ | Artifact | Description |
149
+ |----------|-------------|
150
+ | **Screenshots** | Visual snapshots of test failures |
151
+ | **Videos** | Full video recording of test execution |
152
+ | **Traces** | Playwright trace files for step-by-step debugging |
153
+
154
+ These artifacts are viewable directly in the TestLens dashboard for easy debugging.
155
+
156
+ ## Requirements
157
+
158
+ - Node.js >= 16.0.0
159
+ - Playwright >= 1.40.0
160
+
161
+ ## License
162
+
163
+ MIT License
package/index.js CHANGED
@@ -105,11 +105,11 @@ class TestLensReporter {
105
105
  // For testlensBuildTag, support comma-separated values
106
106
  if (key === 'testlensBuildTag' && value.includes(',')) {
107
107
  customArgs[key] = value.split(',').map(tag => tag.trim()).filter(tag => tag);
108
- logger.info(`✓ Found ${envVar}=${value} (mapped to '${key}' as array of ${customArgs[key].length} tags)`);
108
+ logger.debug(`✓ Found ${envVar}=${value} (mapped to '${key}' as array of ${customArgs[key].length} tags)`);
109
109
  }
110
110
  else {
111
111
  customArgs[key] = value;
112
- logger.info(`✓ Found ${envVar}=${value} (mapped to '${key}')`);
112
+ logger.debug(`✓ Found ${envVar}=${value} (mapped to '${key}')`);
113
113
  }
114
114
  break; // Use first match
115
115
  }
@@ -162,7 +162,7 @@ class TestLensReporter {
162
162
  throw new Error('API_KEY is required for TestLensReporter. Pass it as apiKey option in your playwright config or set one of these environment variables: TESTLENS_API_KEY, TESTLENS_KEY, PLAYWRIGHT_API_KEY, PW_API_KEY, API_KEY, or APIKEY.');
163
163
  }
164
164
  if (apiKey !== options.apiKey) {
165
- logger.info('✓ Using API key from environment variable');
165
+ logger.debug('✓ Using API key from environment variable');
166
166
  }
167
167
  // Default environment to allow self-signed certs unless explicitly set
168
168
  if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === undefined) {
@@ -173,18 +173,18 @@ class TestLensReporter {
173
173
  // Check various ways SSL validation can be disabled or enforced (in order of precedence)
174
174
  if (this.config.ignoreSslErrors === true) {
175
175
  rejectUnauthorized = false;
176
- logger.warn('[WARN] SSL certificate validation disabled via ignoreSslErrors option');
176
+ logger.debug('[DEBUG] SSL certificate validation disabled via ignoreSslErrors option');
177
177
  }
178
178
  else if (this.config.rejectUnauthorized === false) {
179
179
  rejectUnauthorized = false;
180
- logger.warn('[WARN] SSL certificate validation disabled via rejectUnauthorized option');
180
+ logger.debug('[DEBUG] SSL certificate validation disabled via rejectUnauthorized option');
181
181
  }
182
182
  else if (this.config.rejectUnauthorized === true) {
183
183
  rejectUnauthorized = true;
184
184
  }
185
185
  else if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0') {
186
186
  rejectUnauthorized = false;
187
- logger.warn('[WARN] SSL certificate validation disabled via NODE_TLS_REJECT_UNAUTHORIZED environment variable');
187
+ logger.debug('[DEBUG] SSL certificate validation disabled via NODE_TLS_REJECT_UNAUTHORIZED environment variable');
188
188
  }
189
189
  else if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === '1') {
190
190
  rejectUnauthorized = true;
@@ -229,11 +229,11 @@ class TestLensReporter {
229
229
  this.runCreationFailed = false;
230
230
  // Log custom metadata if any
231
231
  if (this.config.customMetadata && Object.keys(this.config.customMetadata).length > 0) {
232
- logger.info('\n[METADATA] Custom Metadata Detected:');
232
+ logger.debug('\n[METADATA] Custom Metadata Detected:');
233
233
  Object.entries(this.config.customMetadata).forEach(([key, value]) => {
234
- logger.info(` ${key}: ${value}`);
234
+ logger.debug(` ${key}: ${value}`);
235
235
  });
236
- logger.info('');
236
+ logger.debug('');
237
237
  }
238
238
  }
239
239
  initializeRunMetadata() {
@@ -296,27 +296,27 @@ class TestLensReporter {
296
296
  return status;
297
297
  }
298
298
  async onBegin(config, suite) {
299
- logger.info(`[REPORTER] source=${__filename} enableArtifacts=${this.config.enableArtifacts}`);
299
+ logger.debug(`[REPORTER] source=${__filename} enableArtifacts=${this.config.enableArtifacts}`);
300
300
  // Show Build Name if provided, otherwise show Run ID
301
301
  if (this.runMetadata.testlensBuildName) {
302
- logger.info(`TestLens Reporter starting - Build: ${this.runMetadata.testlensBuildName}`);
303
- logger.info(` Run ID: ${this.runId}`);
302
+ logger.debug(`TestLens Reporter starting - Build: ${this.runMetadata.testlensBuildName}`);
303
+ logger.debug(` Run ID: ${this.runId}`);
304
304
  }
305
305
  else {
306
- logger.info(`TestLens Reporter starting - Run ID: ${this.runId}`);
306
+ logger.debug(`TestLens Reporter starting - Run ID: ${this.runId}`);
307
307
  }
308
308
  // Collect Git information if enabled
309
309
  if (this.config.enableGitInfo) {
310
310
  this.runMetadata.gitInfo = await this.collectGitInfo();
311
311
  if (this.runMetadata.gitInfo) {
312
- logger.info(`Git info collected: branch=${this.runMetadata.gitInfo.branch}, commit=${this.runMetadata.gitInfo.shortCommit}, author=${this.runMetadata.gitInfo.author}`);
312
+ logger.debug(`Git info collected: branch=${this.runMetadata.gitInfo.branch}, commit=${this.runMetadata.gitInfo.shortCommit}, author=${this.runMetadata.gitInfo.author}`);
313
313
  }
314
314
  else {
315
315
  logger.warn(`[WARN] Git info collection returned null - not in a git repository or git not available`);
316
316
  }
317
317
  }
318
318
  else {
319
- logger.info(`[INFO] Git info collection disabled (enableGitInfo: false)`);
319
+ logger.debug(`[INFO] Git info collection disabled (enableGitInfo: false)`);
320
320
  }
321
321
  // Add shard information if available
322
322
  if (config.shard) {
@@ -335,7 +335,7 @@ class TestLensReporter {
335
335
  }
336
336
  async onTestBegin(test, result) {
337
337
  // Log which test is starting
338
- logger.info(`[TEST] Running test: ${test.title}`);
338
+ logger.debug(`[TEST] Running test: ${test.title}`);
339
339
  const specPath = test.location.file;
340
340
  const specKey = `${specPath}-${test.parent.title}`;
341
341
  // Create or update spec data
@@ -408,7 +408,7 @@ class TestLensReporter {
408
408
  async onTestEnd(test, result) {
409
409
  const testId = this.getTestId(test);
410
410
  let testData = this.testMap.get(testId);
411
- logger.info(`[ARTIFACTS] attachments=${result.attachments?.length ?? 0}`);
411
+ logger.debug(`[ARTIFACTS] attachments=${result.attachments?.length ?? 0}`);
412
412
  if (result.attachments && result.attachments.length > 0) {
413
413
  for (const attachment of result.attachments) {
414
414
  const artifactType = this.getArtifactType(attachment.name);
@@ -421,10 +421,10 @@ class TestLensReporter {
421
421
  }
422
422
  }
423
423
  }
424
- logger.info(`[TestLens] onTestEnd called for test: ${test.title}, status: ${result.status}, testData exists: ${!!testData}`);
424
+ logger.debug(`[TestLens] onTestEnd called for test: ${test.title}, status: ${result.status}, testData exists: ${!!testData}`);
425
425
  // For skipped tests, onTestBegin might not be called, so we need to create the test data here
426
426
  if (!testData) {
427
- logger.info(`[TestLens] Creating test data for skipped/uncreated test: ${test.title}`);
427
+ logger.debug(`[TestLens] Creating test data for skipped/uncreated test: ${test.title}`);
428
428
  // Create spec data if not exists (skipped tests might not have spec data either)
429
429
  const specPath = test.location.file;
430
430
  const specKey = `${specPath}-${test.parent.title}`;
@@ -569,7 +569,7 @@ class TestLensReporter {
569
569
  });
570
570
  // Send testEnd event for all tests, regardless of status
571
571
  // This ensures tests that are interrupted or have unexpected statuses are properly recorded
572
- logger.info(`[TestLens] Sending testEnd - testId: ${testData.id}, status: ${testData.status}, originalStatus: ${testData.originalStatus}`);
572
+ logger.debug(`[TestLens] Sending testEnd - testId: ${testData.id}, status: ${testData.status}, originalStatus: ${testData.originalStatus}`);
573
573
  // Send test end event to API and get response
574
574
  const testEndResponse = await this.sendToApi({
575
575
  type: 'testEnd',
@@ -680,7 +680,7 @@ class TestLensReporter {
680
680
  console.log(summary);
681
681
  }
682
682
  else {
683
- logger.info(summary);
683
+ logger.debug(summary);
684
684
  }
685
685
  // Calculate final stats
686
686
  const totalTests = Array.from(this.testMap.values()).length;
@@ -710,13 +710,13 @@ class TestLensReporter {
710
710
  });
711
711
  // Show Build Name if provided, otherwise show Run ID
712
712
  if (this.runMetadata.testlensBuildName) {
713
- logger.info(`[COMPLETE] TestLens Report completed - Build: ${this.runMetadata.testlensBuildName}`);
714
- logger.info(` Run ID: ${this.runId}`);
713
+ logger.debug(`[COMPLETE] TestLens Report completed - Build: ${this.runMetadata.testlensBuildName}`);
714
+ logger.debug(` Run ID: ${this.runId}`);
715
715
  }
716
716
  else {
717
- logger.info(`[COMPLETE] TestLens Report completed - Run ID: ${this.runId}`);
717
+ logger.debug(`[COMPLETE] TestLens Report completed - Run ID: ${this.runId}`);
718
718
  }
719
- logger.info(`[RESULTS] ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
719
+ logger.debug(`[RESULTS] ${passedTests} passed, ${failedTests} failed (${timedOutTests} timeouts), ${skippedTests} skipped`);
720
720
  }
721
721
  async sendToApi(payload) {
722
722
  // Skip sending if run creation already failed
@@ -953,13 +953,13 @@ class TestLensReporter {
953
953
  codeBlocks,
954
954
  testSuiteName: path.basename(specPath).replace(/\.(spec|test)\.(js|ts)$/, '')
955
955
  });
956
- logger.info(`Sent ${codeBlocks.length} code blocks for: ${path.basename(specPath)}`);
956
+ logger.debug(`Sent ${codeBlocks.length} code blocks for: ${path.basename(specPath)}`);
957
957
  }
958
958
  catch (error) {
959
959
  const errorData = error?.response?.data;
960
960
  // Handle duplicate spec code blocks gracefully (when re-running tests)
961
961
  if (errorData?.error && errorData.error.includes('duplicate key value violates unique constraint')) {
962
- logger.info(`[INFO] Spec code blocks already exist for: ${path.basename(specPath)} (skipped)`);
962
+ logger.debug(`[INFO] Spec code blocks already exist for: ${path.basename(specPath)} (skipped)`);
963
963
  return;
964
964
  }
965
965
  logger.error(`Failed to send spec code blocks: ${errorData || error?.message || 'Unknown error'}`);
@@ -1044,7 +1044,7 @@ class TestLensReporter {
1044
1044
  }
1045
1045
  catch (e) {
1046
1046
  // Remote info is optional - handle gracefully
1047
- logger.info('[INFO] No git remote configured, skipping remote info');
1047
+ logger.debug('[INFO] No git remote configured, skipping remote info');
1048
1048
  }
1049
1049
  const isDirty = (0, child_process_1.execSync)('git status --porcelain', { encoding: 'utf-8' }).trim().length > 0;
1050
1050
  return {