@testivai/witness-playwright 0.1.0 → 0.1.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @testivai/witness-playwright
2
2
 
3
- **Status**: ✅ Production Ready | **Last Updated**: December 21, 2025
3
+ **Status**: ✅ Production Ready | **Last Updated**: January 9, 2026
4
4
 
5
5
  **Project:** @testivai/witness-playwright (MVP - 1 Month Plan)
6
6
 
@@ -16,6 +16,18 @@ This package provides two main exports:
16
16
 
17
17
  To use the reporter, you need to configure it in your `playwright.config.ts` file. You must also provide your API URL and Key via environment variables (`TESTIVAI_API_URL` and `TESTIVAI_API_KEY`).
18
18
 
19
+ **Get Your API Key:**
20
+ 1. Go to your TestivAI dashboard
21
+ 2. Create a new project
22
+ 3. Copy your API key (format: `tstvai-xxxxxxxxxxxx`)
23
+
24
+ **Environment Setup:**
25
+ ```bash
26
+ # Create .env file
27
+ echo "TESTIVAI_API_KEY=tstvai-your-key-here" > .env
28
+ echo "TESTIVAI_API_URL=https://core-api-147980626268.us-central1.run.app" >> .env
29
+ ```
30
+
19
31
  ```typescript
20
32
  // playwright.config.ts
21
33
  import { defineConfig } from '@playwright/test';
package/dist/cli/init.js CHANGED
@@ -126,11 +126,17 @@ async function createConfigFile() {
126
126
  console.log('📁 Config file:', configPath);
127
127
  console.log('');
128
128
  console.log('📖 Next steps:');
129
- console.log(' 1. Review and customize the configuration in testivai.config.ts');
130
- console.log(' 2. Update your playwright.config.ts to use TestivAI reporter');
131
- console.log(' 3. Run your tests with: npx playwright test');
129
+ console.log(' 1. Set up environment variables:');
130
+ console.log(' TESTIVAI_API_KEY=tstvai-your-key-here');
131
+ console.log(' TESTIVAI_API_URL=https://core-api-147980626268.us-central1.run.app');
132
132
  console.log('');
133
- console.log('💡 Need help? Check the comments in testivai.config.ts for examples');
133
+ console.log(' 2. Update your playwright.config.ts to use TestivAI reporter:');
134
+ console.log(' reporter: [[\'@testivai/witness-playwright/reporter\']]');
135
+ console.log('');
136
+ console.log(' 3. Review and customize testivai.config.ts');
137
+ console.log(' 4. Run your tests: npx playwright test');
138
+ console.log('');
139
+ console.log('💡 Get your API key from: https://dashboard-147980626268.us-central1.run.app');
134
140
  }
135
141
  catch (error) {
136
142
  console.error('❌ Failed to create configuration file:', error);
package/dist/index.d.ts CHANGED
@@ -3,5 +3,4 @@ export declare const testivai: {
3
3
  witness: typeof snapshot;
4
4
  };
5
5
  export * from './types';
6
- export * from './reporter';
7
6
  export * from './ci';
package/dist/index.js CHANGED
@@ -20,5 +20,4 @@ exports.testivai = {
20
20
  witness: snapshot_1.snapshot,
21
21
  };
22
22
  __exportStar(require("./types"), exports);
23
- __exportStar(require("./reporter"), exports);
24
23
  __exportStar(require("./ci"), exports);
@@ -0,0 +1,2 @@
1
+ import { TestivAIPlaywrightReporter } from './reporter';
2
+ export = TestivAIPlaywrightReporter;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Entry point for Playwright reporter
3
+ // Playwright expects: module.exports = ReporterClass
4
+ const reporter_1 = require("./reporter");
5
+ module.exports = reporter_1.TestivAIPlaywrightReporter;
@@ -13,4 +13,4 @@ export declare class TestivAIPlaywrightReporter implements Reporter {
13
13
  onBegin(config: FullConfig, suite: Suite): Promise<void>;
14
14
  onEnd(result: FullResult): Promise<void>;
15
15
  }
16
- export {};
16
+ export default TestivAIPlaywrightReporter;
package/dist/reporter.js CHANGED
@@ -111,10 +111,23 @@ class TestivAIPlaywrightReporter {
111
111
  const metadata = await fs.readJson(metadataPath);
112
112
  const domPath = metadata.files.dom;
113
113
  const screenshotPath = metadata.files.screenshot;
114
+ // Extract the first selector's layout data (usually 'body')
115
+ const layoutKeys = Object.keys(metadata.layout || {});
116
+ if (layoutKeys.length === 0) {
117
+ console.warn(`Testivai Reporter: No layout data found for ${metadata.snapshotName}, skipping...`);
118
+ continue;
119
+ }
120
+ const firstSelector = layoutKeys[0];
121
+ const layoutData = metadata.layout[firstSelector];
114
122
  const snapshotPayload = {
115
123
  ...metadata,
116
124
  dom: { html: await fs.readFile(domPath, 'utf-8') },
117
- layout: metadata.layout,
125
+ layout: {
126
+ x: layoutData.x,
127
+ y: layoutData.y,
128
+ width: layoutData.width,
129
+ height: layoutData.height
130
+ },
118
131
  testivaiConfig: metadata.testivaiConfig
119
132
  };
120
133
  snapshots.push(snapshotPayload);
@@ -129,9 +142,12 @@ class TestivAIPlaywrightReporter {
129
142
  };
130
143
  // Start batch and get upload URLs
131
144
  const startBatchResponse = await axios_1.default.post(`${this.options.apiUrl}/api/v1/ingest/start-batch`, batchPayload, {
132
- headers: { 'Authorization': `Bearer ${this.options.apiKey}` },
145
+ headers: { 'X-API-KEY': this.options.apiKey },
133
146
  });
134
- const { batchId, uploadInstructions } = startBatchResponse.data;
147
+ console.log('Testivai Reporter: API Response:', JSON.stringify(startBatchResponse.data, null, 2));
148
+ // Handle both snake_case and camelCase response formats
149
+ const batchId = startBatchResponse.data.batch_id || startBatchResponse.data.batchId;
150
+ const uploadInstructions = startBatchResponse.data.upload_instructions || startBatchResponse.data.uploadInstructions;
135
151
  // Upload files
136
152
  const uploadPromises = filesToUpload.map((file, index) => {
137
153
  const instruction = uploadInstructions[index];
@@ -140,7 +156,7 @@ class TestivAIPlaywrightReporter {
140
156
  await Promise.all(uploadPromises);
141
157
  // Finalize batch
142
158
  await axios_1.default.post(`${this.options.apiUrl}/api/v1/ingest/finish-batch/${batchId}`, {}, {
143
- headers: { 'Authorization': `Bearer ${this.options.apiKey}` },
159
+ headers: { 'X-API-KEY': this.options.apiKey },
144
160
  });
145
161
  console.log(`Testivai Reporter: Successfully uploaded ${snapshots.length} snapshots with Batch ID: ${batchId}`);
146
162
  // Clean up temp files
@@ -148,8 +164,14 @@ class TestivAIPlaywrightReporter {
148
164
  console.log('Testivai Reporter: Cleaned up temporary evidence files.');
149
165
  }
150
166
  catch (error) {
151
- console.error('Testivai Reporter: An error occurred during the onEnd hook:', error);
167
+ console.error('Testivai Reporter: An error occurred during the onEnd hook:', error.message);
168
+ console.error('Error stack:', error.stack);
169
+ if (error.response) {
170
+ console.error('Response status:', error.response.status);
171
+ console.error('Response data:', JSON.stringify(error.response.data, null, 2));
172
+ }
152
173
  }
153
174
  }
154
175
  }
155
176
  exports.TestivAIPlaywrightReporter = TestivAIPlaywrightReporter;
177
+ exports.default = TestivAIPlaywrightReporter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testivai/witness-playwright",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Playwright sensor for Testivai Visual Regression Test system",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "exports": {
11
11
  ".": "./dist/index.js",
12
- "./reporter": "./dist/reporter.js",
12
+ "./reporter": "./dist/reporter-entry.js",
13
13
  "./cli": "./dist/cli/init.js"
14
14
  },
15
15
  "scripts": {
package/progress.md CHANGED
@@ -612,9 +612,60 @@ The Playwright SDK provides two main components that are production-ready:
612
612
 
613
613
  ---
614
614
 
615
- **Last Updated**: December 17, 2025
616
- **Status**: 🎉 MVP COMPLETE ✅ - Production ready
615
+ ## NPM Publication & API Key Format Update (January 9, 2026)
616
+
617
+ ### SDK Published to npm ✅ COMPLETE
618
+
619
+ **Goal**: Publish SDK to npm registry for public consumption and update documentation for new API key format.
620
+
621
+ #### Changes Implemented
622
+
623
+ 1. **NPM Publication** ✅
624
+ - Published `@testivai/witness-playwright@0.1.0` to npm registry
625
+ - Package now publicly available: https://www.npmjs.com/package/@testivai/witness-playwright
626
+ - Users can install via: `npm install @testivai/witness-playwright`
627
+
628
+ 2. **Documentation Updates** ✅
629
+ - Updated README.md with new API key format (`tstvai-xxxxxxxxxxxx`)
630
+ - Added "Get Your API Key" section with step-by-step instructions
631
+ - Added environment setup examples
632
+ - Updated all code examples to show correct usage
633
+
634
+ 3. **Integration Tests** ✅
635
+ - Created visual regression tests in `integration-tests/tests/visual/`
636
+ - Tests use published npm package (not local file reference)
637
+ - All 10 visual tests passing
638
+ - Tests capture dashboard snapshots and send to TestivAI backend
639
+
640
+ 4. **Example Usage** ✅
641
+ ```typescript
642
+ import { test } from '@playwright/test';
643
+ import { testivai } from '@testivai/witness-playwright';
644
+
645
+ test('visual test', async ({ page }, testInfo) => {
646
+ await page.goto('https://example.com');
647
+ await testivai.witness(page, testInfo, 'homepage');
648
+ });
649
+ ```
650
+
651
+ #### API Key Format
652
+ - **New Format**: `tstvai-{32-character-secure-random-string}`
653
+ - **Example**: `tstvai-Ml5Ahr4vxHNht9WJPZ0LndDBQIkEfT9OvpXqB-NGjOs`
654
+ - **Masked Display**: `tstvai-**************NGjOs` (last 6 chars visible)
655
+
656
+ #### Files Updated
657
+ - `README.md` - Added API key format and setup instructions
658
+ - `package.json` - Published version 0.1.0 to npm
659
+ - `integration-tests/package.json` - Uses npm package instead of local file
660
+ - `integration-tests/tests/visual/dashboard-visual.spec.ts` - Example visual tests
661
+
662
+ ---
663
+
664
+ **Last Updated**: January 9, 2026
665
+ **Status**: 🎉 PUBLISHED TO NPM ✅ - Publicly available
666
+ **NPM Package**: @testivai/witness-playwright@0.1.0
617
667
  **Core Features**: Evidence capture and batch upload fully functional
618
668
  **Configuration**: ✅ COMPLETE - End-to-end flow working
669
+ **API Key Format**: tstvai-{secure-random-string}
619
670
  **Known Issues**: Minor UX improvements (retry logic, progress reporting)
620
671
  **Blocker**: None - All critical features implemented
package/src/cli/init.ts CHANGED
@@ -96,11 +96,17 @@ async function createConfigFile(): Promise<void> {
96
96
  console.log('📁 Config file:', configPath);
97
97
  console.log('');
98
98
  console.log('📖 Next steps:');
99
- console.log(' 1. Review and customize the configuration in testivai.config.ts');
100
- console.log(' 2. Update your playwright.config.ts to use TestivAI reporter');
101
- console.log(' 3. Run your tests with: npx playwright test');
99
+ console.log(' 1. Set up environment variables:');
100
+ console.log(' TESTIVAI_API_KEY=tstvai-your-key-here');
101
+ console.log(' TESTIVAI_API_URL=https://core-api-147980626268.us-central1.run.app');
102
102
  console.log('');
103
- console.log('💡 Need help? Check the comments in testivai.config.ts for examples');
103
+ console.log(' 2. Update your playwright.config.ts to use TestivAI reporter:');
104
+ console.log(' reporter: [[\'@testivai/witness-playwright/reporter\']]');
105
+ console.log('');
106
+ console.log(' 3. Review and customize testivai.config.ts');
107
+ console.log(' 4. Run your tests: npx playwright test');
108
+ console.log('');
109
+ console.log('💡 Get your API key from: https://dashboard-147980626268.us-central1.run.app');
104
110
 
105
111
  } catch (error) {
106
112
  console.error('❌ Failed to create configuration file:', error);
package/src/index.ts CHANGED
@@ -5,5 +5,4 @@ export const testivai = {
5
5
  };
6
6
 
7
7
  export * from './types';
8
- export * from './reporter';
9
8
  export * from './ci';
@@ -0,0 +1,6 @@
1
+ // Entry point for Playwright reporter
2
+ // Playwright expects: module.exports = ReporterClass
3
+ import { TestivAIPlaywrightReporter } from './reporter';
4
+
5
+ // This will compile to: module.exports = TestivAIPlaywrightReporter
6
+ export = TestivAIPlaywrightReporter;
package/src/reporter.ts CHANGED
@@ -94,10 +94,24 @@ export class TestivAIPlaywrightReporter implements Reporter {
94
94
  const domPath = metadata.files.dom;
95
95
  const screenshotPath = metadata.files.screenshot;
96
96
 
97
+ // Extract the first selector's layout data (usually 'body')
98
+ const layoutKeys = Object.keys(metadata.layout || {});
99
+ if (layoutKeys.length === 0) {
100
+ console.warn(`Testivai Reporter: No layout data found for ${metadata.snapshotName}, skipping...`);
101
+ continue;
102
+ }
103
+ const firstSelector = layoutKeys[0];
104
+ const layoutData = metadata.layout[firstSelector];
105
+
97
106
  const snapshotPayload: SnapshotPayload = {
98
107
  ...metadata,
99
108
  dom: { html: await fs.readFile(domPath, 'utf-8') },
100
- layout: metadata.layout,
109
+ layout: {
110
+ x: layoutData.x,
111
+ y: layoutData.y,
112
+ width: layoutData.width,
113
+ height: layoutData.height
114
+ },
101
115
  testivaiConfig: metadata.testivaiConfig
102
116
  };
103
117
  snapshots.push(snapshotPayload);
@@ -115,10 +129,14 @@ export class TestivAIPlaywrightReporter implements Reporter {
115
129
 
116
130
  // Start batch and get upload URLs
117
131
  const startBatchResponse = await axios.post(`${this.options.apiUrl}/api/v1/ingest/start-batch`, batchPayload, {
118
- headers: { 'Authorization': `Bearer ${this.options.apiKey}` },
132
+ headers: { 'X-API-KEY': this.options.apiKey },
119
133
  });
120
134
 
121
- const { batchId, uploadInstructions } = startBatchResponse.data;
135
+ console.log('Testivai Reporter: API Response:', JSON.stringify(startBatchResponse.data, null, 2));
136
+
137
+ // Handle both snake_case and camelCase response formats
138
+ const batchId = startBatchResponse.data.batch_id || startBatchResponse.data.batchId;
139
+ const uploadInstructions = startBatchResponse.data.upload_instructions || startBatchResponse.data.uploadInstructions;
122
140
 
123
141
  // Upload files
124
142
  const uploadPromises = filesToUpload.map((file, index) => {
@@ -132,7 +150,7 @@ export class TestivAIPlaywrightReporter implements Reporter {
132
150
 
133
151
  // Finalize batch
134
152
  await axios.post(`${this.options.apiUrl}/api/v1/ingest/finish-batch/${batchId}`, {}, {
135
- headers: { 'Authorization': `Bearer ${this.options.apiKey}` },
153
+ headers: { 'X-API-KEY': this.options.apiKey },
136
154
  });
137
155
 
138
156
  console.log(`Testivai Reporter: Successfully uploaded ${snapshots.length} snapshots with Batch ID: ${batchId}`);
@@ -141,8 +159,15 @@ export class TestivAIPlaywrightReporter implements Reporter {
141
159
  await fs.emptyDir(this.tempDir);
142
160
  console.log('Testivai Reporter: Cleaned up temporary evidence files.');
143
161
 
144
- } catch (error) {
145
- console.error('Testivai Reporter: An error occurred during the onEnd hook:', error);
162
+ } catch (error: any) {
163
+ console.error('Testivai Reporter: An error occurred during the onEnd hook:', error.message);
164
+ console.error('Error stack:', error.stack);
165
+ if (error.response) {
166
+ console.error('Response status:', error.response.status);
167
+ console.error('Response data:', JSON.stringify(error.response.data, null, 2));
168
+ }
146
169
  }
147
170
  }
148
171
  }
172
+
173
+ export default TestivAIPlaywrightReporter;
package/tsconfig.json CHANGED
@@ -7,6 +7,7 @@
7
7
  "outDir": "./dist",
8
8
  "strict": true,
9
9
  "esModuleInterop": true,
10
+ "allowSyntheticDefaultImports": true,
10
11
  "skipLibCheck": true,
11
12
  "forceConsistentCasingInFileNames": true,
12
13
  "resolveJsonModule": true,