testblocks-agent 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/dist/client.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentClient = void 0;
4
+ class AgentClient {
5
+ baseUrl;
6
+ token;
7
+ constructor(config) {
8
+ this.baseUrl = config.serverUrl;
9
+ this.token = config.token;
10
+ }
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic JSON responses
12
+ async request(method, path, body) {
13
+ const url = `${this.baseUrl}/api/agent${path}`;
14
+ const headers = {
15
+ 'Authorization': `Bearer ${this.token}`,
16
+ };
17
+ let requestBody;
18
+ if (body !== undefined) {
19
+ headers['Content-Type'] = 'application/json';
20
+ requestBody = JSON.stringify(body);
21
+ }
22
+ const res = await fetch(url, { method, headers, body: requestBody });
23
+ if (!res.ok) {
24
+ const errBody = await res.text();
25
+ let errMsg;
26
+ try {
27
+ errMsg = JSON.parse(errBody).error || errBody;
28
+ }
29
+ catch {
30
+ errMsg = errBody;
31
+ }
32
+ throw new Error(`API ${res.status}: ${errMsg}`);
33
+ }
34
+ return res.json();
35
+ }
36
+ async validate() {
37
+ return this.request('GET', '/validate');
38
+ }
39
+ async poll() {
40
+ const data = await this.request('GET', '/poll');
41
+ return data.job || null;
42
+ }
43
+ async reportProgress(update) {
44
+ return this.request('POST', '/progress', update);
45
+ }
46
+ async reportResults(payload) {
47
+ await this.request('POST', '/results', payload);
48
+ }
49
+ async uploadArtifact(runId, filePath, fileData) {
50
+ const url = `${this.baseUrl}/api/agent/artifacts/${runId}`;
51
+ const res = await fetch(url, {
52
+ method: 'POST',
53
+ headers: {
54
+ 'Authorization': `Bearer ${this.token}`,
55
+ 'Content-Type': 'application/octet-stream',
56
+ 'X-Artifact-Path': filePath,
57
+ },
58
+ body: new Uint8Array(fileData),
59
+ });
60
+ if (!res.ok) {
61
+ throw new Error(`Upload failed: ${res.status}`);
62
+ }
63
+ }
64
+ }
65
+ exports.AgentClient = AgentClient;
66
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAgDA,MAAa,WAAW;IACd,OAAO,CAAS;IAChB,KAAK,CAAS;IAEtB,YAAY,MAAmB;QAC7B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,wFAAwF;IAChF,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,IAAY,EAAE,IAAc;QAChE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,aAAa,IAAI,EAAE,CAAC;QAC/C,MAAM,OAAO,GAA2B;YACtC,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;SACxC,CAAC;QAEF,IAAI,WAA+B,CAAC;QACpC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC7C,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QAErE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,OAAO,CAAC;YACnB,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAsB;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAuB;QACzC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAa,EAAE,QAAgB,EAAE,QAAgB;QACpE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,KAAK,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;gBACvC,cAAc,EAAE,0BAA0B;gBAC1C,iBAAiB,EAAE,QAAQ;aAC5B;YACD,IAAI,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC;SAC/B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;CACF;AAvED,kCAuEC"}
@@ -0,0 +1,9 @@
1
+ export interface AgentConfig {
2
+ serverUrl: string;
3
+ token: string;
4
+ projectId?: string;
5
+ }
6
+ export declare function saveConfig(config: AgentConfig): void;
7
+ export declare function loadConfig(): AgentConfig;
8
+ export declare function isConfigCommand(): boolean;
9
+ export declare function handleConfigCommand(): void;
package/dist/config.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.saveConfig = saveConfig;
7
+ exports.loadConfig = loadConfig;
8
+ exports.isConfigCommand = isConfigCommand;
9
+ exports.handleConfigCommand = handleConfigCommand;
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.testblocks');
14
+ const CONFIG_FILE = path_1.default.join(CONFIG_DIR, 'agent.json');
15
+ function parseArgs() {
16
+ const args = process.argv.slice(2);
17
+ const config = {};
18
+ for (let i = 0; i < args.length; i++) {
19
+ const arg = args[i];
20
+ const next = args[i + 1];
21
+ if ((arg === '--server' || arg === '-s') && next) {
22
+ config.serverUrl = next.replace(/\/$/, '');
23
+ i++;
24
+ }
25
+ else if ((arg === '--token' || arg === '-t') && next) {
26
+ config.token = next;
27
+ i++;
28
+ }
29
+ else if ((arg === '--project' || arg === '-p') && next) {
30
+ config.projectId = next;
31
+ i++;
32
+ }
33
+ }
34
+ return config;
35
+ }
36
+ function loadConfigFile() {
37
+ try {
38
+ if (fs_1.default.existsSync(CONFIG_FILE)) {
39
+ const data = JSON.parse(fs_1.default.readFileSync(CONFIG_FILE, 'utf-8'));
40
+ return {
41
+ serverUrl: data.serverUrl || data.server,
42
+ token: data.token,
43
+ projectId: data.projectId || data.project,
44
+ };
45
+ }
46
+ }
47
+ catch {
48
+ // Ignore file read errors
49
+ }
50
+ return {};
51
+ }
52
+ function saveConfig(config) {
53
+ fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true });
54
+ fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify({
55
+ serverUrl: config.serverUrl,
56
+ token: config.token,
57
+ projectId: config.projectId,
58
+ }, null, 2));
59
+ }
60
+ function loadConfig() {
61
+ const args = parseArgs();
62
+ const env = {
63
+ serverUrl: process.env.TESTBLOCKS_SERVER,
64
+ token: process.env.TESTBLOCKS_TOKEN,
65
+ projectId: process.env.TESTBLOCKS_PROJECT,
66
+ };
67
+ const file = loadConfigFile();
68
+ // Priority: CLI args > env vars > config file
69
+ const serverUrl = args.serverUrl || env.serverUrl || file.serverUrl;
70
+ const token = args.token || env.token || file.token;
71
+ const projectId = args.projectId || env.projectId || file.projectId;
72
+ if (!serverUrl) {
73
+ console.error('Error: Server URL is required');
74
+ console.error(' Use --server <url> or set TESTBLOCKS_SERVER env var');
75
+ process.exit(1);
76
+ }
77
+ if (!token) {
78
+ console.error('Error: Agent token is required');
79
+ console.error(' Use --token <token> or set TESTBLOCKS_TOKEN env var');
80
+ process.exit(1);
81
+ }
82
+ return { serverUrl, token, projectId: projectId || undefined };
83
+ }
84
+ function isConfigCommand() {
85
+ return process.argv[2] === 'config';
86
+ }
87
+ function handleConfigCommand() {
88
+ const args = parseArgs();
89
+ if (!args.serverUrl || !args.token) {
90
+ console.error('Usage: testblocks-agent config --server <url> --token <token>');
91
+ process.exit(1);
92
+ }
93
+ saveConfig({ serverUrl: args.serverUrl, token: args.token, projectId: args.projectId });
94
+ console.log(`Configuration saved to ${CONFIG_FILE}`);
95
+ }
96
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { AgentClient, AgentJobPayload } from './client';
2
+ export declare function browserToDevice(browser: string): string;
3
+ export declare function generateRunnerConfig(config: AgentJobPayload['config']): string;
4
+ export declare function sanitizeError(msg: string): string;
5
+ export interface PlaywrightReportSuite {
6
+ specs?: PlaywrightReportSpec[];
7
+ suites?: PlaywrightReportSuite[];
8
+ [key: string]: unknown;
9
+ }
10
+ export interface PlaywrightReportSpec {
11
+ file?: string;
12
+ tests?: Array<{
13
+ results?: Array<{
14
+ status: string;
15
+ duration?: number;
16
+ error?: {
17
+ message?: string;
18
+ };
19
+ attachments?: PlaywrightAttachment[];
20
+ }>;
21
+ }>;
22
+ [key: string]: unknown;
23
+ }
24
+ export interface PlaywrightAttachment {
25
+ name?: string;
26
+ path?: string | null;
27
+ contentType?: string;
28
+ }
29
+ export declare function flattenSpecs(suites: PlaywrightReportSuite[]): PlaywrightReportSpec[];
30
+ export declare function mapPlaywrightStatus(pwStatus: string): 'passed' | 'failed' | 'error' | 'skipped';
31
+ export declare function executeJob(job: AgentJobPayload, client: AgentClient): Promise<void>;
32
+ export declare function collectArtifacts(attachments: PlaywrightAttachment[], workDir: string): {
33
+ screenshots: string[];
34
+ video: string | null;
35
+ trace: string | null;
36
+ };
@@ -0,0 +1,375 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.browserToDevice = browserToDevice;
7
+ exports.generateRunnerConfig = generateRunnerConfig;
8
+ exports.sanitizeError = sanitizeError;
9
+ exports.flattenSpecs = flattenSpecs;
10
+ exports.mapPlaywrightStatus = mapPlaywrightStatus;
11
+ exports.executeJob = executeJob;
12
+ exports.collectArtifacts = collectArtifacts;
13
+ const child_process_1 = require("child_process");
14
+ const path_1 = __importDefault(require("path"));
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const os_1 = __importDefault(require("os"));
17
+ const WORK_BASE = path_1.default.join(os_1.default.tmpdir(), 'testblocks-agent');
18
+ function browserToDevice(browser) {
19
+ switch (browser) {
20
+ case 'firefox': return 'Desktop Firefox';
21
+ case 'webkit': return 'Desktop Safari';
22
+ default: return 'Desktop Chrome';
23
+ }
24
+ }
25
+ function generateRunnerConfig(config) {
26
+ const device = browserToDevice(config.browser);
27
+ const lines = [];
28
+ lines.push("import { defineConfig, devices } from '@playwright/test';");
29
+ lines.push("import dotenv from 'dotenv';");
30
+ lines.push('');
31
+ lines.push('dotenv.config();');
32
+ lines.push('');
33
+ lines.push('export default defineConfig({');
34
+ lines.push(" testDir: './',");
35
+ lines.push(` timeout: ${config.timeout},`);
36
+ lines.push(` retries: ${config.retries},`);
37
+ lines.push(' fullyParallel: false,');
38
+ lines.push(' workers: 1,');
39
+ lines.push(' use: {');
40
+ lines.push(` headless: ${config.headless},`);
41
+ lines.push(` viewport: { width: ${config.viewportWidth}, height: ${config.viewportHeight} },`);
42
+ lines.push(` screenshot: '${config.screenshots}',`);
43
+ lines.push(` video: '${config.video}',`);
44
+ lines.push(` trace: '${config.trace}',`);
45
+ lines.push(" baseURL: process.env.BASE_URL || undefined,");
46
+ lines.push(' },');
47
+ lines.push(' projects: [');
48
+ lines.push(' {');
49
+ lines.push(` name: '${config.browser}',`);
50
+ lines.push(` use: { ...devices['${device}'] },`);
51
+ lines.push(' },');
52
+ lines.push(' ],');
53
+ lines.push(" reporter: [['json', { outputFile: 'report.json' }], ['line']],");
54
+ lines.push('});');
55
+ lines.push('');
56
+ return lines.join('\n');
57
+ }
58
+ function sanitizeError(msg) {
59
+ const clean = msg.replace(/\x1b\[[0-9;]*m/g, '');
60
+ return clean.length > 300 ? clean.substring(0, 300) + '...' : clean;
61
+ }
62
+ function flattenSpecs(suites) {
63
+ const specs = [];
64
+ for (const suite of suites) {
65
+ if (suite.specs)
66
+ specs.push(...suite.specs);
67
+ if (suite.suites)
68
+ specs.push(...flattenSpecs(suite.suites));
69
+ }
70
+ return specs;
71
+ }
72
+ function mapPlaywrightStatus(pwStatus) {
73
+ switch (pwStatus) {
74
+ case 'passed': return 'passed';
75
+ case 'failed': return 'failed';
76
+ case 'timedOut': return 'failed';
77
+ case 'skipped': return 'skipped';
78
+ default: return 'error';
79
+ }
80
+ }
81
+ async function executeJob(job, client) {
82
+ const workDir = path_1.default.join(WORK_BASE, job.testRunId);
83
+ let childProcess = null;
84
+ let cancelled = false;
85
+ try {
86
+ // Create working directory
87
+ fs_1.default.mkdirSync(workDir, { recursive: true });
88
+ console.log(` Working directory: ${workDir}`);
89
+ // Build filename → testCaseId mapping
90
+ const filenameToTestId = new Map();
91
+ // Write spec files
92
+ let hasFixtures = false;
93
+ for (const spec of job.specs) {
94
+ fs_1.default.writeFileSync(path_1.default.join(workDir, `${spec.filename}.spec.ts`), spec.specCode);
95
+ filenameToTestId.set(spec.filename, spec.testCaseId);
96
+ if (spec.fixturesCode && !hasFixtures) {
97
+ fs_1.default.writeFileSync(path_1.default.join(workDir, 'fixtures.ts'), spec.fixturesCode);
98
+ hasFixtures = true;
99
+ }
100
+ }
101
+ // Write playwright.config.ts
102
+ fs_1.default.writeFileSync(path_1.default.join(workDir, 'playwright.config.ts'), generateRunnerConfig(job.config));
103
+ // Write .env
104
+ if (job.envVars.length > 0) {
105
+ const envContent = job.envVars.map(v => `${v.name}=${v.value}`).join('\n') + '\n';
106
+ fs_1.default.writeFileSync(path_1.default.join(workDir, '.env'), envContent);
107
+ }
108
+ // Write package.json
109
+ fs_1.default.writeFileSync(path_1.default.join(workDir, 'package.json'), JSON.stringify({
110
+ name: 'testblocks-agent-run',
111
+ private: true,
112
+ devDependencies: {
113
+ '@playwright/test': '*',
114
+ dotenv: '*',
115
+ },
116
+ }, null, 2));
117
+ // Try to find and symlink node_modules
118
+ // First try: look for node_modules relative to the agent binary
119
+ const possibleNodeModules = [
120
+ path_1.default.resolve(__dirname, '..', 'node_modules'),
121
+ path_1.default.resolve(__dirname, '..', '..', 'node_modules'),
122
+ path_1.default.resolve(process.cwd(), 'node_modules'),
123
+ ];
124
+ const workNodeModules = path_1.default.join(workDir, 'node_modules');
125
+ if (!fs_1.default.existsSync(workNodeModules)) {
126
+ for (const nm of possibleNodeModules) {
127
+ if (fs_1.default.existsSync(nm)) {
128
+ try {
129
+ fs_1.default.symlinkSync(nm, workNodeModules, 'junction');
130
+ break;
131
+ }
132
+ catch {
133
+ // Try next option
134
+ }
135
+ }
136
+ }
137
+ }
138
+ // Build per-test status for progress reporting
139
+ const perTestStatus = job.specs.map(spec => ({
140
+ testCaseId: spec.testCaseId,
141
+ testName: spec.filename,
142
+ status: 'pending',
143
+ }));
144
+ // Spawn playwright test
145
+ console.log(' Starting Playwright...');
146
+ const child = (0, child_process_1.spawn)('npx', ['playwright', 'test', '--config=playwright.config.ts'], {
147
+ cwd: workDir,
148
+ env: { ...process.env },
149
+ stdio: ['ignore', 'pipe', 'pipe'],
150
+ shell: true,
151
+ });
152
+ childProcess = child;
153
+ let stderrData = '';
154
+ // Parse progress from stdout
155
+ child.stdout?.on('data', (chunk) => {
156
+ const text = chunk.toString();
157
+ process.stdout.write(text); // Echo to terminal
158
+ const lines = text.split('\n');
159
+ for (const line of lines) {
160
+ const progressMatch = line.match(/\[(\d+)\/(\d+)\]/);
161
+ if (progressMatch) {
162
+ const current = parseInt(progressMatch[1], 10);
163
+ // Report progress to server
164
+ client.reportProgress({
165
+ jobId: job.jobId,
166
+ completedTests: current - 1,
167
+ currentTest: null,
168
+ perTestStatus,
169
+ }).then(res => {
170
+ if (res.cancelled) {
171
+ cancelled = true;
172
+ child.kill('SIGTERM');
173
+ }
174
+ }).catch(() => { });
175
+ }
176
+ const passedMatch = line.match(/✓|passed/i);
177
+ const failedMatch = line.match(/✘|failed/i);
178
+ if (passedMatch || failedMatch) {
179
+ const nameMatch = line.match(/›\s+(.+?)(?:\s+\(|$)/);
180
+ if (nameMatch) {
181
+ const testName = nameMatch[1].trim();
182
+ const idx = perTestStatus.findIndex(t => t.testName === testName || t.testName.includes(testName));
183
+ if (idx >= 0) {
184
+ perTestStatus[idx].status = passedMatch ? 'passed' : 'failed';
185
+ }
186
+ }
187
+ }
188
+ }
189
+ });
190
+ child.stderr?.on('data', (chunk) => {
191
+ const text = chunk.toString();
192
+ stderrData += text;
193
+ process.stderr.write(text);
194
+ });
195
+ // Wait for process to finish
196
+ await new Promise((resolve) => {
197
+ child.on('close', (code) => resolve(code));
198
+ child.on('error', () => resolve(null));
199
+ });
200
+ childProcess = null;
201
+ if (cancelled) {
202
+ console.log(' Run cancelled by user');
203
+ await client.reportResults({
204
+ jobId: job.jobId,
205
+ testRunId: job.testRunId,
206
+ results: job.specs.map(spec => ({
207
+ testCaseId: spec.testCaseId,
208
+ status: 'error',
209
+ durationMs: null,
210
+ errorMessage: 'Cancelled by user',
211
+ retryCount: 0,
212
+ artifacts: null,
213
+ })),
214
+ status: 'cancelled',
215
+ });
216
+ return;
217
+ }
218
+ // Parse report.json
219
+ const reportPath = path_1.default.join(workDir, 'report.json');
220
+ let report = null;
221
+ if (fs_1.default.existsSync(reportPath)) {
222
+ try {
223
+ report = JSON.parse(fs_1.default.readFileSync(reportPath, 'utf-8'));
224
+ }
225
+ catch {
226
+ console.error(' Failed to parse report.json');
227
+ }
228
+ }
229
+ // Process results
230
+ const results = [];
231
+ const processedTestIds = new Set();
232
+ if (report?.suites && report.suites.length > 0) {
233
+ const specs = flattenSpecs(report.suites);
234
+ for (const spec of specs) {
235
+ const filename = path_1.default.basename(spec.file || '', '.spec.ts');
236
+ const testCaseId = filenameToTestId.get(filename);
237
+ if (!testCaseId)
238
+ continue;
239
+ const tests = spec.tests || [];
240
+ const test = tests[0];
241
+ if (!test)
242
+ continue;
243
+ const testResults = test.results || [];
244
+ const lastResult = testResults[testResults.length - 1];
245
+ if (!lastResult)
246
+ continue;
247
+ processedTestIds.add(testCaseId);
248
+ const status = mapPlaywrightStatus(lastResult.status);
249
+ const duration = lastResult.duration || 0;
250
+ const errorMessage = lastResult.error?.message
251
+ ? sanitizeError(lastResult.error.message)
252
+ : null;
253
+ // Collect artifacts
254
+ const artifacts = collectArtifacts(lastResult.attachments || [], workDir);
255
+ // Upload artifacts to server
256
+ for (const screenshot of artifacts.screenshots) {
257
+ await uploadFile(client, job.testRunId, workDir, screenshot);
258
+ }
259
+ if (artifacts.video) {
260
+ await uploadFile(client, job.testRunId, workDir, artifacts.video);
261
+ }
262
+ if (artifacts.trace) {
263
+ await uploadFile(client, job.testRunId, workDir, artifacts.trace);
264
+ }
265
+ results.push({
266
+ testCaseId,
267
+ status,
268
+ durationMs: duration,
269
+ errorMessage,
270
+ retryCount: Math.max(0, testResults.length - 1),
271
+ artifacts: (artifacts.screenshots.length > 0 || artifacts.video || artifacts.trace)
272
+ ? artifacts : null,
273
+ });
274
+ }
275
+ }
276
+ // Mark unprocessed tests as error
277
+ for (const spec of job.specs) {
278
+ if (processedTestIds.has(spec.testCaseId))
279
+ continue;
280
+ const errMsg = stderrData
281
+ ? sanitizeError(stderrData.substring(0, 500))
282
+ : 'Test execution failed — no results produced';
283
+ results.push({
284
+ testCaseId: spec.testCaseId,
285
+ status: 'error',
286
+ durationMs: null,
287
+ errorMessage: errMsg,
288
+ retryCount: 0,
289
+ artifacts: null,
290
+ });
291
+ }
292
+ // Report final results to server
293
+ await client.reportResults({
294
+ jobId: job.jobId,
295
+ testRunId: job.testRunId,
296
+ results,
297
+ });
298
+ const passed = results.filter(r => r.status === 'passed').length;
299
+ const failed = results.filter(r => r.status === 'failed').length;
300
+ const errors = results.filter(r => r.status === 'error').length;
301
+ console.log(` Results: ${passed} passed, ${failed} failed, ${errors} errors`);
302
+ }
303
+ catch (err) {
304
+ console.error(' Execution error:', err);
305
+ // Try to report failure
306
+ try {
307
+ await client.reportResults({
308
+ jobId: job.jobId,
309
+ testRunId: job.testRunId,
310
+ results: job.specs.map(spec => ({
311
+ testCaseId: spec.testCaseId,
312
+ status: 'error',
313
+ durationMs: null,
314
+ errorMessage: err instanceof Error ? sanitizeError(err.message) : 'Unknown execution error',
315
+ retryCount: 0,
316
+ artifacts: null,
317
+ })),
318
+ });
319
+ }
320
+ catch {
321
+ console.error(' Failed to report error to server');
322
+ }
323
+ }
324
+ finally {
325
+ // Kill child process if still running
326
+ if (childProcess) {
327
+ try {
328
+ childProcess.kill('SIGTERM');
329
+ }
330
+ catch { }
331
+ }
332
+ // Clean up working directory
333
+ try {
334
+ fs_1.default.rmSync(workDir, { recursive: true, force: true });
335
+ }
336
+ catch {
337
+ // Best effort cleanup
338
+ }
339
+ }
340
+ }
341
+ function collectArtifacts(attachments, workDir) {
342
+ const result = {
343
+ screenshots: [],
344
+ video: null,
345
+ trace: null,
346
+ };
347
+ for (const att of attachments) {
348
+ if (!att.path)
349
+ continue;
350
+ const relativePath = path_1.default.relative(workDir, att.path).replace(/\\/g, '/');
351
+ if (att.contentType?.startsWith('image/')) {
352
+ result.screenshots.push(relativePath);
353
+ }
354
+ else if (att.contentType?.startsWith('video/')) {
355
+ result.video = relativePath;
356
+ }
357
+ else if (att.name === 'trace' || att.path?.endsWith('.zip')) {
358
+ result.trace = relativePath;
359
+ }
360
+ }
361
+ return result;
362
+ }
363
+ async function uploadFile(client, runId, workDir, relativePath) {
364
+ const fullPath = path_1.default.join(workDir, relativePath);
365
+ if (!fs_1.default.existsSync(fullPath))
366
+ return;
367
+ try {
368
+ const fileData = fs_1.default.readFileSync(fullPath);
369
+ await client.uploadArtifact(runId, relativePath, fileData);
370
+ }
371
+ catch (err) {
372
+ console.error(` Failed to upload artifact ${relativePath}:`, err);
373
+ }
374
+ }
375
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function ensurePlaywright(): Promise<void>;