@qate/cli 1.0.0 → 1.1.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.
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Auth Flow Executor for CLI
3
+ * Ports auth flow execution from electron-test-agent/src/tools/RestApiTools.js
4
+ * Executes authentication flows locally to obtain auth headers/params for API tests
5
+ */
6
+ export interface AuthVariable {
7
+ name: string;
8
+ source: string;
9
+ type: 'extract' | 'literal' | 'env';
10
+ }
11
+ export interface AuthTransform {
12
+ name: string;
13
+ operation: string;
14
+ input: any;
15
+ parameters?: any;
16
+ }
17
+ export interface AuthExtraction {
18
+ name: string;
19
+ path: string;
20
+ defaultValue?: any;
21
+ }
22
+ export interface AuthCondition {
23
+ field: string;
24
+ operator: 'equals' | 'not_equals' | 'contains' | 'exists' | 'greater_than' | 'less_than';
25
+ value: any;
26
+ onTrue?: string;
27
+ onFalse?: string;
28
+ }
29
+ export interface AuthHttpRequest {
30
+ url: string;
31
+ method: string;
32
+ headers?: Record<string, string>;
33
+ body?: any;
34
+ bodyType?: 'json' | 'x-www-form-urlencoded';
35
+ timeout?: number;
36
+ }
37
+ export interface AuthStep {
38
+ id: string;
39
+ name: string;
40
+ type: 'http_request' | 'load_vars' | 'transform' | 'condition';
41
+ description?: string;
42
+ request?: AuthHttpRequest;
43
+ load?: AuthVariable[];
44
+ transform?: AuthTransform[];
45
+ condition?: AuthCondition;
46
+ extract?: AuthExtraction[];
47
+ onError?: {
48
+ action: 'fail' | 'continue' | 'retry';
49
+ retryCount?: number;
50
+ continueStep?: string;
51
+ };
52
+ }
53
+ export interface AuthOutput {
54
+ name: string;
55
+ value: string;
56
+ type: 'header' | 'query_param' | 'body_param';
57
+ }
58
+ export interface AuthDefinition {
59
+ id: string;
60
+ name: string;
61
+ roleName?: string;
62
+ authType?: string;
63
+ steps: AuthStep[];
64
+ outputs: AuthOutput[];
65
+ settings?: {
66
+ timeout?: number;
67
+ retryOnFailure?: boolean;
68
+ maxRetries?: number;
69
+ };
70
+ }
71
+ export interface AuthData {
72
+ headers: Record<string, string>;
73
+ queryParams: Record<string, string>;
74
+ bodyParams: Record<string, string>;
75
+ }
76
+ /**
77
+ * Execute authentication flow and return auth data
78
+ */
79
+ export declare function executeAuthFlow(authDefinition: AuthDefinition): Promise<AuthData>;
80
+ /**
81
+ * Apply auth data to request config (headers, query params)
82
+ */
83
+ export declare function applyAuthToRequest(requestConfig: {
84
+ url: string;
85
+ headers?: Record<string, string>;
86
+ }, authData: AuthData): void;
87
+ //# sourceMappingURL=AuthFlowExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthFlowExecutor.d.ts","sourceRoot":"","sources":["../src/AuthFlowExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ /**
3
+ * Auth Flow Executor for CLI
4
+ * Ports auth flow execution from electron-test-agent/src/tools/RestApiTools.js
5
+ * Executes authentication flows locally to obtain auth headers/params for API tests
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.executeAuthFlow = executeAuthFlow;
12
+ exports.applyAuthToRequest = applyAuthToRequest;
13
+ const axios_1 = __importDefault(require("axios"));
14
+ const crypto_1 = __importDefault(require("crypto"));
15
+ // ============ Cache ============
16
+ const authCache = new Map();
17
+ const AUTH_CACHE_DURATION_MS = 5 * 60 * 1000; // 5 minutes
18
+ // ============ Main Functions ============
19
+ /**
20
+ * Execute authentication flow and return auth data
21
+ */
22
+ async function executeAuthFlow(authDefinition) {
23
+ if (!authDefinition || !authDefinition.steps || authDefinition.steps.length === 0) {
24
+ return { headers: {}, queryParams: {}, bodyParams: {} };
25
+ }
26
+ // Check cache
27
+ const cacheKeyContent = JSON.stringify({
28
+ id: authDefinition.id,
29
+ steps: authDefinition.steps,
30
+ outputs: authDefinition.outputs
31
+ });
32
+ const cacheKey = crypto_1.default.createHash('md5').update(cacheKeyContent).digest('hex');
33
+ const cached = authCache.get(cacheKey);
34
+ if (cached && Date.now() < cached.expiry) {
35
+ return cached.authData;
36
+ }
37
+ const context = {
38
+ env: process.env,
39
+ steps: {},
40
+ variables: {}
41
+ };
42
+ // Execute steps sequentially
43
+ for (const step of authDefinition.steps) {
44
+ try {
45
+ const stepResult = await executeAuthStep(step, context);
46
+ context.steps[step.id] = stepResult;
47
+ }
48
+ catch (stepError) {
49
+ if (step.onError?.action === 'continue') {
50
+ continue;
51
+ }
52
+ throw stepError;
53
+ }
54
+ }
55
+ // Generate outputs
56
+ const authData = generateAuthData(authDefinition.outputs || [], context);
57
+ // Cache the result
58
+ authCache.set(cacheKey, {
59
+ authData,
60
+ expiry: Date.now() + AUTH_CACHE_DURATION_MS
61
+ });
62
+ return authData;
63
+ }
64
+ /**
65
+ * Execute a single auth step
66
+ */
67
+ async function executeAuthStep(step, context) {
68
+ switch (step.type) {
69
+ case 'http_request':
70
+ return await executeHttpRequestStep(step, context);
71
+ case 'load_vars':
72
+ return executeLoadVarsStep(step, context);
73
+ case 'transform':
74
+ return executeTransformStep(step, context);
75
+ case 'condition':
76
+ return executeConditionStep(step, context);
77
+ default:
78
+ throw new Error(`Unknown step type: ${step.type}`);
79
+ }
80
+ }
81
+ /**
82
+ * Execute HTTP request auth step
83
+ */
84
+ async function executeHttpRequestStep(step, context) {
85
+ const request = step.request;
86
+ const url = resolveTemplate(request.url, context);
87
+ const headers = {};
88
+ for (const [key, value] of Object.entries(request.headers || {})) {
89
+ headers[key] = resolveTemplate(value, context);
90
+ }
91
+ let body = null;
92
+ if (request.body && ['POST', 'PUT', 'PATCH'].includes(request.method)) {
93
+ // Check if form-urlencoded
94
+ const isFormUrlEncoded = request.bodyType === 'x-www-form-urlencoded' ||
95
+ (headers['Content-Type'] || '').includes('x-www-form-urlencoded');
96
+ if (isFormUrlEncoded) {
97
+ if (Array.isArray(request.body)) {
98
+ // Key-value pair format: [{key, value}]
99
+ const params = new URLSearchParams();
100
+ for (const pair of request.body) {
101
+ params.append(resolveTemplate(pair.key, context), resolveTemplate(pair.value, context));
102
+ }
103
+ body = params.toString();
104
+ }
105
+ else if (typeof request.body === 'object') {
106
+ // Plain object format (backward compat)
107
+ const resolved = resolveTemplateObject(request.body, context);
108
+ const params = new URLSearchParams();
109
+ for (const [key, value] of Object.entries(resolved)) {
110
+ params.append(key, String(value));
111
+ }
112
+ body = params.toString();
113
+ }
114
+ else {
115
+ body = resolveTemplate(request.body, context);
116
+ }
117
+ if (!headers['Content-Type']) {
118
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
119
+ }
120
+ }
121
+ else if (typeof request.body === 'object') {
122
+ body = resolveTemplateObject(request.body, context);
123
+ if (!headers['Content-Type']) {
124
+ headers['Content-Type'] = 'application/json';
125
+ }
126
+ }
127
+ else {
128
+ body = resolveTemplate(request.body, context);
129
+ }
130
+ }
131
+ const response = await (0, axios_1.default)({
132
+ method: request.method,
133
+ url,
134
+ headers,
135
+ data: body,
136
+ timeout: request.timeout || 30000,
137
+ validateStatus: () => true
138
+ });
139
+ if (response.status >= 400) {
140
+ throw new Error(`HTTP ${response.status}: ${response.statusText || 'Error'}`);
141
+ }
142
+ const responseData = response.data;
143
+ // Extract data from response
144
+ const extractedData = {};
145
+ if (step.extract) {
146
+ for (const extraction of step.extract) {
147
+ try {
148
+ const value = extractJsonPath(responseData, extraction.path) || extraction.defaultValue;
149
+ extractedData[extraction.name] = value;
150
+ }
151
+ catch {
152
+ extractedData[extraction.name] = extraction.defaultValue;
153
+ }
154
+ }
155
+ }
156
+ return {
157
+ response: responseData,
158
+ ...extractedData
159
+ };
160
+ }
161
+ /**
162
+ * Execute load variables step
163
+ */
164
+ function executeLoadVarsStep(step, context) {
165
+ const loadedVars = {};
166
+ for (const variable of step.load || []) {
167
+ let value;
168
+ switch (variable.type) {
169
+ case 'env':
170
+ value = process.env[variable.source];
171
+ break;
172
+ case 'literal':
173
+ value = variable.source;
174
+ break;
175
+ case 'extract':
176
+ value = extractJsonPath(context, variable.source);
177
+ break;
178
+ default:
179
+ value = variable.source;
180
+ }
181
+ loadedVars[variable.name] = value;
182
+ }
183
+ // Apply transformations
184
+ if (step.transform) {
185
+ for (const transform of step.transform) {
186
+ const input = resolveTemplate(transform.input, { ...context, ...loadedVars });
187
+ const transformedValue = applyTransformation(transform.operation, input, transform.parameters);
188
+ loadedVars[transform.name] = transformedValue;
189
+ }
190
+ }
191
+ return loadedVars;
192
+ }
193
+ /**
194
+ * Execute transform step
195
+ */
196
+ function executeTransformStep(step, context) {
197
+ const transformedData = {};
198
+ for (const transform of step.transform || []) {
199
+ const input = resolveTemplate(transform.input, context);
200
+ const transformedValue = applyTransformation(transform.operation, input, transform.parameters);
201
+ transformedData[transform.name] = transformedValue;
202
+ }
203
+ return transformedData;
204
+ }
205
+ /**
206
+ * Execute condition step
207
+ */
208
+ function executeConditionStep(step, context) {
209
+ const condition = step.condition;
210
+ const fieldValue = resolveTemplate(condition.field, context);
211
+ const compareValue = resolveTemplate(condition.value, context);
212
+ let result = false;
213
+ switch (condition.operator) {
214
+ case 'equals':
215
+ result = fieldValue === compareValue;
216
+ break;
217
+ case 'not_equals':
218
+ result = fieldValue !== compareValue;
219
+ break;
220
+ case 'contains':
221
+ result = String(fieldValue).includes(String(compareValue));
222
+ break;
223
+ case 'exists':
224
+ result = fieldValue !== undefined && fieldValue !== null;
225
+ break;
226
+ default:
227
+ result = false;
228
+ }
229
+ return { conditionResult: result, fieldValue, compareValue };
230
+ }
231
+ // ============ Helper Functions ============
232
+ /**
233
+ * Apply transformation to a value
234
+ */
235
+ function applyTransformation(operation, input, parameters = {}) {
236
+ switch (operation) {
237
+ case 'base64':
238
+ return Buffer.from(String(input)).toString('base64');
239
+ case 'concat':
240
+ return Array.isArray(input) ? input.join('') : String(input);
241
+ case 'hash':
242
+ return crypto_1.default.createHash('sha256').update(String(input)).digest('hex');
243
+ case 'json_parse':
244
+ return JSON.parse(String(input));
245
+ case 'url_encode':
246
+ return encodeURIComponent(String(input));
247
+ default:
248
+ return input;
249
+ }
250
+ }
251
+ /**
252
+ * Resolve template variables in a string
253
+ */
254
+ function resolveTemplate(template, context) {
255
+ if (typeof template !== 'string')
256
+ return template;
257
+ return template.replace(/\{\{(.+?)\}\}/g, (match, path) => {
258
+ const value = resolvePath(path.trim(), context);
259
+ return value !== undefined ? String(value) : match;
260
+ });
261
+ }
262
+ /**
263
+ * Resolve template variables in an object
264
+ */
265
+ function resolveTemplateObject(obj, context) {
266
+ if (typeof obj === 'string') {
267
+ return resolveTemplate(obj, context);
268
+ }
269
+ else if (Array.isArray(obj)) {
270
+ return obj.map(item => resolveTemplateObject(item, context));
271
+ }
272
+ else if (typeof obj === 'object' && obj !== null) {
273
+ const resolved = {};
274
+ for (const [key, value] of Object.entries(obj)) {
275
+ resolved[key] = resolveTemplateObject(value, context);
276
+ }
277
+ return resolved;
278
+ }
279
+ return obj;
280
+ }
281
+ /**
282
+ * Resolve a path in the context (e.g., "steps.step1.token")
283
+ */
284
+ function resolvePath(path, context) {
285
+ const parts = path.split('.');
286
+ let current = context;
287
+ for (const part of parts) {
288
+ if (current && typeof current === 'object') {
289
+ current = current[part];
290
+ }
291
+ else {
292
+ return undefined;
293
+ }
294
+ }
295
+ return current;
296
+ }
297
+ /**
298
+ * Extract value using JSONPath (simplified implementation)
299
+ */
300
+ function extractJsonPath(data, path) {
301
+ if (path.startsWith('$.')) {
302
+ path = path.substring(2);
303
+ }
304
+ return resolvePath(path, data);
305
+ }
306
+ /**
307
+ * Generate auth data from outputs
308
+ */
309
+ function generateAuthData(outputs, context) {
310
+ const authData = {
311
+ headers: {},
312
+ queryParams: {},
313
+ bodyParams: {}
314
+ };
315
+ for (const output of outputs) {
316
+ const value = resolveTemplate(output.value, context);
317
+ switch (output.type) {
318
+ case 'header':
319
+ authData.headers[output.name] = value;
320
+ break;
321
+ case 'query_param':
322
+ authData.queryParams[output.name] = value;
323
+ break;
324
+ case 'body_param':
325
+ authData.bodyParams[output.name] = value;
326
+ break;
327
+ }
328
+ }
329
+ return authData;
330
+ }
331
+ /**
332
+ * Apply auth data to request config (headers, query params)
333
+ */
334
+ function applyAuthToRequest(requestConfig, authData) {
335
+ // Apply auth headers
336
+ if (authData.headers && Object.keys(authData.headers).length > 0) {
337
+ requestConfig.headers = {
338
+ ...requestConfig.headers,
339
+ ...authData.headers
340
+ };
341
+ }
342
+ // Apply query params (append to URL)
343
+ if (authData.queryParams && Object.keys(authData.queryParams).length > 0) {
344
+ const url = new URL(requestConfig.url);
345
+ for (const [key, value] of Object.entries(authData.queryParams)) {
346
+ url.searchParams.set(key, value);
347
+ }
348
+ requestConfig.url = url.toString();
349
+ }
350
+ }
351
+ //# sourceMappingURL=AuthFlowExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthFlowExecutor.js","sourceRoot":"","sources":["../src/AuthFlowExecutor.ts"],"names":[],"mappings":"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"}
@@ -168,21 +168,21 @@ function generateTestFile(test, baseUrl) {
168
168
  const description = test.description ? `\n * ${test.description}` : '';
169
169
  const tags = test.tags?.length ? `\n * Tags: ${test.tags.join(', ')}` : '';
170
170
  const priority = test.priority ? `\n * Priority: ${test.priority}` : '';
171
- return `/**
172
- * Test: ${test.name}${description}${tags}${priority}
173
- *
174
- * Generated by Qate CLI
175
- * Do not edit manually - regenerate using: qate export
176
- */
177
-
178
- import axios from 'axios';
179
- import { describe, test, expect } from 'vitest';
180
-
181
- const BASE_URL = '${escapeString(baseUrl)}';
182
-
183
- describe('${escapeString(test.name)}', () => {
184
- ${stepCode}
185
- });
171
+ return `/**
172
+ * Test: ${test.name}${description}${tags}${priority}
173
+ *
174
+ * Generated by Qate CLI
175
+ * Do not edit manually - regenerate using: qate export
176
+ */
177
+
178
+ import axios from 'axios';
179
+ import { describe, test, expect } from 'vitest';
180
+
181
+ const BASE_URL = '${escapeString(baseUrl)}';
182
+
183
+ describe('${escapeString(test.name)}', () => {
184
+ ${stepCode}
185
+ });
186
186
  `;
187
187
  }
188
188
  /**
@@ -211,14 +211,14 @@ function generatePackageJson(name) {
211
211
  * Generate vitest.config.ts
212
212
  */
213
213
  function generateVitestConfig() {
214
- return `import { defineConfig } from 'vitest/config';
215
-
216
- export default defineConfig({
217
- test: {
218
- globals: true,
219
- testTimeout: 30000,
220
- },
221
- });
214
+ return `import { defineConfig } from 'vitest/config';
215
+
216
+ export default defineConfig({
217
+ test: {
218
+ globals: true,
219
+ testTimeout: 30000,
220
+ },
221
+ });
222
222
  `;
223
223
  }
224
224
  /**
@@ -250,11 +250,11 @@ function generateAxiosSummary(exportData) {
250
250
  const appType = exportData.application?.type || 'unknown';
251
251
  const type = exportData.type === 'testsequence' ? 'Test Sequence' : 'Test Set';
252
252
  const name = exportData.testSequence?.name || exportData.testSet?.name || 'Unknown';
253
- return `
254
- Generating Axios tests from ${type}: "${name}"
255
- Application: ${appName} (${appType}) - ${appUrl}
256
- Tests: ${testCount}
257
- Total Steps: ${stepCount}
253
+ return `
254
+ Generating Axios tests from ${type}: "${name}"
255
+ Application: ${appName} (${appType}) - ${appUrl}
256
+ Tests: ${testCount}
257
+ Total Steps: ${stepCount}
258
258
  `;
259
259
  }
260
260
  //# sourceMappingURL=AxiosGenerator.js.map
@@ -0,0 +1,12 @@
1
+ import { TestResult, ExecutionStatus } from './client';
2
+ /**
3
+ * Generate JUnit XML from TestResult[] (REST/SOAP local execution).
4
+ * Each TestResult becomes a <testsuite>, each StepResult becomes a <testcase>.
5
+ */
6
+ export declare function generateJunitXml(results: TestResult[] | null | undefined, suiteName?: string): string;
7
+ /**
8
+ * Generate JUnit XML from ExecutionStatus (desktop app polling).
9
+ * No step-level detail available — each test becomes a single <testcase>.
10
+ */
11
+ export declare function generateJunitXmlFromStatus(status: ExecutionStatus | null | undefined, suiteName?: string): string;
12
+ //# sourceMappingURL=JunitXmlGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JunitXmlGenerator.d.ts","sourceRoot":"","sources":["../src/JunitXmlGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAiBvD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAqFrG;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBjH"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateJunitXml = generateJunitXml;
4
+ exports.generateJunitXmlFromStatus = generateJunitXmlFromStatus;
5
+ function escapeXml(str) {
6
+ if (str == null)
7
+ return '';
8
+ return String(str)
9
+ .replace(/&/g, '&amp;')
10
+ .replace(/</g, '&lt;')
11
+ .replace(/>/g, '&gt;')
12
+ .replace(/"/g, '&quot;')
13
+ .replace(/'/g, '&apos;');
14
+ }
15
+ function safeDuration(duration) {
16
+ if (duration == null || isNaN(duration))
17
+ return '0.000';
18
+ return (duration / 1000).toFixed(3);
19
+ }
20
+ /**
21
+ * Generate JUnit XML from TestResult[] (REST/SOAP local execution).
22
+ * Each TestResult becomes a <testsuite>, each StepResult becomes a <testcase>.
23
+ */
24
+ function generateJunitXml(results, suiteName) {
25
+ const safeResults = Array.isArray(results) ? results : [];
26
+ const safeSuiteName = suiteName || 'Qate Tests';
27
+ const timestamp = new Date().toISOString();
28
+ let totalTests = 0;
29
+ let totalFailures = 0;
30
+ let totalErrors = 0;
31
+ let totalTime = 0;
32
+ const suites = [];
33
+ for (const result of safeResults) {
34
+ const testName = result?.testName || 'Unknown Test';
35
+ const steps = Array.isArray(result?.steps) && result.steps.length > 0 ? result.steps : null;
36
+ if (steps) {
37
+ // Create testcases from steps
38
+ let suiteTests = 0;
39
+ let suiteFailures = 0;
40
+ let suiteErrors = 0;
41
+ let suiteTime = 0;
42
+ const testcases = [];
43
+ for (let i = 0; i < steps.length; i++) {
44
+ const step = steps[i];
45
+ const stepName = step?.description || `Step ${i + 1}`;
46
+ const stepDuration = safeDuration(step?.duration);
47
+ suiteTime += (step?.duration != null && !isNaN(step.duration)) ? step.duration : 0;
48
+ suiteTests++;
49
+ let inner = '';
50
+ if (step?.status === 'failed') {
51
+ suiteFailures++;
52
+ const msg = escapeXml(step.error || 'Test step failed');
53
+ inner = `\n <failure message="${msg}" type="TestFailure">${msg}</failure>`;
54
+ }
55
+ else if (step?.status === 'error') {
56
+ suiteErrors++;
57
+ const msg = escapeXml(step.error || 'Test step error');
58
+ inner = `\n <error message="${msg}" type="TestError">${msg}</error>`;
59
+ }
60
+ testcases.push(` <testcase name="${escapeXml(stepName)}" classname="${escapeXml(testName)}" time="${stepDuration}">${inner}\n </testcase>`);
61
+ }
62
+ totalTests += suiteTests;
63
+ totalFailures += suiteFailures;
64
+ totalErrors += suiteErrors;
65
+ totalTime += suiteTime;
66
+ suites.push(` <testsuite name="${escapeXml(testName)}" tests="${suiteTests}" failures="${suiteFailures}" errors="${suiteErrors}" time="${safeDuration(suiteTime)}" timestamp="${timestamp}">\n${testcases.join('\n')}\n </testsuite>`);
67
+ }
68
+ else {
69
+ // No steps — create a single testcase from test-level data
70
+ totalTests++;
71
+ const duration = (result?.duration != null && !isNaN(result.duration)) ? result.duration : 0;
72
+ totalTime += duration;
73
+ let inner = '';
74
+ if (result?.status === 'failed') {
75
+ totalFailures++;
76
+ inner = `\n <failure message="Test failed" type="TestFailure">Test failed</failure>`;
77
+ }
78
+ else if (result?.status === 'error') {
79
+ totalErrors++;
80
+ inner = `\n <error message="Test error" type="TestError">Test error</error>`;
81
+ }
82
+ suites.push(` <testsuite name="${escapeXml(testName)}" tests="1" failures="${result?.status === 'failed' ? 1 : 0}" errors="${result?.status === 'error' ? 1 : 0}" time="${safeDuration(duration)}" timestamp="${timestamp}">\n <testcase name="${escapeXml(testName)}" classname="${escapeXml(testName)}" time="${safeDuration(duration)}">${inner}\n </testcase>\n </testsuite>`);
83
+ }
84
+ }
85
+ const lines = [
86
+ '<?xml version="1.0" encoding="UTF-8"?>',
87
+ `<testsuites name="${escapeXml(safeSuiteName)}" tests="${totalTests}" failures="${totalFailures}" errors="${totalErrors}" time="${safeDuration(totalTime)}" timestamp="${timestamp}">`,
88
+ ...suites,
89
+ '</testsuites>',
90
+ ''
91
+ ];
92
+ return lines.join('\n');
93
+ }
94
+ /**
95
+ * Generate JUnit XML from ExecutionStatus (desktop app polling).
96
+ * No step-level detail available — each test becomes a single <testcase>.
97
+ */
98
+ function generateJunitXmlFromStatus(status, suiteName) {
99
+ if (!status) {
100
+ return generateJunitXml([], suiteName);
101
+ }
102
+ const tests = Array.isArray(status.tests) ? status.tests : [];
103
+ const results = tests.map((t) => ({
104
+ testId: t?.testId || '',
105
+ testName: t?.testName || 'Unknown Test',
106
+ status: (t?.status === 'passed' || t?.status === 'failed' || t?.status === 'error')
107
+ ? t.status
108
+ : 'error',
109
+ duration: (t?.executionTime != null && !isNaN(t.executionTime)) ? t.executionTime : 0,
110
+ steps: undefined
111
+ }));
112
+ return generateJunitXml(results, suiteName || status.testSetName || status.sequenceName || 'Qate Tests');
113
+ }
114
+ //# sourceMappingURL=JunitXmlGenerator.js.map