@testivai/witness-cdp 1.0.0
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/LICENSE +21 -0
- package/README.md +405 -0
- package/dist/__tests__/setup.d.ts +4 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +24 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/bin/testivai.d.ts +3 -0
- package/dist/bin/testivai.d.ts.map +1 -0
- package/dist/bin/testivai.js +48 -0
- package/dist/bin/testivai.js.map +1 -0
- package/dist/cdp/binding.d.ts +56 -0
- package/dist/cdp/binding.d.ts.map +1 -0
- package/dist/cdp/binding.js +364 -0
- package/dist/cdp/binding.js.map +1 -0
- package/dist/cdp/capture.d.ts +61 -0
- package/dist/cdp/capture.d.ts.map +1 -0
- package/dist/cdp/capture.js +422 -0
- package/dist/cdp/capture.js.map +1 -0
- package/dist/cdp/client.d.ts +63 -0
- package/dist/cdp/client.d.ts.map +1 -0
- package/dist/cdp/client.js +279 -0
- package/dist/cdp/client.js.map +1 -0
- package/dist/cdp/discovery.d.ts +33 -0
- package/dist/cdp/discovery.d.ts.map +1 -0
- package/dist/cdp/discovery.js +157 -0
- package/dist/cdp/discovery.js.map +1 -0
- package/dist/ci.d.ts +31 -0
- package/dist/ci.d.ts.map +1 -0
- package/dist/ci.js +118 -0
- package/dist/ci.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +122 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/capture.d.ts +3 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +143 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +255 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +438 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +329 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/file-naming.d.ts +31 -0
- package/dist/utils/file-naming.d.ts.map +1 -0
- package/dist/utils/file-naming.js +137 -0
- package/dist/utils/file-naming.js.map +1 -0
- package/dist/utils/framework-detect.d.ts +31 -0
- package/dist/utils/framework-detect.d.ts.map +1 -0
- package/dist/utils/framework-detect.js +379 -0
- package/dist/utils/framework-detect.js.map +1 -0
- package/dist/utils/logger.d.ts +29 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +114 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/process.d.ts +61 -0
- package/dist/utils/process.d.ts.map +1 -0
- package/dist/utils/process.js +208 -0
- package/dist/utils/process.js.map +1 -0
- package/dist/utils/template-generator.d.ts +36 -0
- package/dist/utils/template-generator.d.ts.map +1 -0
- package/dist/utils/template-generator.js +255 -0
- package/dist/utils/template-generator.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runCommand = void 0;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const client_1 = require("../cdp/client");
|
|
43
|
+
const binding_1 = require("../cdp/binding");
|
|
44
|
+
const discovery_1 = require("../cdp/discovery");
|
|
45
|
+
const common_1 = require("@testivai/common");
|
|
46
|
+
const process_1 = require("../utils/process");
|
|
47
|
+
const logger_1 = require("../utils/logger");
|
|
48
|
+
const ci_1 = require("../ci");
|
|
49
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
50
|
+
exports.runCommand = new commander_1.Command('run')
|
|
51
|
+
.description('Run visual tests with automatic capture')
|
|
52
|
+
.argument('<command>', 'Test command to execute (e.g., "npm test", "cypress run")')
|
|
53
|
+
.option('-p, --port <number>', 'Chrome DevTools Protocol port')
|
|
54
|
+
.option('-b, --batch-id <id>', 'Specify batch ID (auto-generated if not provided)')
|
|
55
|
+
.option('--debug', 'Enable debug logging for snapshots')
|
|
56
|
+
.action(async (command, options) => {
|
|
57
|
+
let client = null;
|
|
58
|
+
let processManager = null;
|
|
59
|
+
let batchId = null;
|
|
60
|
+
// Setup signal handlers for cleanup
|
|
61
|
+
(0, process_1.setupSignalHandlers)(async () => {
|
|
62
|
+
logger_1.logger.info('Cleaning up...');
|
|
63
|
+
if (batchId) {
|
|
64
|
+
await finishBatch(batchId);
|
|
65
|
+
}
|
|
66
|
+
if (client) {
|
|
67
|
+
await client.disconnect();
|
|
68
|
+
}
|
|
69
|
+
if (processManager) {
|
|
70
|
+
processManager.kill();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
// Load configuration
|
|
75
|
+
const config = (0, common_1.loadConfig)();
|
|
76
|
+
const apiKey = (0, common_1.getApiKey)();
|
|
77
|
+
// Check debug flag from command line or config
|
|
78
|
+
const isDebug = options.debug || config?.debug || false;
|
|
79
|
+
if (!apiKey) {
|
|
80
|
+
logger_1.logger.error('Not authenticated. Run "testivai auth <api-key>" first.');
|
|
81
|
+
process.exit(2);
|
|
82
|
+
}
|
|
83
|
+
// Validate API key
|
|
84
|
+
logger_1.logger.info('Validating API key...');
|
|
85
|
+
const apiClient = new common_1.CoreApiClient(apiKey);
|
|
86
|
+
const validation = await apiClient.validateApiKey();
|
|
87
|
+
if (!validation.valid) {
|
|
88
|
+
logger_1.logger.error(`Invalid API key: ${validation.error}`);
|
|
89
|
+
process.exit(2);
|
|
90
|
+
}
|
|
91
|
+
// Get CDP port from config or options
|
|
92
|
+
const resolvedConfig = await config;
|
|
93
|
+
const port = parseInt(options.port || resolvedConfig.cdpPort || '9222', 10);
|
|
94
|
+
// Get git info first (doesn't require Chrome)
|
|
95
|
+
const gitInfo = await getGitInfo();
|
|
96
|
+
// Detect CI environment
|
|
97
|
+
const ciRunId = (0, ci_1.getCiRunId)();
|
|
98
|
+
const ciInfo = (0, ci_1.getCiInfo)();
|
|
99
|
+
if (ciRunId && isDebug) {
|
|
100
|
+
logger_1.logger.info(`Detected CI environment. Run ID: ${ciRunId}`);
|
|
101
|
+
if (ciInfo) {
|
|
102
|
+
logger_1.logger.info(`CI Info: provider=${ciInfo.provider}, PR=#${ciInfo.prNumber || 'N/A'}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Start the test command FIRST (non-blocking)
|
|
106
|
+
// This allows the test runner to launch Chrome
|
|
107
|
+
logger_1.logger.info(`Starting test command: ${chalk_1.default.cyan(command)}`);
|
|
108
|
+
processManager = new process_1.ProcessManager(command, [], {
|
|
109
|
+
cwd: process.cwd(),
|
|
110
|
+
env: {
|
|
111
|
+
...process.env,
|
|
112
|
+
TESTIVAI_MODE: 'true',
|
|
113
|
+
TESTIVAI_CDP_PORT: port.toString(),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
await processManager.start();
|
|
117
|
+
// Give the test command a moment to start launching Chrome
|
|
118
|
+
logger_1.logger.info('Waiting for test runner to start...');
|
|
119
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
120
|
+
// Now wait for Chrome to become available on CDP port
|
|
121
|
+
logger_1.logger.info('Waiting for Chrome DevTools Protocol...');
|
|
122
|
+
client = new client_1.CdpClient();
|
|
123
|
+
let connected = false;
|
|
124
|
+
let retryCount = 0;
|
|
125
|
+
const maxRetries = 60; // Wait up to 60 seconds for Chrome to start
|
|
126
|
+
while (!connected && retryCount < maxRetries && processManager.isRunning()) {
|
|
127
|
+
try {
|
|
128
|
+
await client.connect(port);
|
|
129
|
+
connected = true;
|
|
130
|
+
logger_1.logger.info('Successfully connected to Chrome DevTools Protocol');
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
retryCount++;
|
|
134
|
+
if (retryCount >= maxRetries) {
|
|
135
|
+
throw new Error(`Failed to connect to Chrome after ${maxRetries} attempts. The test runner may not be launching Chrome with --remote-debugging-port=${port}`);
|
|
136
|
+
}
|
|
137
|
+
if (!processManager.isRunning()) {
|
|
138
|
+
throw new Error(`Test command exited before Chrome could start. Make sure your test runner launches Chrome with --remote-debugging-port=${port}`);
|
|
139
|
+
}
|
|
140
|
+
logger_1.logger.info(`Waiting for Chrome on port ${port}... (${retryCount}/${maxRetries})`);
|
|
141
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!connected) {
|
|
145
|
+
throw new Error('Failed to connect to Chrome DevTools Protocol');
|
|
146
|
+
}
|
|
147
|
+
// Get browser info
|
|
148
|
+
const browserInfo = await getBrowserInfo(client);
|
|
149
|
+
// Set up CDP binding
|
|
150
|
+
const binding = new binding_1.CdpBinding(client, { debug: isDebug });
|
|
151
|
+
await binding.setupBindings();
|
|
152
|
+
// Wait for the test command to complete
|
|
153
|
+
logger_1.logger.info('Monitoring test execution...');
|
|
154
|
+
const result = await processManager.wait();
|
|
155
|
+
// Get all captured snapshots
|
|
156
|
+
const snapshots = binding.getSnapshots();
|
|
157
|
+
logger_1.logger.info(`Captured ${snapshots.length} snapshot(s)`);
|
|
158
|
+
// Clean up CDP connection
|
|
159
|
+
binding.cleanup();
|
|
160
|
+
// Start batch with snapshots (like Playwright SDK)
|
|
161
|
+
if (snapshots.length > 0) {
|
|
162
|
+
batchId = options.batchId || await startBatchWithSnapshots(apiClient, gitInfo, browserInfo, snapshots, isDebug, ciRunId, ciInfo);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
batchId = options.batchId || await startBatch(apiClient, gitInfo, browserInfo, ciRunId, ciInfo);
|
|
166
|
+
}
|
|
167
|
+
// Finish batch
|
|
168
|
+
if (batchId) {
|
|
169
|
+
await finishBatch(batchId);
|
|
170
|
+
}
|
|
171
|
+
// Print results
|
|
172
|
+
console.log(chalk_1.default.green('\n=== Test Results ==='));
|
|
173
|
+
console.log(`Batch ID: ${batchId}`);
|
|
174
|
+
console.log(`Snapshots: ${snapshots.length}`);
|
|
175
|
+
console.log(`Exit code: ${result.exitCode}`);
|
|
176
|
+
console.log(`Dashboard: https://dashboard.testiv.ai/projects/${validation.projectId}/batches/${batchId}`);
|
|
177
|
+
// Exit with same code as test command
|
|
178
|
+
process.exit(result.exitCode || 0);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof discovery_1.CdpDiscoveryError) {
|
|
182
|
+
console.log(chalk_1.default.red(error.message));
|
|
183
|
+
console.log(...error.getInstructions());
|
|
184
|
+
process.exit(3);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
logger_1.logger.error('Run failed:', error);
|
|
188
|
+
process.exit(4);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
/**
|
|
193
|
+
* Get browser information from CDP
|
|
194
|
+
*/
|
|
195
|
+
async function getBrowserInfo(client) {
|
|
196
|
+
try {
|
|
197
|
+
const connectionInfo = client.getConnectionInfo();
|
|
198
|
+
// Navigate to a blank page to ensure viewport is properly initialized
|
|
199
|
+
await client.send('Page.navigate', { url: 'about:blank' });
|
|
200
|
+
// Wait a moment for the page to load
|
|
201
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
202
|
+
const userAgent = await client.send('Runtime.evaluate', {
|
|
203
|
+
expression: 'navigator.userAgent',
|
|
204
|
+
returnByValue: true,
|
|
205
|
+
});
|
|
206
|
+
const viewport = await client.send('Runtime.evaluate', {
|
|
207
|
+
expression: `
|
|
208
|
+
(function() {
|
|
209
|
+
return {
|
|
210
|
+
width: window.innerWidth,
|
|
211
|
+
height: window.innerHeight
|
|
212
|
+
};
|
|
213
|
+
})()
|
|
214
|
+
`,
|
|
215
|
+
returnByValue: true,
|
|
216
|
+
});
|
|
217
|
+
// Ensure we have valid viewport dimensions
|
|
218
|
+
const width = viewport.result.value?.width || 1920; // Default fallback
|
|
219
|
+
const height = viewport.result.value?.height || 1080; // Default fallback
|
|
220
|
+
return {
|
|
221
|
+
name: 'chrome',
|
|
222
|
+
version: connectionInfo?.browserVersion || 'unknown',
|
|
223
|
+
viewportWidth: width,
|
|
224
|
+
viewportHeight: height,
|
|
225
|
+
userAgent: userAgent.result.value || 'unknown',
|
|
226
|
+
os: 'unknown',
|
|
227
|
+
device: 'desktop',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
logger_1.logger.error('Failed to get browser info:', error);
|
|
232
|
+
// Return sensible defaults if we can't get the actual values
|
|
233
|
+
return {
|
|
234
|
+
name: 'chrome',
|
|
235
|
+
version: 'unknown',
|
|
236
|
+
viewportWidth: 1920,
|
|
237
|
+
viewportHeight: 1080,
|
|
238
|
+
userAgent: 'unknown',
|
|
239
|
+
os: 'unknown',
|
|
240
|
+
device: 'desktop',
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get git information
|
|
246
|
+
*/
|
|
247
|
+
async function getGitInfo() {
|
|
248
|
+
try {
|
|
249
|
+
const git = (0, simple_git_1.default)();
|
|
250
|
+
const [branch, commit, message, author] = await Promise.all([
|
|
251
|
+
git.revparse(['--abbrev-ref', 'HEAD']).catch(() => 'unknown'),
|
|
252
|
+
git.revparse(['HEAD']).catch(() => 'unknown'),
|
|
253
|
+
git.show(['-s', '--format=%s']).catch(() => ''),
|
|
254
|
+
git.show(['-s', '--format=%an']).catch(() => ''),
|
|
255
|
+
]);
|
|
256
|
+
return {
|
|
257
|
+
branch,
|
|
258
|
+
commit,
|
|
259
|
+
message: message || undefined,
|
|
260
|
+
author: author || undefined,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
logger_1.logger.error('Failed to get git info:', error);
|
|
265
|
+
return {
|
|
266
|
+
branch: 'unknown',
|
|
267
|
+
commit: 'unknown',
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Start a new batch with snapshots (like Playwright SDK)
|
|
273
|
+
*/
|
|
274
|
+
async function startBatchWithSnapshots(apiClient, gitInfo, browserInfo, snapshots, debug, ciRunId, ciInfo) {
|
|
275
|
+
try {
|
|
276
|
+
// Transform snapshots to match API format
|
|
277
|
+
const transformedSnapshots = snapshots.map(snapshot => {
|
|
278
|
+
const structureHtml = snapshot.structure || '';
|
|
279
|
+
if (debug) {
|
|
280
|
+
logger_1.logger.info(`DEBUG: Snapshot ${snapshot.name} - Structure length: ${structureHtml.length} chars`);
|
|
281
|
+
}
|
|
282
|
+
if (structureHtml.length === 0) {
|
|
283
|
+
logger_1.logger.warn(`WARNING: Empty structure for snapshot ${snapshot.name}`);
|
|
284
|
+
}
|
|
285
|
+
else if (debug) {
|
|
286
|
+
logger_1.logger.info(`DEBUG: Structure preview: ${structureHtml.substring(0, 100)}...`);
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
snapshotName: snapshot.name,
|
|
290
|
+
testName: snapshot.name,
|
|
291
|
+
timestamp: new Date(snapshot.timestamp).getTime(),
|
|
292
|
+
url: snapshot.url || 'about:blank',
|
|
293
|
+
viewport: snapshot.viewport || { width: 1920, height: 1080 },
|
|
294
|
+
screenshotData: snapshot.screenshot, // Already base64 encoded
|
|
295
|
+
structure: { html: structureHtml },
|
|
296
|
+
styles: snapshot.styles || { computed_styles: {} },
|
|
297
|
+
performanceMetrics: snapshot.performanceMetrics,
|
|
298
|
+
layout: {
|
|
299
|
+
x: 0,
|
|
300
|
+
y: 0,
|
|
301
|
+
width: snapshot.viewport?.width || 1920,
|
|
302
|
+
height: snapshot.viewport?.height || 1080
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
const batchPayload = {
|
|
307
|
+
git: gitInfo,
|
|
308
|
+
browser: browserInfo,
|
|
309
|
+
snapshots: transformedSnapshots,
|
|
310
|
+
timestamp: Date.now(),
|
|
311
|
+
runId: ciRunId || process.env.CI_RUN_ID || null,
|
|
312
|
+
ci: ciInfo || null,
|
|
313
|
+
};
|
|
314
|
+
// Compress if large
|
|
315
|
+
const compressionHelper = (await Promise.resolve().then(() => __importStar(require('@testivai/common')))).compressionHelper;
|
|
316
|
+
const payloadJson = JSON.stringify(batchPayload);
|
|
317
|
+
const compressionResult = await compressionHelper.compress(payloadJson);
|
|
318
|
+
const apiKey = (0, common_1.getApiKey)();
|
|
319
|
+
if (!apiKey) {
|
|
320
|
+
throw new Error('API key is required');
|
|
321
|
+
}
|
|
322
|
+
const apiUrl = process.env.TESTIVAI_API_URL || common_1.DEFAULT_CORE_API_URL;
|
|
323
|
+
// Create AbortController for timeout
|
|
324
|
+
const controller = new AbortController();
|
|
325
|
+
const timeout = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
326
|
+
const response = await fetch(`${apiUrl}/api/v1/ingest/start-batch`, {
|
|
327
|
+
method: 'POST',
|
|
328
|
+
headers: {
|
|
329
|
+
'X-API-Key': apiKey,
|
|
330
|
+
'Content-Type': 'application/json',
|
|
331
|
+
...(compressionResult.compressionRatio > 0 && {
|
|
332
|
+
'Content-Encoding': 'gzip',
|
|
333
|
+
}),
|
|
334
|
+
},
|
|
335
|
+
body: compressionResult.data,
|
|
336
|
+
signal: controller.signal,
|
|
337
|
+
});
|
|
338
|
+
clearTimeout(timeout);
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
throw new Error(`Failed to start batch: ${response.statusText}`);
|
|
341
|
+
}
|
|
342
|
+
const result = await response.json();
|
|
343
|
+
const returnedBatchId = result.batch_id || result.batchId;
|
|
344
|
+
if (!returnedBatchId) {
|
|
345
|
+
throw new Error('No batch ID returned from API');
|
|
346
|
+
}
|
|
347
|
+
return returnedBatchId;
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
351
|
+
logger_1.logger.error('Failed to start batch: Request timed out after 30 seconds');
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
logger_1.logger.error('Failed to start batch:', error);
|
|
355
|
+
}
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Start a new batch (without snapshots)
|
|
361
|
+
*/
|
|
362
|
+
async function startBatch(apiClient, gitInfo, browserInfo, ciRunId, ciInfo) {
|
|
363
|
+
try {
|
|
364
|
+
const apiKey = (0, common_1.getApiKey)();
|
|
365
|
+
if (!apiKey) {
|
|
366
|
+
throw new Error('API key is required');
|
|
367
|
+
}
|
|
368
|
+
const apiUrl = process.env.TESTIVAI_API_URL || common_1.DEFAULT_CORE_API_URL;
|
|
369
|
+
// Create AbortController for timeout
|
|
370
|
+
const controller = new AbortController();
|
|
371
|
+
const timeout = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
372
|
+
const response = await fetch(`${apiUrl}/api/v1/ingest/start-batch`, {
|
|
373
|
+
method: 'POST',
|
|
374
|
+
headers: {
|
|
375
|
+
'X-API-Key': apiKey,
|
|
376
|
+
'Content-Type': 'application/json',
|
|
377
|
+
},
|
|
378
|
+
body: JSON.stringify({
|
|
379
|
+
git: gitInfo,
|
|
380
|
+
browser: browserInfo,
|
|
381
|
+
snapshots: [],
|
|
382
|
+
timestamp: Date.now(),
|
|
383
|
+
runId: ciRunId || process.env.CI_RUN_ID || null,
|
|
384
|
+
ci: ciInfo || null,
|
|
385
|
+
}),
|
|
386
|
+
signal: controller.signal,
|
|
387
|
+
});
|
|
388
|
+
clearTimeout(timeout);
|
|
389
|
+
if (!response.ok) {
|
|
390
|
+
throw new Error(`Failed to start batch: ${response.statusText}`);
|
|
391
|
+
}
|
|
392
|
+
const result = await response.json();
|
|
393
|
+
logger_1.logger.upload(result.batch_id);
|
|
394
|
+
return result.batch_id;
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
398
|
+
logger_1.logger.error('Failed to start batch: Request timed out after 30 seconds');
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
logger_1.logger.error('Failed to start batch:', error);
|
|
402
|
+
}
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Finish a batch
|
|
408
|
+
*/
|
|
409
|
+
async function finishBatch(batchId) {
|
|
410
|
+
try {
|
|
411
|
+
const apiKey = (0, common_1.getApiKey)();
|
|
412
|
+
if (!apiKey) {
|
|
413
|
+
throw new Error('API key is required');
|
|
414
|
+
}
|
|
415
|
+
const apiUrl = process.env.TESTIVAI_API_URL || common_1.DEFAULT_CORE_API_URL;
|
|
416
|
+
// Create AbortController for timeout
|
|
417
|
+
const controller = new AbortController();
|
|
418
|
+
const timeout = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
419
|
+
const response = await fetch(`${apiUrl}/api/v1/ingest/finish-batch/${batchId}`, {
|
|
420
|
+
method: 'POST',
|
|
421
|
+
headers: {
|
|
422
|
+
'X-API-Key': apiKey,
|
|
423
|
+
'Content-Type': 'application/json',
|
|
424
|
+
},
|
|
425
|
+
signal: controller.signal,
|
|
426
|
+
});
|
|
427
|
+
clearTimeout(timeout);
|
|
428
|
+
if (!response.ok) {
|
|
429
|
+
throw new Error(`Failed to finish batch: ${response.statusText}`);
|
|
430
|
+
}
|
|
431
|
+
logger_1.logger.success(`Batch ${batchId} finished successfully`);
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
logger_1.logger.error('Failed to finish batch:', error);
|
|
435
|
+
// Don't throw here - we want to exit even if finishing fails
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI CDP SDK
|
|
3
|
+
* Framework-agnostic visual regression testing using Chrome DevTools Protocol
|
|
4
|
+
*/
|
|
5
|
+
export * from './types';
|
|
6
|
+
export { CdpClient } from './cdp/client';
|
|
7
|
+
export { CdpCapture } from './cdp/capture';
|
|
8
|
+
export { CdpBinding } from './cdp/binding';
|
|
9
|
+
export { CdpDiscovery, CdpDiscoveryError } from './cdp/discovery';
|
|
10
|
+
export { logger, createLogger } from './utils/logger';
|
|
11
|
+
export { toSafeFilename, generateUniqueFilename, extractNameFromUrl, sanitizeTestName, isSafeFilename } from './utils/file-naming';
|
|
12
|
+
export { ProcessManager, spawnProcess, setupSignalHandlers, commandExists } from './utils/process';
|
|
13
|
+
export { FrameworkDetector } from './utils/framework-detect';
|
|
14
|
+
export { authCommand } from './commands/auth';
|
|
15
|
+
export { initCommand } from './commands/init';
|
|
16
|
+
export { runCommand } from './commands/run';
|
|
17
|
+
export { witnessCommand } from './commands/capture';
|
|
18
|
+
export { CoreApiClient, DEFAULT_CORE_API_URL, saveCredentials, loadCredentials, deleteCredentials, getApiKey, isAuthenticated, findConfigFile, loadConfig, configExists, getOutputDir, CompressionHelper, compressionHelper, } from '@testivai/common';
|
|
19
|
+
export declare const VERSION: any;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnI,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,OAAO,KAAwC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI CDP SDK
|
|
4
|
+
* Framework-agnostic visual regression testing using Chrome DevTools Protocol
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.VERSION = exports.compressionHelper = exports.CompressionHelper = exports.getOutputDir = exports.configExists = exports.loadConfig = exports.findConfigFile = exports.isAuthenticated = exports.getApiKey = exports.deleteCredentials = exports.loadCredentials = exports.saveCredentials = exports.DEFAULT_CORE_API_URL = exports.CoreApiClient = exports.witnessCommand = exports.runCommand = exports.initCommand = exports.authCommand = exports.FrameworkDetector = exports.commandExists = exports.setupSignalHandlers = exports.spawnProcess = exports.ProcessManager = exports.isSafeFilename = exports.sanitizeTestName = exports.extractNameFromUrl = exports.generateUniqueFilename = exports.toSafeFilename = exports.createLogger = exports.logger = exports.CdpDiscoveryError = exports.CdpDiscovery = exports.CdpBinding = exports.CdpCapture = exports.CdpClient = void 0;
|
|
22
|
+
// Export types
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
// Export CDP modules
|
|
25
|
+
var client_1 = require("./cdp/client");
|
|
26
|
+
Object.defineProperty(exports, "CdpClient", { enumerable: true, get: function () { return client_1.CdpClient; } });
|
|
27
|
+
var capture_1 = require("./cdp/capture");
|
|
28
|
+
Object.defineProperty(exports, "CdpCapture", { enumerable: true, get: function () { return capture_1.CdpCapture; } });
|
|
29
|
+
var binding_1 = require("./cdp/binding");
|
|
30
|
+
Object.defineProperty(exports, "CdpBinding", { enumerable: true, get: function () { return binding_1.CdpBinding; } });
|
|
31
|
+
var discovery_1 = require("./cdp/discovery");
|
|
32
|
+
Object.defineProperty(exports, "CdpDiscovery", { enumerable: true, get: function () { return discovery_1.CdpDiscovery; } });
|
|
33
|
+
Object.defineProperty(exports, "CdpDiscoveryError", { enumerable: true, get: function () { return discovery_1.CdpDiscoveryError; } });
|
|
34
|
+
// Export utilities
|
|
35
|
+
var logger_1 = require("./utils/logger");
|
|
36
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
|
|
37
|
+
Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
|
|
38
|
+
var file_naming_1 = require("./utils/file-naming");
|
|
39
|
+
Object.defineProperty(exports, "toSafeFilename", { enumerable: true, get: function () { return file_naming_1.toSafeFilename; } });
|
|
40
|
+
Object.defineProperty(exports, "generateUniqueFilename", { enumerable: true, get: function () { return file_naming_1.generateUniqueFilename; } });
|
|
41
|
+
Object.defineProperty(exports, "extractNameFromUrl", { enumerable: true, get: function () { return file_naming_1.extractNameFromUrl; } });
|
|
42
|
+
Object.defineProperty(exports, "sanitizeTestName", { enumerable: true, get: function () { return file_naming_1.sanitizeTestName; } });
|
|
43
|
+
Object.defineProperty(exports, "isSafeFilename", { enumerable: true, get: function () { return file_naming_1.isSafeFilename; } });
|
|
44
|
+
var process_1 = require("./utils/process");
|
|
45
|
+
Object.defineProperty(exports, "ProcessManager", { enumerable: true, get: function () { return process_1.ProcessManager; } });
|
|
46
|
+
Object.defineProperty(exports, "spawnProcess", { enumerable: true, get: function () { return process_1.spawnProcess; } });
|
|
47
|
+
Object.defineProperty(exports, "setupSignalHandlers", { enumerable: true, get: function () { return process_1.setupSignalHandlers; } });
|
|
48
|
+
Object.defineProperty(exports, "commandExists", { enumerable: true, get: function () { return process_1.commandExists; } });
|
|
49
|
+
var framework_detect_1 = require("./utils/framework-detect");
|
|
50
|
+
Object.defineProperty(exports, "FrameworkDetector", { enumerable: true, get: function () { return framework_detect_1.FrameworkDetector; } });
|
|
51
|
+
// Export commands (for programmatic use)
|
|
52
|
+
var auth_1 = require("./commands/auth");
|
|
53
|
+
Object.defineProperty(exports, "authCommand", { enumerable: true, get: function () { return auth_1.authCommand; } });
|
|
54
|
+
var init_1 = require("./commands/init");
|
|
55
|
+
Object.defineProperty(exports, "initCommand", { enumerable: true, get: function () { return init_1.initCommand; } });
|
|
56
|
+
var run_1 = require("./commands/run");
|
|
57
|
+
Object.defineProperty(exports, "runCommand", { enumerable: true, get: function () { return run_1.runCommand; } });
|
|
58
|
+
var capture_2 = require("./commands/capture");
|
|
59
|
+
Object.defineProperty(exports, "witnessCommand", { enumerable: true, get: function () { return capture_2.witnessCommand; } });
|
|
60
|
+
// Re-export common utilities
|
|
61
|
+
var common_1 = require("@testivai/common");
|
|
62
|
+
Object.defineProperty(exports, "CoreApiClient", { enumerable: true, get: function () { return common_1.CoreApiClient; } });
|
|
63
|
+
Object.defineProperty(exports, "DEFAULT_CORE_API_URL", { enumerable: true, get: function () { return common_1.DEFAULT_CORE_API_URL; } });
|
|
64
|
+
Object.defineProperty(exports, "saveCredentials", { enumerable: true, get: function () { return common_1.saveCredentials; } });
|
|
65
|
+
Object.defineProperty(exports, "loadCredentials", { enumerable: true, get: function () { return common_1.loadCredentials; } });
|
|
66
|
+
Object.defineProperty(exports, "deleteCredentials", { enumerable: true, get: function () { return common_1.deleteCredentials; } });
|
|
67
|
+
Object.defineProperty(exports, "getApiKey", { enumerable: true, get: function () { return common_1.getApiKey; } });
|
|
68
|
+
Object.defineProperty(exports, "isAuthenticated", { enumerable: true, get: function () { return common_1.isAuthenticated; } });
|
|
69
|
+
Object.defineProperty(exports, "findConfigFile", { enumerable: true, get: function () { return common_1.findConfigFile; } });
|
|
70
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return common_1.loadConfig; } });
|
|
71
|
+
Object.defineProperty(exports, "configExists", { enumerable: true, get: function () { return common_1.configExists; } });
|
|
72
|
+
Object.defineProperty(exports, "getOutputDir", { enumerable: true, get: function () { return common_1.getOutputDir; } });
|
|
73
|
+
Object.defineProperty(exports, "CompressionHelper", { enumerable: true, get: function () { return common_1.CompressionHelper; } });
|
|
74
|
+
Object.defineProperty(exports, "compressionHelper", { enumerable: true, get: function () { return common_1.compressionHelper; } });
|
|
75
|
+
// Version
|
|
76
|
+
exports.VERSION = require('../../package.json').version;
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,eAAe;AACf,0CAAwB;AAExB,qBAAqB;AACrB,uCAAyC;AAAhC,mGAAA,SAAS,OAAA;AAClB,yCAA2C;AAAlC,qGAAA,UAAU,OAAA;AACnB,yCAA2C;AAAlC,qGAAA,UAAU,OAAA;AACnB,6CAAkE;AAAzD,yGAAA,YAAY,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAExC,mBAAmB;AACnB,yCAAsD;AAA7C,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAC7B,mDAAmI;AAA1H,6GAAA,cAAc,OAAA;AAAE,qHAAA,sBAAsB,OAAA;AAAE,iHAAA,kBAAkB,OAAA;AAAE,+GAAA,gBAAgB,OAAA;AAAE,6GAAA,cAAc,OAAA;AACrG,2CAAmG;AAA1F,yGAAA,cAAc,OAAA;AAAE,uGAAA,YAAY,OAAA;AAAE,8GAAA,mBAAmB,OAAA;AAAE,wGAAA,aAAa,OAAA;AACzE,6DAA6D;AAApD,qHAAA,iBAAiB,OAAA;AAE1B,yCAAyC;AACzC,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,sCAA4C;AAAnC,iGAAA,UAAU,OAAA;AACnB,8CAAoD;AAA3C,yGAAA,cAAc,OAAA;AAEvB,6BAA6B;AAC7B,2CAc0B;AAbxB,uGAAA,aAAa,OAAA;AACb,8GAAA,oBAAoB,OAAA;AACpB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,mGAAA,SAAS,OAAA;AACT,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AACd,oGAAA,UAAU,OAAA;AACV,sGAAA,YAAY,OAAA;AACZ,sGAAA,YAAY,OAAA;AACZ,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAGnB,UAAU;AACG,QAAA,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC"}
|