@uipath/test-manager-tool 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/tool.js +1247 -920
  2. package/package.json +9 -9
package/dist/tool.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@uipath/test-manager-tool",
4
- version: "0.1.8",
4
+ version: "0.1.10",
5
5
  description: "Manage test cases, test sets, executions, and results.",
6
6
  private: false,
7
7
  maintainers: [
@@ -11,14 +11,14 @@ var package_default = {
11
11
  ],
12
12
  repository: {
13
13
  type: "git",
14
- url: "https://github.com/UiPath/uipcli.git",
14
+ url: "https://github.com/UiPath/cli.git",
15
15
  directory: "packages/test-manager-tool"
16
16
  },
17
17
  publishConfig: {
18
- registry: "https://registry.npmjs.org/"
18
+ registry: "https://npm.pkg.github.com/@uipath"
19
19
  },
20
20
  keywords: [
21
- "uipcli-tool"
21
+ "cli-tool"
22
22
  ],
23
23
  type: "module",
24
24
  main: "./dist/tool.js",
@@ -32,27 +32,29 @@ var package_default = {
32
32
  "dist"
33
33
  ],
34
34
  scripts: {
35
- build: "bun build ./src/tool.ts --outdir dist --format esm --target node --external commander --external @uipath/common --external @uipath/auth --external @uipath/filesystem && bun build ./src/index.ts --outdir dist --format esm --target node --external '*/tool.js' --external commander --external @uipath/common --external @uipath/auth --external @uipath/filesystem",
35
+ build: "bun ../../tools/build-tool.ts",
36
36
  package: "bun run build && bun pm pack",
37
37
  lint: "biome check .",
38
38
  "lint:fix": "biome check --write ."
39
39
  },
40
40
  peerDependencies: {
41
41
  commander: "^14.0.3",
42
- "@uipath/common": "^0.1.7",
43
- "@uipath/auth": "^0.1.6",
42
+ "@uipath/common": "^0.1.13",
43
+ "@uipath/auth": "^0.1.9",
44
44
  "@uipath/filesystem": "^0.1.6"
45
45
  },
46
46
  devDependencies: {
47
47
  "@uipath/orchestrator-sdk": "workspace:*",
48
48
  "@uipath/test-manager-sdk": "workspace:*",
49
- "@types/node": "^25.2.3",
49
+ "@types/node": "^25.5.0",
50
50
  typescript: "^5"
51
51
  }
52
52
  };
53
53
 
54
54
  // src/commands/attachment.ts
55
55
  import {
56
+ catchError as catchError2,
57
+ extractErrorDetails,
56
58
  logger as logger2,
57
59
  OutputFormatter as OutputFormatter2,
58
60
  processContext,
@@ -2093,6 +2095,7 @@ if (false) {}
2093
2095
  // src/utils/context.ts
2094
2096
  import { getLoginStatusAsync } from "@uipath/auth";
2095
2097
  import {
2098
+ catchError,
2096
2099
  configureLogger,
2097
2100
  LogLevel,
2098
2101
  logger,
@@ -2171,12 +2174,10 @@ async function resolveCommandContext(options) {
2171
2174
  accessToken
2172
2175
  });
2173
2176
  const projectsApi = new ProjectsApi(tmConfig);
2174
- let project;
2175
- try {
2176
- project = await projectsApi.projectsGetProjectByProjectPrefix({
2177
- projectPrefix: projectKey
2178
- });
2179
- } catch {
2177
+ const [projectError, project] = await catchError(projectsApi.projectsGetProjectByProjectPrefix({
2178
+ projectPrefix: projectKey
2179
+ }));
2180
+ if (projectError) {
2180
2181
  OutputFormatter.error({
2181
2182
  Result: "Failure",
2182
2183
  Message: `Project '${projectKey}' not found.`
@@ -2206,65 +2207,19 @@ async function resolveCommandContext(options) {
2206
2207
  };
2207
2208
  }
2208
2209
 
2209
- // src/utils/error-handler.ts
2210
- async function extractErrorDetails(error) {
2211
- const status = error.status || error.response?.status;
2212
- let rawBody;
2213
- let extractedMessage;
2214
- if (error.response) {
2215
- try {
2216
- rawBody = await error.response.text();
2217
- if (rawBody) {
2218
- try {
2219
- const parsed = JSON.parse(rawBody);
2220
- if (parsed?.errors && typeof parsed.errors === "object") {
2221
- for (const field of Object.values(parsed.errors)) {
2222
- if (Array.isArray(field) && field.length > 0 && field[0]?.message) {
2223
- extractedMessage = field[0].message;
2224
- break;
2225
- }
2226
- }
2227
- }
2228
- if (!extractedMessage) {
2229
- extractedMessage = parsed?.message || parsed?.errorMessage || parsed?.title;
2230
- }
2231
- } catch {
2232
- extractedMessage = rawBody;
2233
- }
2234
- }
2235
- } catch {}
2236
- }
2237
- let message;
2238
- if (status === 401) {
2239
- message = "Unauthorized (401). Run `uip login` to authenticate.";
2240
- } else if (status === 403) {
2241
- message = "Forbidden (403). Ensure the account has the required Test Manager permissions (TestExecution.Read, TestSet.Read, etc.).";
2242
- } else if (status === 405) {
2243
- message = "Method Not Allowed (405). The endpoint may not exist or the base URL may be incorrect.";
2244
- } else {
2245
- const baseMessage = extractedMessage || error.message || "Unknown error";
2246
- message = status ? `HTTP ${status}: ${baseMessage}` : baseMessage;
2247
- }
2248
- let details = error.message || String(error);
2249
- if (rawBody) {
2250
- try {
2251
- const parsed = JSON.parse(rawBody);
2252
- const extra = {};
2253
- if (parsed.errorCode)
2254
- extra.errorCode = parsed.errorCode;
2255
- if (parsed.details)
2256
- extra.details = parsed.details;
2257
- if (parsed.errors != null)
2258
- extra.errors = parsed.errors;
2259
- if (parsed.data && Object.keys(parsed.data).length > 0)
2260
- extra.data = parsed.data;
2261
- details = Object.keys(extra).length > 0 ? JSON.stringify(extra) : rawBody;
2262
- } catch {
2263
- details = rawBody;
2264
- }
2265
- }
2266
- return { message, details };
2210
+ // src/utils/shared.ts
2211
+ var TERMINAL_STATUSES = new Set(["finished", "cancelled"]);
2212
+ function msToDuration(ms) {
2213
+ const totalSec = Math.floor(ms / 1000);
2214
+ const h = Math.floor(totalSec / 3600);
2215
+ const m = Math.floor(totalSec % 3600 / 60);
2216
+ const s = totalSec % 60;
2217
+ return [h, m, s].map((v) => String(v).padStart(2, "0")).join(":");
2218
+ }
2219
+ function calcPassRate(passed, total) {
2220
+ return total > 0 ? Math.round(passed / total * 1000) / 10 : 0;
2267
2221
  }
2222
+ var TM_FORBIDDEN_MESSAGE = "Forbidden (403). Ensure the account has the required Test Manager permissions (TestExecution.Read, TestSet.Read, etc.).";
2268
2223
 
2269
2224
  // src/commands/attachment.ts
2270
2225
  var OBJECT_TYPE_TEST_CASE_LOG = "testCaseLog";
@@ -2278,7 +2233,7 @@ var registerAttachmentCommand = (program) => {
2278
2233
  if (!ctx)
2279
2234
  return;
2280
2235
  const { tmConfig, tmBaseUrl, projectId, accessToken } = ctx;
2281
- try {
2236
+ const [error] = await catchError2((async () => {
2282
2237
  const fs = getFileSystem();
2283
2238
  const executionId = options.executionId;
2284
2239
  const nameFilters = options.testCaseName;
@@ -2313,11 +2268,9 @@ var registerAttachmentCommand = (program) => {
2313
2268
  const tc = log.testCase;
2314
2269
  const testCaseName = tc?.packageEntryPointName ?? tc?.name ?? log.automationTestCaseName ?? logId;
2315
2270
  logger2.info(`Processing test case: ${testCaseName} (log ${logId})`);
2316
- let attachments;
2317
- try {
2318
- attachments = await listAttachments(tmBaseUrl, accessToken, projectId, logId);
2319
- } catch (err) {
2320
- const msg = err instanceof Error ? err.message : String(err);
2271
+ const [listErr, attachments] = await catchError2(listAttachments(tmBaseUrl, accessToken, projectId, logId));
2272
+ if (listErr) {
2273
+ const msg = listErr instanceof Error ? listErr.message : String(listErr);
2321
2274
  logger2.warn(`Failed to list attachments for '${testCaseName}': ${msg}`);
2322
2275
  skipped.push(`${testCaseName}: ${msg}`);
2323
2276
  continue;
@@ -2332,15 +2285,15 @@ var registerAttachmentCommand = (program) => {
2332
2285
  if (!attachmentId)
2333
2286
  continue;
2334
2287
  const fileName = attachment.fileName ?? `${attachmentId}${attachment.fileExtension ? `.${attachment.fileExtension}` : ""}`;
2335
- try {
2336
- const data = await downloadAttachment(tmBaseUrl, accessToken, projectId, attachmentId);
2288
+ const [dlErr, data] = await catchError2(downloadAttachment(tmBaseUrl, accessToken, projectId, attachmentId));
2289
+ if (dlErr) {
2290
+ const msg = dlErr instanceof Error ? dlErr.message : String(dlErr);
2291
+ logger2.warn(` Failed to download '${fileName}': ${msg}`);
2292
+ } else {
2337
2293
  const outPath = fs.path.join(testCaseDir, sanitizeName(fileName));
2338
2294
  await fs.writeFile(outPath, new Uint8Array(data));
2339
2295
  logger2.info(` Downloaded: ${fileName} → ${outPath}`);
2340
2296
  totalDownloaded++;
2341
- } catch (err) {
2342
- const msg = err instanceof Error ? err.message : String(err);
2343
- logger2.warn(` Failed to download '${fileName}': ${msg}`);
2344
2297
  }
2345
2298
  }
2346
2299
  }
@@ -2351,14 +2304,18 @@ var registerAttachmentCommand = (program) => {
2351
2304
  MatchedTestCases: logs.length,
2352
2305
  ...skipped.length > 0 && { Skipped: skipped }
2353
2306
  }));
2354
- } catch (error) {
2355
- const { message, details } = await extractErrorDetails(error);
2307
+ })());
2308
+ if (error) {
2309
+ const { message, details } = await extractErrorDetails(error, {
2310
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2311
+ });
2356
2312
  OutputFormatter2.error({
2357
2313
  Result: "Failure",
2358
2314
  Message: message,
2359
2315
  Instructions: details
2360
2316
  });
2361
2317
  processContext.exit(1);
2318
+ return;
2362
2319
  }
2363
2320
  });
2364
2321
  };
@@ -2410,26 +2367,13 @@ function sanitizeName(name) {
2410
2367
 
2411
2368
  // src/commands/execution.ts
2412
2369
  import {
2370
+ catchError as catchError3,
2371
+ extractErrorDetails as extractErrorDetails2,
2413
2372
  logger as logger3,
2414
2373
  OutputFormatter as OutputFormatter3,
2415
2374
  processContext as processContext2,
2416
2375
  SuccessOutput as SuccessOutput2
2417
2376
  } from "@uipath/common";
2418
-
2419
- // src/utils/shared.ts
2420
- var TERMINAL_STATUSES = new Set(["finished", "cancelled"]);
2421
- function msToDuration(ms) {
2422
- const totalSec = Math.floor(ms / 1000);
2423
- const h = Math.floor(totalSec / 3600);
2424
- const m = Math.floor(totalSec % 3600 / 60);
2425
- const s = totalSec % 60;
2426
- return [h, m, s].map((v) => String(v).padStart(2, "0")).join(":");
2427
- }
2428
- function calcPassRate(passed, total) {
2429
- return total > 0 ? Math.round(passed / total * 1000) / 10 : 0;
2430
- }
2431
-
2432
- // src/commands/execution.ts
2433
2377
  var registerExecutionCommand = (program) => {
2434
2378
  const executionCmd = program.command("execution").description("Manage Test Manager test executions");
2435
2379
  executionCmd.command("retry").description("Retry only the failed test cases of a finished execution.").requiredOption("--execution-id <uuid>", "Test execution UUID to retry").option("--project-key <key>", "Test Manager project key (e.g. DEMO)").option("--test-set-key <key>", "Test set key to derive project key from (e.g. DEMO:42 → DEMO)").option("--execution-type <type>", "Execution type for the retry: automated, manual, mixed, none", "automated").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext2, async (options) => {
@@ -2437,66 +2381,86 @@ var registerExecutionCommand = (program) => {
2437
2381
  if (!ctx)
2438
2382
  return;
2439
2383
  const { tmConfig, projectId } = ctx;
2440
- try {
2441
- const executionId = options.executionId;
2442
- logger3.info(`Fetching execution stats for ${executionId}`);
2443
- const executionsApi = new TestExecutionsApi(tmConfig);
2444
- const currentStats = await executionsApi.testExecutionsGetByIdWithStats({
2445
- id: executionId,
2446
- projectId
2384
+ const executionId = options.executionId;
2385
+ logger3.info(`Fetching execution stats for ${executionId}`);
2386
+ const executionsApi = new TestExecutionsApi(tmConfig);
2387
+ const [statsErr, currentStats] = await catchError3(executionsApi.testExecutionsGetByIdWithStats({
2388
+ id: executionId,
2389
+ projectId
2390
+ }));
2391
+ if (statsErr) {
2392
+ const { message, details } = await extractErrorDetails2(statsErr, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
2393
+ OutputFormatter3.error({
2394
+ Result: "Failure",
2395
+ Message: message,
2396
+ Instructions: details
2447
2397
  });
2448
- const currentStatus = currentStats.status ?? "";
2449
- if (!TERMINAL_STATUSES.has(currentStatus.toLowerCase())) {
2450
- OutputFormatter3.error({
2451
- Result: "Failure",
2452
- Message: `Execution '${executionId}' is not in a terminal state (current: ${currentStatus}). Wait for it to finish before retrying.`
2453
- });
2454
- processContext2.exit(1);
2455
- return;
2456
- }
2457
- const failedCount = currentStats.failed ?? 0;
2458
- if (failedCount === 0) {
2459
- OutputFormatter3.success(new SuccessOutput2("ExecutionRetry", {
2460
- Message: `Execution '${executionId}' has no failed test cases to retry.`
2461
- }));
2462
- return;
2463
- }
2464
- logger3.info(`Collecting failed test case log IDs for execution ${executionId}`);
2465
- const testCaseLogsApi = new TestCaseLogsApi(tmConfig);
2466
- const failedLogIds = await fetchAllFailedLogIds(testCaseLogsApi, projectId, executionId);
2467
- if (failedLogIds.length === 0) {
2468
- OutputFormatter3.error({
2469
- Result: "Failure",
2470
- Message: `No failed test case logs found for execution '${executionId}'.`
2471
- });
2472
- processContext2.exit(1);
2473
- return;
2474
- }
2475
- logger3.info(`Found ${failedLogIds.length} failed test case log(s) to retry`);
2476
- logger3.info(`Starting retry for execution ${executionId}`);
2477
- await executionsApi.testExecutionsExecute({
2478
- id: executionId,
2479
- projectId,
2480
- uiPathTestManagementHubTestManagementAbstractionsDTOsStartExecutionRequest: {
2481
- executionType: options.executionType,
2482
- testCaseLogIds: failedLogIds
2483
- }
2398
+ processContext2.exit(1);
2399
+ return;
2400
+ }
2401
+ const currentStatus = currentStats.status ?? "";
2402
+ if (!TERMINAL_STATUSES.has(currentStatus.toLowerCase())) {
2403
+ OutputFormatter3.error({
2404
+ Result: "Failure",
2405
+ Message: `Execution '${executionId}' is not in a terminal state (current: ${currentStatus}). Wait for it to finish before retrying.`
2484
2406
  });
2407
+ processContext2.exit(1);
2408
+ return;
2409
+ }
2410
+ const failedCount = currentStats.failed ?? 0;
2411
+ if (failedCount === 0) {
2485
2412
  OutputFormatter3.success(new SuccessOutput2("ExecutionRetry", {
2486
- ExecutionId: executionId,
2487
- Status: "Running",
2488
- StartTime: new Date().toISOString(),
2489
- RetriedCount: failedLogIds.length
2413
+ Message: `Execution '${executionId}' has no failed test cases to retry.`
2490
2414
  }));
2491
- } catch (error) {
2492
- const { message, details } = await extractErrorDetails(error);
2415
+ return;
2416
+ }
2417
+ logger3.info(`Collecting failed test case log IDs for execution ${executionId}`);
2418
+ const testCaseLogsApi = new TestCaseLogsApi(tmConfig);
2419
+ const [logsErr, failedLogIds] = await catchError3(fetchAllFailedLogIds(testCaseLogsApi, projectId, executionId));
2420
+ if (logsErr) {
2421
+ const { message, details } = await extractErrorDetails2(logsErr, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
2422
+ OutputFormatter3.error({
2423
+ Result: "Failure",
2424
+ Message: message,
2425
+ Instructions: details
2426
+ });
2427
+ processContext2.exit(1);
2428
+ return;
2429
+ }
2430
+ if (failedLogIds.length === 0) {
2431
+ OutputFormatter3.error({
2432
+ Result: "Failure",
2433
+ Message: `No failed test case logs found for execution '${executionId}'.`
2434
+ });
2435
+ processContext2.exit(1);
2436
+ return;
2437
+ }
2438
+ logger3.info(`Found ${failedLogIds.length} failed test case log(s) to retry`);
2439
+ logger3.info(`Starting retry for execution ${executionId}`);
2440
+ const [retryErr] = await catchError3(executionsApi.testExecutionsExecute({
2441
+ id: executionId,
2442
+ projectId,
2443
+ uiPathTestManagementHubTestManagementAbstractionsDTOsStartExecutionRequest: {
2444
+ executionType: options.executionType,
2445
+ testCaseLogIds: failedLogIds
2446
+ }
2447
+ }));
2448
+ if (retryErr) {
2449
+ const { message, details } = await extractErrorDetails2(retryErr, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
2493
2450
  OutputFormatter3.error({
2494
2451
  Result: "Failure",
2495
2452
  Message: message,
2496
2453
  Instructions: details
2497
2454
  });
2498
2455
  processContext2.exit(1);
2456
+ return;
2499
2457
  }
2458
+ OutputFormatter3.success(new SuccessOutput2("ExecutionRetry", {
2459
+ ExecutionId: executionId,
2460
+ Status: "Running",
2461
+ StartTime: new Date().toISOString(),
2462
+ RetriedCount: failedLogIds.length
2463
+ }));
2500
2464
  });
2501
2465
  };
2502
2466
  async function fetchAllFailedLogIds(api, projectId, testExecutionId) {
@@ -2525,7 +2489,13 @@ async function fetchAllFailedLogIds(api, projectId, testExecutionId) {
2525
2489
  }
2526
2490
 
2527
2491
  // src/commands/project.ts
2528
- import { OutputFormatter as OutputFormatter4, processContext as processContext3, SuccessOutput as SuccessOutput3 } from "@uipath/common";
2492
+ import {
2493
+ catchError as catchError4,
2494
+ extractErrorDetails as extractErrorDetails3,
2495
+ OutputFormatter as OutputFormatter4,
2496
+ processContext as processContext3,
2497
+ SuccessOutput as SuccessOutput3
2498
+ } from "@uipath/common";
2529
2499
  var registerProjectCommand = (program) => {
2530
2500
  const projectCmd = program.command("project").description("Manage Test Manager projects");
2531
2501
  projectCmd.command("list").description("List all Test Manager projects.").option("--filter <text>", "Filter projects by name").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
@@ -2533,7 +2503,7 @@ var registerProjectCommand = (program) => {
2533
2503
  if (!ctx)
2534
2504
  return;
2535
2505
  const { tmConfig } = ctx;
2536
- try {
2506
+ const [error, rows] = await catchError4((async () => {
2537
2507
  const projectsApi = new ProjectsApi(tmConfig);
2538
2508
  const all = [];
2539
2509
  const top = 50;
@@ -2549,123 +2519,139 @@ var registerProjectCommand = (program) => {
2549
2519
  if (skip >= (page.total ?? 0) || (page.data ?? []).length < top)
2550
2520
  break;
2551
2521
  }
2552
- const rows = all.map((p) => ({
2522
+ return all.map((p) => ({
2553
2523
  ProjectKey: p.projectPrefix ?? "",
2554
2524
  Name: p.name ?? "",
2555
2525
  Description: p.description ?? "",
2556
2526
  Active: p.isActive ?? true
2557
2527
  }));
2558
- OutputFormatter4.success(new SuccessOutput3("ProjectsList", rows));
2559
- } catch (error) {
2560
- const { message, details } = await extractErrorDetails(error);
2528
+ })());
2529
+ if (error) {
2530
+ const { message, details } = await extractErrorDetails3(error, {
2531
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2532
+ });
2561
2533
  OutputFormatter4.error({
2562
2534
  Result: "Failure",
2563
2535
  Message: message,
2564
2536
  Instructions: details
2565
2537
  });
2566
2538
  processContext3.exit(1);
2539
+ return;
2567
2540
  }
2541
+ OutputFormatter4.success(new SuccessOutput3("ProjectsList", rows));
2568
2542
  });
2569
2543
  projectCmd.command("create").description("Create a new Test Manager project.").requiredOption("--name <name>", "Project name").requiredOption("--project-key <key>", "Project key / prefix (e.g. MYPROJ)").option("--description <text>", "Project description").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2570
2544
  const ctx = await resolveBaseContext(options);
2571
2545
  if (!ctx)
2572
2546
  return;
2573
2547
  const { tmConfig } = ctx;
2574
- try {
2575
- const projectsApi = new ProjectsApi(tmConfig);
2576
- const project = await projectsApi.projectsCreate({
2577
- uiPathTestManagementHubTestManagementAbstractionsDTOsCreateProjectRequest: {
2578
- name: options.name,
2579
- description: options.description ?? "",
2580
- projectPrefix: options.projectKey,
2581
- isActive: true
2582
- }
2548
+ const projectsApi = new ProjectsApi(tmConfig);
2549
+ const [error, project] = await catchError4(projectsApi.projectsCreate({
2550
+ uiPathTestManagementHubTestManagementAbstractionsDTOsCreateProjectRequest: {
2551
+ name: options.name,
2552
+ description: options.description ?? "",
2553
+ projectPrefix: options.projectKey,
2554
+ isActive: true
2555
+ }
2556
+ }));
2557
+ if (error) {
2558
+ const { message, details } = await extractErrorDetails3(error, {
2559
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2583
2560
  });
2584
- OutputFormatter4.success(new SuccessOutput3("ProjectCreate", {
2585
- ProjectKey: project.projectPrefix ?? "",
2586
- Id: project.id ?? "",
2587
- Name: project.name ?? "",
2588
- Description: project.description ?? ""
2589
- }));
2590
- } catch (error) {
2591
- const { message, details } = await extractErrorDetails(error);
2592
2561
  OutputFormatter4.error({
2593
2562
  Result: "Failure",
2594
2563
  Message: message,
2595
2564
  Instructions: details
2596
2565
  });
2597
2566
  processContext3.exit(1);
2567
+ return;
2598
2568
  }
2569
+ OutputFormatter4.success(new SuccessOutput3("ProjectCreate", {
2570
+ ProjectKey: project.projectPrefix ?? "",
2571
+ Id: project.id ?? "",
2572
+ Name: project.name ?? "",
2573
+ Description: project.description ?? ""
2574
+ }));
2599
2575
  });
2600
2576
  projectCmd.command("update").description("Update a Test Manager project name or description.").requiredOption("--project-key <key>", "Project key / prefix (e.g. MYPROJ)").option("--name <name>", "New project name").option("--description <text>", "New project description").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2601
2577
  const ctx = await resolveBaseContext(options);
2602
2578
  if (!ctx)
2603
2579
  return;
2604
2580
  const { tmConfig } = ctx;
2605
- try {
2581
+ const [error, existing] = await catchError4((async () => {
2606
2582
  const projectsApi = new ProjectsApi(tmConfig);
2607
- const existing = await projectsApi.projectsGetProjectByProjectPrefix({
2583
+ const proj = await projectsApi.projectsGetProjectByProjectPrefix({
2608
2584
  projectPrefix: options.projectKey
2609
2585
  });
2610
- if (!existing.id)
2586
+ if (!proj.id)
2611
2587
  throw new Error(`Project '${options.projectKey}' not found.`);
2612
2588
  await projectsApi.projectsUpdate({
2613
- id: existing.id,
2589
+ id: proj.id,
2614
2590
  uiPathTestManagementHubTestManagementAbstractionsDTOsUpdateProjectRequest: {
2615
- name: options.name ?? existing.name,
2616
- description: options.description ?? existing.description
2591
+ name: options.name ?? proj.name,
2592
+ description: options.description ?? proj.description
2617
2593
  }
2618
2594
  });
2619
- OutputFormatter4.success(new SuccessOutput3("ProjectUpdate", {
2620
- ProjectKey: options.projectKey,
2621
- Id: existing.id,
2622
- Name: options.name ?? existing.name ?? "",
2623
- Description: options.description ?? existing.description ?? ""
2624
- }));
2625
- } catch (error) {
2626
- const { message, details } = await extractErrorDetails(error);
2595
+ return proj;
2596
+ })());
2597
+ if (error) {
2598
+ const { message, details } = await extractErrorDetails3(error, {
2599
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2600
+ });
2627
2601
  OutputFormatter4.error({
2628
2602
  Result: "Failure",
2629
2603
  Message: message,
2630
2604
  Instructions: details
2631
2605
  });
2632
2606
  processContext3.exit(1);
2607
+ return;
2633
2608
  }
2609
+ OutputFormatter4.success(new SuccessOutput3("ProjectUpdate", {
2610
+ ProjectKey: options.projectKey,
2611
+ Id: existing.id,
2612
+ Name: options.name ?? existing.name ?? "",
2613
+ Description: options.description ?? existing.description ?? ""
2614
+ }));
2634
2615
  });
2635
2616
  projectCmd.command("delete").description("Delete a Test Manager project by its key.").requiredOption("--project-key <key>", "Project key / prefix (e.g. MYPROJ)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2636
2617
  const ctx = await resolveBaseContext(options);
2637
2618
  if (!ctx)
2638
2619
  return;
2639
2620
  const { tmConfig } = ctx;
2640
- try {
2621
+ const [error, project] = await catchError4((async () => {
2641
2622
  const projectsApi = new ProjectsApi(tmConfig);
2642
- const project = await projectsApi.projectsGetProjectByProjectPrefix({
2623
+ const proj = await projectsApi.projectsGetProjectByProjectPrefix({
2643
2624
  projectPrefix: options.projectKey
2644
2625
  });
2645
- if (!project.id)
2626
+ if (!proj.id)
2646
2627
  throw new Error(`Project '${options.projectKey}' not found.`);
2647
- await projectsApi.projectsDelete({ id: project.id });
2648
- OutputFormatter4.success(new SuccessOutput3("ProjectDelete", {
2649
- ProjectKey: options.projectKey,
2650
- Id: project.id,
2651
- Result: "Deleted"
2652
- }));
2653
- } catch (error) {
2654
- const { message, details } = await extractErrorDetails(error);
2628
+ await projectsApi.projectsDelete({ id: proj.id });
2629
+ return proj;
2630
+ })());
2631
+ if (error) {
2632
+ const { message, details } = await extractErrorDetails3(error, {
2633
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2634
+ });
2655
2635
  OutputFormatter4.error({
2656
2636
  Result: "Failure",
2657
2637
  Message: message,
2658
2638
  Instructions: details
2659
2639
  });
2660
2640
  processContext3.exit(1);
2641
+ return;
2661
2642
  }
2643
+ OutputFormatter4.success(new SuccessOutput3("ProjectDelete", {
2644
+ ProjectKey: options.projectKey,
2645
+ Id: project.id,
2646
+ Result: "Deleted"
2647
+ }));
2662
2648
  });
2663
- projectCmd.command("set-default-folder").description("Set the default Orchestrator folder for a project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'orch folders list')").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2649
+ projectCmd.command("set-default-folder").description("Set the default Orchestrator folder for a project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'uip or folders list')").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2664
2650
  const ctx = await resolveCommandContext(options);
2665
2651
  if (!ctx)
2666
2652
  return;
2667
2653
  const { tmBaseUrl, accessToken, projectId } = ctx;
2668
- try {
2654
+ const [error] = await catchError4((async () => {
2669
2655
  const res = await fetch(`${tmBaseUrl}/api/v2/${projectId}/projectsettings/folder`, {
2670
2656
  method: "PUT",
2671
2657
  headers: {
@@ -2680,27 +2666,31 @@ var registerProjectCommand = (program) => {
2680
2666
  const body = await res.text().catch(() => "");
2681
2667
  throw new Error(`HTTP ${res.status} ${res.statusText}${body ? `: ${body}` : ""}`);
2682
2668
  }
2683
- OutputFormatter4.success(new SuccessOutput3("ProjectSetDefaultFolder", {
2684
- ProjectKey: options.projectKey,
2685
- FolderKey: options.folderKey,
2686
- Result: "Updated"
2687
- }));
2688
- } catch (error) {
2689
- const { message, details } = await extractErrorDetails(error);
2669
+ })());
2670
+ if (error) {
2671
+ const { message, details } = await extractErrorDetails3(error, {
2672
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2673
+ });
2690
2674
  OutputFormatter4.error({
2691
2675
  Result: "Failure",
2692
2676
  Message: message,
2693
2677
  Instructions: details
2694
2678
  });
2695
2679
  processContext3.exit(1);
2680
+ return;
2696
2681
  }
2682
+ OutputFormatter4.success(new SuccessOutput3("ProjectSetDefaultFolder", {
2683
+ ProjectKey: options.projectKey,
2684
+ FolderKey: options.folderKey,
2685
+ Result: "Updated"
2686
+ }));
2697
2687
  });
2698
2688
  projectCmd.command("clear-default-folder").description("Clear the default Orchestrator folder from a project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext3, async (options) => {
2699
2689
  const ctx = await resolveCommandContext(options);
2700
2690
  if (!ctx)
2701
2691
  return;
2702
2692
  const { tmBaseUrl, accessToken, projectId } = ctx;
2703
- try {
2693
+ const [error] = await catchError4((async () => {
2704
2694
  const res = await fetch(`${tmBaseUrl}/api/v2/${projectId}/projectsettings/folder`, {
2705
2695
  method: "PUT",
2706
2696
  headers: {
@@ -2713,24 +2703,30 @@ var registerProjectCommand = (program) => {
2713
2703
  const body = await res.text().catch(() => "");
2714
2704
  throw new Error(`HTTP ${res.status} ${res.statusText}${body ? `: ${body}` : ""}`);
2715
2705
  }
2716
- OutputFormatter4.success(new SuccessOutput3("ProjectClearDefaultFolder", {
2717
- ProjectKey: options.projectKey,
2718
- Result: "Cleared"
2719
- }));
2720
- } catch (error) {
2721
- const { message, details } = await extractErrorDetails(error);
2706
+ })());
2707
+ if (error) {
2708
+ const { message, details } = await extractErrorDetails3(error, {
2709
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2710
+ });
2722
2711
  OutputFormatter4.error({
2723
2712
  Result: "Failure",
2724
2713
  Message: message,
2725
2714
  Instructions: details
2726
2715
  });
2727
2716
  processContext3.exit(1);
2717
+ return;
2728
2718
  }
2719
+ OutputFormatter4.success(new SuccessOutput3("ProjectClearDefaultFolder", {
2720
+ ProjectKey: options.projectKey,
2721
+ Result: "Cleared"
2722
+ }));
2729
2723
  });
2730
2724
  };
2731
2725
 
2732
2726
  // src/commands/report.ts
2733
2727
  import {
2728
+ catchError as catchError5,
2729
+ extractErrorDetails as extractErrorDetails4,
2734
2730
  logger as logger4,
2735
2731
  OutputFormatter as OutputFormatter5,
2736
2732
  processContext as processContext4,
@@ -2813,7 +2809,7 @@ var registerReportCommand = (program) => {
2813
2809
  if (!ctx)
2814
2810
  return;
2815
2811
  const { tmConfig, projectId } = ctx;
2816
- try {
2812
+ const [error, data] = await catchError5((async () => {
2817
2813
  const executionId = options.executionId;
2818
2814
  logger4.info(`Fetching execution stats for ${executionId}`);
2819
2815
  const executionsApi = new TestExecutionsApi(tmConfig);
@@ -2833,18 +2829,21 @@ var registerReportCommand = (program) => {
2833
2829
  const failedLogs = await fetchAllFailedLogs(testCaseLogsApi, projectId, executionId);
2834
2830
  const failedTests = await Promise.all(failedLogs.map(async (log) => {
2835
2831
  const name = log.testCase?.name ?? log.automationTestCaseName ?? log.id ?? "unknown";
2836
- let error = log.info ?? "";
2837
- if (!error && log.id) {
2838
- try {
2839
- const assertions = await testCaseLogArtifactsApi.testCaseLogArtifactsGetAssertions({ id: log.id, projectId });
2832
+ let assertionError = log.info ?? "";
2833
+ if (!assertionError && log.id) {
2834
+ const [assertErr, assertions] = await catchError5(testCaseLogArtifactsApi.testCaseLogArtifactsGetAssertions({ id: log.id, projectId }));
2835
+ if (!assertErr) {
2840
2836
  const failedMessages = assertions.filter((a) => a.succeeded === false).map((a) => a.message).filter(Boolean).join("; ");
2841
2837
  if (failedMessages)
2842
- error = failedMessages;
2843
- } catch {}
2838
+ assertionError = failedMessages;
2839
+ }
2844
2840
  }
2845
- return { TestCaseName: name, Error: error };
2841
+ return {
2842
+ TestCaseName: name,
2843
+ Error: assertionError
2844
+ };
2846
2845
  }));
2847
- const data = {
2846
+ return {
2848
2847
  ExecutionId: executionId,
2849
2848
  TestSetName: stats.name ?? "",
2850
2849
  TotalTests: total,
@@ -2857,21 +2856,24 @@ var registerReportCommand = (program) => {
2857
2856
  Duration: msToDuration(stats.duration ?? 0),
2858
2857
  FailedTests: failedTests
2859
2858
  };
2860
- if (options.query) {
2861
- const filtered = applyQuery(data, options.query);
2862
- process.stdout.write(`${JSON.stringify(filtered)}
2863
- `);
2864
- } else {
2865
- OutputFormatter5.success(new SuccessOutput4("ReportGet", data));
2866
- }
2867
- } catch (error) {
2868
- const { message, details } = await extractErrorDetails(error);
2859
+ })());
2860
+ if (error) {
2861
+ const { message, details } = await extractErrorDetails4(error, {
2862
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
2863
+ });
2869
2864
  OutputFormatter5.error({
2870
2865
  Result: "Failure",
2871
2866
  Message: message,
2872
2867
  Instructions: details
2873
2868
  });
2874
2869
  processContext4.exit(1);
2870
+ return;
2871
+ }
2872
+ if (options.query) {
2873
+ const filtered = applyQuery(data, options.query);
2874
+ OutputFormatter5.success(new SuccessOutput4("ReportGet", filtered));
2875
+ } else {
2876
+ OutputFormatter5.success(new SuccessOutput4("ReportGet", data));
2875
2877
  }
2876
2878
  });
2877
2879
  };
@@ -2900,6 +2902,8 @@ async function fetchAllFailedLogs(api, projectId, testExecutionId) {
2900
2902
 
2901
2903
  // src/commands/result.ts
2902
2904
  import {
2905
+ catchError as catchError6,
2906
+ extractErrorDetails as extractErrorDetails5,
2903
2907
  logger as logger5,
2904
2908
  OutputFormatter as OutputFormatter6,
2905
2909
  processContext as processContext5,
@@ -3022,7 +3026,7 @@ var registerResultCommand = (program) => {
3022
3026
  baseUrl,
3023
3027
  tenantName
3024
3028
  } = ctx;
3025
- try {
3029
+ const [error] = await catchError6((async () => {
3026
3030
  const orgSlug = organizationName ?? organizationId;
3027
3031
  const tmWebUrl = `${baseUrl}/${orgSlug}/${tenantName}/testmanager_`;
3028
3032
  const executionId = options.executionId;
@@ -3050,13 +3054,16 @@ var registerResultCommand = (program) => {
3050
3054
  durationMs = log.executionEnd.getTime() - log.executionStart.getTime();
3051
3055
  }
3052
3056
  let assertions = [];
3053
- try {
3054
- const raw = await artifactsApi.testCaseLogArtifactsGetAssertions({ id: logId, projectId });
3057
+ const [assertErr, raw] = await catchError6(artifactsApi.testCaseLogArtifactsGetAssertions({
3058
+ id: logId,
3059
+ projectId
3060
+ }));
3061
+ if (!assertErr) {
3055
3062
  assertions = raw.map((a) => ({
3056
3063
  Message: a.message ?? "",
3057
3064
  Succeeded: a.succeeded ?? true
3058
3065
  }));
3059
- } catch {}
3066
+ }
3060
3067
  return {
3061
3068
  Id: logId,
3062
3069
  TestCaseId: testCaseId,
@@ -3110,14 +3117,18 @@ var registerResultCommand = (program) => {
3110
3117
  Failed: failuresCount,
3111
3118
  Cancelled: canceledCount
3112
3119
  }));
3113
- } catch (error) {
3114
- const { message, details } = await extractErrorDetails(error);
3120
+ })());
3121
+ if (error) {
3122
+ const { message, details } = await extractErrorDetails5(error, {
3123
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
3124
+ });
3115
3125
  OutputFormatter6.error({
3116
3126
  Result: "Failure",
3117
3127
  Message: message,
3118
3128
  Instructions: details
3119
3129
  });
3120
3130
  processContext5.exit(1);
3131
+ return;
3121
3132
  }
3122
3133
  });
3123
3134
  };
@@ -3145,7 +3156,7 @@ async function fetchAllTestCaseLogs2(api, projectId, testExecutionId) {
3145
3156
  async function fetchTestSetPackages(tmBaseUrl, accessToken, projectId, testSetId) {
3146
3157
  if (!testSetId)
3147
3158
  return [];
3148
- try {
3159
+ const [err, result] = await catchError6((async () => {
3149
3160
  const url = `${tmBaseUrl}/api/v2/${encodeURIComponent(projectId)}/testsets/${encodeURIComponent(testSetId)}/packages`;
3150
3161
  const response = await fetch(url, {
3151
3162
  headers: { Authorization: `Bearer ${accessToken}` }
@@ -3158,13 +3169,20 @@ async function fetchTestSetPackages(tmBaseUrl, accessToken, projectId, testSetId
3158
3169
  Name: p.packageName ?? p.name ?? "",
3159
3170
  Version: p.version ?? ""
3160
3171
  }));
3161
- } catch {
3172
+ })());
3173
+ if (err)
3162
3174
  return [];
3163
- }
3175
+ return result;
3164
3176
  }
3165
3177
 
3166
3178
  // src/commands/testcase.ts
3167
- import { OutputFormatter as OutputFormatter7, processContext as processContext6, SuccessOutput as SuccessOutput6 } from "@uipath/common";
3179
+ import {
3180
+ catchError as catchError7,
3181
+ extractErrorDetails as extractErrorDetails6,
3182
+ OutputFormatter as OutputFormatter7,
3183
+ processContext as processContext6,
3184
+ SuccessOutput as SuccessOutput6
3185
+ } from "@uipath/common";
3168
3186
 
3169
3187
  // ../orchestrator-sdk/generated/src/runtime.ts
3170
3188
  var BASE_PATH2 = "https://alpha.uipath.com/uipattycyrhx/abizon_1/orchestrator_".replace(/\/+$/, "");
@@ -3553,6 +3571,20 @@ function EntitySummaryDtoFromJSONTyped(json, ignoreDiscriminator) {
3553
3571
  };
3554
3572
  }
3555
3573
 
3574
+ // ../orchestrator-sdk/generated/src/models/UpdatePolicyDto.ts
3575
+ function UpdatePolicyDtoFromJSON(json) {
3576
+ return UpdatePolicyDtoFromJSONTyped(json, false);
3577
+ }
3578
+ function UpdatePolicyDtoFromJSONTyped(json, ignoreDiscriminator) {
3579
+ if (json == null) {
3580
+ return json;
3581
+ }
3582
+ return {
3583
+ type: json["Type"] == null ? undefined : json["Type"],
3584
+ specificVersion: json["SpecificVersion"] == null ? undefined : json["SpecificVersion"]
3585
+ };
3586
+ }
3587
+
3556
3588
  // ../orchestrator-sdk/generated/src/models/ExtendedFolderDto.ts
3557
3589
  function ExtendedFolderDtoFromJSON(json) {
3558
3590
  return ExtendedFolderDtoFromJSONTyped(json, false);
@@ -3580,145 +3612,102 @@ function ExtendedFolderDtoFromJSONTyped(json, ignoreDiscriminator) {
3580
3612
  };
3581
3613
  }
3582
3614
 
3583
- // ../orchestrator-sdk/generated/src/models/Folder.ts
3584
- function FolderFromJSON(json) {
3585
- return FolderFromJSONTyped(json, false);
3615
+ // ../orchestrator-sdk/generated/src/models/MachineVpnSettingsDto.ts
3616
+ function MachineVpnSettingsDtoFromJSON(json) {
3617
+ return MachineVpnSettingsDtoFromJSONTyped(json, false);
3586
3618
  }
3587
- function FolderFromJSONTyped(json, ignoreDiscriminator) {
3619
+ function MachineVpnSettingsDtoFromJSONTyped(json, ignoreDiscriminator) {
3588
3620
  if (json == null) {
3589
3621
  return json;
3590
3622
  }
3591
3623
  return {
3592
- id: json["id"] == null ? undefined : json["id"],
3593
- key: json["key"] == null ? undefined : json["key"],
3594
- path: json["path"] == null ? undefined : json["path"],
3595
- timestamp: json["timestamp"] == null ? undefined : new Date(json["timestamp"]),
3596
- type: json["type"] == null ? undefined : json["type"],
3597
- fullyQualifiedName: json["fullyQualifiedName"] == null ? undefined : json["fullyQualifiedName"],
3598
- displayName: json["displayName"] == null ? undefined : json["displayName"],
3599
- description: json["description"] == null ? undefined : json["description"],
3600
- isDeleted: json["isDeleted"] == null ? undefined : json["isDeleted"]
3624
+ cidr: json["cidr"] == null ? undefined : json["cidr"]
3601
3625
  };
3602
3626
  }
3603
3627
 
3604
- // ../orchestrator-sdk/generated/src/models/FolderAssignDomainUserRequest.ts
3605
- function FolderAssignDomainUserRequestToJSON(json) {
3606
- return FolderAssignDomainUserRequestToJSONTyped(json, false);
3628
+ // ../orchestrator-sdk/generated/src/models/MaintenanceWindowDto.ts
3629
+ function MaintenanceWindowDtoFromJSON(json) {
3630
+ return MaintenanceWindowDtoFromJSONTyped(json, false);
3607
3631
  }
3608
- function FolderAssignDomainUserRequestToJSONTyped(value, ignoreDiscriminator = false) {
3609
- if (value == null) {
3610
- return value;
3632
+ function MaintenanceWindowDtoFromJSONTyped(json, ignoreDiscriminator) {
3633
+ if (json == null) {
3634
+ return json;
3611
3635
  }
3612
3636
  return {
3613
- assignment: DomainUserAssignmentDtoToJSON(value["assignment"])
3637
+ enabled: json["enabled"] == null ? undefined : json["enabled"],
3638
+ jobStopStrategy: json["jobStopStrategy"] == null ? undefined : json["jobStopStrategy"],
3639
+ cronExpression: json["cronExpression"] == null ? undefined : json["cronExpression"],
3640
+ timezoneId: json["timezoneId"] == null ? undefined : json["timezoneId"],
3641
+ duration: json["duration"] == null ? undefined : json["duration"],
3642
+ nextExecutionTime: json["nextExecutionTime"] == null ? undefined : new Date(json["nextExecutionTime"])
3614
3643
  };
3615
3644
  }
3616
3645
 
3617
- // ../orchestrator-sdk/generated/src/models/MachineAssignmentsDto.ts
3618
- function MachineAssignmentsDtoToJSON(json) {
3619
- return MachineAssignmentsDtoToJSONTyped(json, false);
3646
+ // ../orchestrator-sdk/generated/src/models/UpdateInfoDto.ts
3647
+ function UpdateInfoDtoFromJSON(json) {
3648
+ return UpdateInfoDtoFromJSONTyped(json, false);
3620
3649
  }
3621
- function MachineAssignmentsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3622
- if (value == null) {
3623
- return value;
3650
+ function UpdateInfoDtoFromJSONTyped(json, ignoreDiscriminator) {
3651
+ if (json == null) {
3652
+ return json;
3624
3653
  }
3625
3654
  return {
3626
- MachineIds: value["machineIds"],
3627
- FolderIds: value["folderIds"]
3655
+ updateStatus: json["updateStatus"] == null ? undefined : json["updateStatus"],
3656
+ reason: json["reason"] == null ? undefined : json["reason"],
3657
+ targetUpdateVersion: json["targetUpdateVersion"] == null ? undefined : json["targetUpdateVersion"],
3658
+ isCommunity: json["isCommunity"] == null ? undefined : json["isCommunity"],
3659
+ statusInfo: json["statusInfo"] == null ? undefined : json["statusInfo"]
3628
3660
  };
3629
3661
  }
3630
3662
 
3631
- // ../orchestrator-sdk/generated/src/models/FolderAssignMachinesRequest.ts
3632
- function FolderAssignMachinesRequestToJSON(json) {
3633
- return FolderAssignMachinesRequestToJSONTyped(json, false);
3663
+ // ../orchestrator-sdk/generated/src/models/MachinesRobotVersionDto.ts
3664
+ function MachinesRobotVersionDtoFromJSON(json) {
3665
+ return MachinesRobotVersionDtoFromJSONTyped(json, false);
3634
3666
  }
3635
- function FolderAssignMachinesRequestToJSONTyped(value, ignoreDiscriminator = false) {
3636
- if (value == null) {
3637
- return value;
3667
+ function MachinesRobotVersionDtoFromJSONTyped(json, ignoreDiscriminator) {
3668
+ if (json == null) {
3669
+ return json;
3638
3670
  }
3639
3671
  return {
3640
- assignments: MachineAssignmentsDtoToJSON(value["assignments"])
3672
+ count: json["Count"] == null ? undefined : json["Count"],
3673
+ version: json["Version"] == null ? undefined : json["Version"],
3674
+ machineId: json["MachineId"] == null ? undefined : json["MachineId"]
3641
3675
  };
3642
3676
  }
3643
3677
 
3644
- // ../orchestrator-sdk/generated/src/models/UserAssignmentsDto.ts
3645
- function UserAssignmentsDtoToJSON(json) {
3646
- return UserAssignmentsDtoToJSONTyped(json, false);
3678
+ // ../orchestrator-sdk/generated/src/models/RobotUserDto.ts
3679
+ function RobotUserDtoFromJSON(json) {
3680
+ return RobotUserDtoFromJSONTyped(json, false);
3647
3681
  }
3648
- function UserAssignmentsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3649
- if (value == null) {
3650
- return value;
3682
+ function RobotUserDtoFromJSONTyped(json, ignoreDiscriminator) {
3683
+ if (json == null) {
3684
+ return json;
3651
3685
  }
3652
3686
  return {
3653
- UserIds: value["userIds"],
3654
- RolesPerFolder: value["rolesPerFolder"] == null ? undefined : value["rolesPerFolder"].map(FolderRolesDtoToJSON)
3655
- };
3656
- }
3657
-
3658
- // ../orchestrator-sdk/generated/src/models/FolderAssignUsersRequest.ts
3659
- function FolderAssignUsersRequestToJSON(json) {
3660
- return FolderAssignUsersRequestToJSONTyped(json, false);
3661
- }
3662
- function FolderAssignUsersRequestToJSONTyped(value, ignoreDiscriminator = false) {
3663
- if (value == null) {
3664
- return value;
3665
- }
3666
- return {
3667
- assignments: UserAssignmentsDtoToJSON(value["assignments"])
3668
- };
3669
- }
3670
-
3671
- // ../orchestrator-sdk/generated/src/models/SimpleUserEntityDto.ts
3672
- function SimpleUserEntityDtoFromJSON(json) {
3673
- return SimpleUserEntityDtoFromJSONTyped(json, false);
3674
- }
3675
- function SimpleUserEntityDtoFromJSONTyped(json, ignoreDiscriminator) {
3676
- if (json == null) {
3677
- return json;
3678
- }
3679
- return {
3680
- key: json["Key"] == null ? undefined : json["Key"],
3681
3687
  userName: json["UserName"] == null ? undefined : json["UserName"],
3682
- isInherited: json["IsInherited"] == null ? undefined : json["IsInherited"],
3683
- assignedToFolderIds: json["AssignedToFolderIds"] == null ? undefined : json["AssignedToFolderIds"],
3684
- mayHaveAttended: json["MayHaveAttended"] == null ? undefined : json["MayHaveAttended"],
3685
- mayHaveUnattended: json["MayHaveUnattended"] == null ? undefined : json["MayHaveUnattended"],
3686
- type: json["Type"] == null ? undefined : json["Type"],
3687
- source: json["Source"] == null ? undefined : json["Source"],
3688
- isActive: json["IsActive"] == null ? undefined : json["IsActive"],
3689
- id: json["Id"] == null ? undefined : json["Id"]
3688
+ robotId: json["RobotId"],
3689
+ hasTriggers: json["HasTriggers"] == null ? undefined : json["HasTriggers"]
3690
3690
  };
3691
3691
  }
3692
3692
 
3693
- // ../orchestrator-sdk/generated/src/models/RoleUsersDto.ts
3694
- function RoleUsersDtoFromJSON(json) {
3695
- return RoleUsersDtoFromJSONTyped(json, false);
3693
+ // ../orchestrator-sdk/generated/src/models/UserRoleDto.ts
3694
+ function UserRoleDtoFromJSON(json) {
3695
+ return UserRoleDtoFromJSONTyped(json, false);
3696
3696
  }
3697
- function RoleUsersDtoFromJSONTyped(json, ignoreDiscriminator) {
3697
+ function UserRoleDtoFromJSONTyped(json, ignoreDiscriminator) {
3698
3698
  if (json == null) {
3699
3699
  return json;
3700
3700
  }
3701
3701
  return {
3702
- name: json["Name"] == null ? undefined : json["Name"],
3703
- users: json["Users"] == null ? undefined : json["Users"].map(SimpleUserEntityDtoFromJSON),
3702
+ userId: json["UserId"] == null ? undefined : json["UserId"],
3703
+ roleId: json["RoleId"] == null ? undefined : json["RoleId"],
3704
+ userName: json["UserName"] == null ? undefined : json["UserName"],
3705
+ roleName: json["RoleName"] == null ? undefined : json["RoleName"],
3706
+ roleType: json["RoleType"] == null ? undefined : json["RoleType"],
3704
3707
  id: json["Id"] == null ? undefined : json["Id"]
3705
3708
  };
3706
3709
  }
3707
3710
 
3708
- // ../orchestrator-sdk/generated/src/models/FolderAssignmentsDto.ts
3709
- function FolderAssignmentsDtoFromJSON(json) {
3710
- return FolderAssignmentsDtoFromJSONTyped(json, false);
3711
- }
3712
- function FolderAssignmentsDtoFromJSONTyped(json, ignoreDiscriminator) {
3713
- if (json == null) {
3714
- return json;
3715
- }
3716
- return {
3717
- folder: json["Folder"] == null ? undefined : SimpleFolderDtoFromJSON(json["Folder"]),
3718
- roles: json["Roles"] == null ? undefined : json["Roles"].map(RoleUsersDtoFromJSON)
3719
- };
3720
- }
3721
-
3722
3711
  // ../orchestrator-sdk/generated/src/models/FolderDto.ts
3723
3712
  function FolderDtoFromJSON(json) {
3724
3713
  return FolderDtoFromJSONTyped(json, false);
@@ -3764,155 +3753,202 @@ function FolderDtoToJSONTyped(value, ignoreDiscriminator = false) {
3764
3753
  };
3765
3754
  }
3766
3755
 
3767
- // ../orchestrator-sdk/generated/src/models/FolderIdentifier.ts
3768
- function FolderIdentifierFromJSON(json) {
3769
- return FolderIdentifierFromJSONTyped(json, false);
3756
+ // ../orchestrator-sdk/generated/src/models/Folder.ts
3757
+ function FolderFromJSON(json) {
3758
+ return FolderFromJSONTyped(json, false);
3770
3759
  }
3771
- function FolderIdentifierFromJSONTyped(json, ignoreDiscriminator) {
3760
+ function FolderFromJSONTyped(json, ignoreDiscriminator) {
3772
3761
  if (json == null) {
3773
3762
  return json;
3774
3763
  }
3775
3764
  return {
3776
3765
  id: json["id"] == null ? undefined : json["id"],
3777
3766
  key: json["key"] == null ? undefined : json["key"],
3778
- path: json["path"] == null ? undefined : json["path"]
3767
+ path: json["path"] == null ? undefined : json["path"],
3768
+ timestamp: json["timestamp"] == null ? undefined : new Date(json["timestamp"]),
3769
+ type: json["type"] == null ? undefined : json["type"],
3770
+ fullyQualifiedName: json["fullyQualifiedName"] == null ? undefined : json["fullyQualifiedName"],
3771
+ displayName: json["displayName"] == null ? undefined : json["displayName"],
3772
+ description: json["description"] == null ? undefined : json["description"],
3773
+ isDeleted: json["isDeleted"] == null ? undefined : json["isDeleted"]
3779
3774
  };
3780
3775
  }
3781
3776
 
3782
- // ../orchestrator-sdk/generated/src/models/FolderMachineInheritDto.ts
3783
- function FolderMachineInheritDtoToJSON(json) {
3784
- return FolderMachineInheritDtoToJSONTyped(json, false);
3777
+ // ../orchestrator-sdk/generated/src/models/FolderAssignDomainUserRequest.ts
3778
+ function FolderAssignDomainUserRequestToJSON(json) {
3779
+ return FolderAssignDomainUserRequestToJSONTyped(json, false);
3785
3780
  }
3786
- function FolderMachineInheritDtoToJSONTyped(value, ignoreDiscriminator = false) {
3781
+ function FolderAssignDomainUserRequestToJSONTyped(value, ignoreDiscriminator = false) {
3787
3782
  if (value == null) {
3788
3783
  return value;
3789
3784
  }
3790
3785
  return {
3791
- MachineId: value["machineId"],
3792
- FolderId: value["folderId"],
3793
- InheritEnabled: value["inheritEnabled"]
3786
+ assignment: DomainUserAssignmentDtoToJSON(value["assignment"])
3794
3787
  };
3795
3788
  }
3796
3789
 
3797
- // ../orchestrator-sdk/generated/src/models/FolderMachineRobotsDto.ts
3798
- function FolderMachineRobotsDtoToJSON(json) {
3799
- return FolderMachineRobotsDtoToJSONTyped(json, false);
3790
+ // ../orchestrator-sdk/generated/src/models/MachineAssignmentsDto.ts
3791
+ function MachineAssignmentsDtoToJSON(json) {
3792
+ return MachineAssignmentsDtoToJSONTyped(json, false);
3800
3793
  }
3801
- function FolderMachineRobotsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3794
+ function MachineAssignmentsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3802
3795
  if (value == null) {
3803
3796
  return value;
3804
3797
  }
3805
3798
  return {
3806
- MachineId: value["machineId"],
3807
- FolderId: value["folderId"],
3808
- AddedRobotIds: value["addedRobotIds"],
3809
- RemovedRobotIds: value["removedRobotIds"]
3799
+ MachineIds: value["machineIds"],
3800
+ FolderIds: value["folderIds"]
3810
3801
  };
3811
3802
  }
3812
3803
 
3813
- // ../orchestrator-sdk/generated/src/models/FolderUpdateNameDescriptionRequest.ts
3814
- function FolderUpdateNameDescriptionRequestToJSON(json) {
3815
- return FolderUpdateNameDescriptionRequestToJSONTyped(json, false);
3804
+ // ../orchestrator-sdk/generated/src/models/FolderAssignMachinesRequest.ts
3805
+ function FolderAssignMachinesRequestToJSON(json) {
3806
+ return FolderAssignMachinesRequestToJSONTyped(json, false);
3816
3807
  }
3817
- function FolderUpdateNameDescriptionRequestToJSONTyped(value, ignoreDiscriminator = false) {
3808
+ function FolderAssignMachinesRequestToJSONTyped(value, ignoreDiscriminator = false) {
3818
3809
  if (value == null) {
3819
3810
  return value;
3820
3811
  }
3821
3812
  return {
3822
- name: value["name"],
3823
- description: value["description"]
3813
+ assignments: MachineAssignmentsDtoToJSON(value["assignments"])
3824
3814
  };
3825
3815
  }
3826
3816
 
3827
- // ../orchestrator-sdk/generated/src/models/MachineVpnSettingsDto.ts
3828
- function MachineVpnSettingsDtoFromJSON(json) {
3829
- return MachineVpnSettingsDtoFromJSONTyped(json, false);
3817
+ // ../orchestrator-sdk/generated/src/models/UserAssignmentsDto.ts
3818
+ function UserAssignmentsDtoToJSON(json) {
3819
+ return UserAssignmentsDtoToJSONTyped(json, false);
3830
3820
  }
3831
- function MachineVpnSettingsDtoFromJSONTyped(json, ignoreDiscriminator) {
3832
- if (json == null) {
3833
- return json;
3821
+ function UserAssignmentsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3822
+ if (value == null) {
3823
+ return value;
3834
3824
  }
3835
3825
  return {
3836
- cidr: json["cidr"] == null ? undefined : json["cidr"]
3826
+ UserIds: value["userIds"],
3827
+ RolesPerFolder: value["rolesPerFolder"] == null ? undefined : value["rolesPerFolder"].map(FolderRolesDtoToJSON)
3837
3828
  };
3838
3829
  }
3839
3830
 
3840
- // ../orchestrator-sdk/generated/src/models/MaintenanceWindowDto.ts
3841
- function MaintenanceWindowDtoFromJSON(json) {
3842
- return MaintenanceWindowDtoFromJSONTyped(json, false);
3831
+ // ../orchestrator-sdk/generated/src/models/FolderAssignUsersRequest.ts
3832
+ function FolderAssignUsersRequestToJSON(json) {
3833
+ return FolderAssignUsersRequestToJSONTyped(json, false);
3843
3834
  }
3844
- function MaintenanceWindowDtoFromJSONTyped(json, ignoreDiscriminator) {
3845
- if (json == null) {
3846
- return json;
3835
+ function FolderAssignUsersRequestToJSONTyped(value, ignoreDiscriminator = false) {
3836
+ if (value == null) {
3837
+ return value;
3847
3838
  }
3848
3839
  return {
3849
- enabled: json["enabled"] == null ? undefined : json["enabled"],
3850
- jobStopStrategy: json["jobStopStrategy"] == null ? undefined : json["jobStopStrategy"],
3851
- cronExpression: json["cronExpression"] == null ? undefined : json["cronExpression"],
3852
- timezoneId: json["timezoneId"] == null ? undefined : json["timezoneId"],
3853
- duration: json["duration"] == null ? undefined : json["duration"],
3854
- nextExecutionTime: json["nextExecutionTime"] == null ? undefined : new Date(json["nextExecutionTime"])
3840
+ assignments: UserAssignmentsDtoToJSON(value["assignments"])
3855
3841
  };
3856
3842
  }
3857
3843
 
3858
- // ../orchestrator-sdk/generated/src/models/MachinesRobotVersionDto.ts
3859
- function MachinesRobotVersionDtoFromJSON(json) {
3860
- return MachinesRobotVersionDtoFromJSONTyped(json, false);
3844
+ // ../orchestrator-sdk/generated/src/models/SimpleUserEntityDto.ts
3845
+ function SimpleUserEntityDtoFromJSON(json) {
3846
+ return SimpleUserEntityDtoFromJSONTyped(json, false);
3861
3847
  }
3862
- function MachinesRobotVersionDtoFromJSONTyped(json, ignoreDiscriminator) {
3848
+ function SimpleUserEntityDtoFromJSONTyped(json, ignoreDiscriminator) {
3863
3849
  if (json == null) {
3864
3850
  return json;
3865
3851
  }
3866
3852
  return {
3867
- count: json["Count"] == null ? undefined : json["Count"],
3868
- version: json["Version"] == null ? undefined : json["Version"],
3869
- machineId: json["MachineId"] == null ? undefined : json["MachineId"]
3853
+ key: json["Key"] == null ? undefined : json["Key"],
3854
+ userName: json["UserName"] == null ? undefined : json["UserName"],
3855
+ isInherited: json["IsInherited"] == null ? undefined : json["IsInherited"],
3856
+ assignedToFolderIds: json["AssignedToFolderIds"] == null ? undefined : json["AssignedToFolderIds"],
3857
+ mayHaveAttended: json["MayHaveAttended"] == null ? undefined : json["MayHaveAttended"],
3858
+ mayHaveUnattended: json["MayHaveUnattended"] == null ? undefined : json["MayHaveUnattended"],
3859
+ type: json["Type"] == null ? undefined : json["Type"],
3860
+ source: json["Source"] == null ? undefined : json["Source"],
3861
+ isActive: json["IsActive"] == null ? undefined : json["IsActive"],
3862
+ id: json["Id"] == null ? undefined : json["Id"]
3870
3863
  };
3871
3864
  }
3872
3865
 
3873
- // ../orchestrator-sdk/generated/src/models/UpdatePolicyDto.ts
3874
- function UpdatePolicyDtoFromJSON(json) {
3875
- return UpdatePolicyDtoFromJSONTyped(json, false);
3866
+ // ../orchestrator-sdk/generated/src/models/RoleUsersDto.ts
3867
+ function RoleUsersDtoFromJSON(json) {
3868
+ return RoleUsersDtoFromJSONTyped(json, false);
3876
3869
  }
3877
- function UpdatePolicyDtoFromJSONTyped(json, ignoreDiscriminator) {
3870
+ function RoleUsersDtoFromJSONTyped(json, ignoreDiscriminator) {
3878
3871
  if (json == null) {
3879
3872
  return json;
3880
3873
  }
3881
3874
  return {
3882
- type: json["Type"] == null ? undefined : json["Type"],
3883
- specificVersion: json["SpecificVersion"] == null ? undefined : json["SpecificVersion"]
3875
+ name: json["Name"] == null ? undefined : json["Name"],
3876
+ users: json["Users"] == null ? undefined : json["Users"].map(SimpleUserEntityDtoFromJSON),
3877
+ id: json["Id"] == null ? undefined : json["Id"]
3884
3878
  };
3885
3879
  }
3886
3880
 
3887
- // ../orchestrator-sdk/generated/src/models/RobotUserDto.ts
3888
- function RobotUserDtoFromJSON(json) {
3889
- return RobotUserDtoFromJSONTyped(json, false);
3881
+ // ../orchestrator-sdk/generated/src/models/FolderAssignmentsDto.ts
3882
+ function FolderAssignmentsDtoFromJSON(json) {
3883
+ return FolderAssignmentsDtoFromJSONTyped(json, false);
3890
3884
  }
3891
- function RobotUserDtoFromJSONTyped(json, ignoreDiscriminator) {
3885
+ function FolderAssignmentsDtoFromJSONTyped(json, ignoreDiscriminator) {
3892
3886
  if (json == null) {
3893
3887
  return json;
3894
3888
  }
3895
3889
  return {
3896
- userName: json["UserName"] == null ? undefined : json["UserName"],
3897
- robotId: json["RobotId"],
3898
- hasTriggers: json["HasTriggers"] == null ? undefined : json["HasTriggers"]
3890
+ folder: json["Folder"] == null ? undefined : SimpleFolderDtoFromJSON(json["Folder"]),
3891
+ roles: json["Roles"] == null ? undefined : json["Roles"].map(RoleUsersDtoFromJSON)
3899
3892
  };
3900
3893
  }
3901
3894
 
3902
- // ../orchestrator-sdk/generated/src/models/UpdateInfoDto.ts
3903
- function UpdateInfoDtoFromJSON(json) {
3904
- return UpdateInfoDtoFromJSONTyped(json, false);
3895
+ // ../orchestrator-sdk/generated/src/models/FolderIdentifier.ts
3896
+ function FolderIdentifierFromJSON(json) {
3897
+ return FolderIdentifierFromJSONTyped(json, false);
3905
3898
  }
3906
- function UpdateInfoDtoFromJSONTyped(json, ignoreDiscriminator) {
3899
+ function FolderIdentifierFromJSONTyped(json, ignoreDiscriminator) {
3907
3900
  if (json == null) {
3908
3901
  return json;
3909
3902
  }
3910
3903
  return {
3911
- updateStatus: json["updateStatus"] == null ? undefined : json["updateStatus"],
3912
- reason: json["reason"] == null ? undefined : json["reason"],
3913
- targetUpdateVersion: json["targetUpdateVersion"] == null ? undefined : json["targetUpdateVersion"],
3914
- isCommunity: json["isCommunity"] == null ? undefined : json["isCommunity"],
3915
- statusInfo: json["statusInfo"] == null ? undefined : json["statusInfo"]
3904
+ id: json["id"] == null ? undefined : json["id"],
3905
+ key: json["key"] == null ? undefined : json["key"],
3906
+ path: json["path"] == null ? undefined : json["path"]
3907
+ };
3908
+ }
3909
+
3910
+ // ../orchestrator-sdk/generated/src/models/FolderMachineInheritDto.ts
3911
+ function FolderMachineInheritDtoToJSON(json) {
3912
+ return FolderMachineInheritDtoToJSONTyped(json, false);
3913
+ }
3914
+ function FolderMachineInheritDtoToJSONTyped(value, ignoreDiscriminator = false) {
3915
+ if (value == null) {
3916
+ return value;
3917
+ }
3918
+ return {
3919
+ MachineId: value["machineId"],
3920
+ FolderId: value["folderId"],
3921
+ InheritEnabled: value["inheritEnabled"]
3922
+ };
3923
+ }
3924
+
3925
+ // ../orchestrator-sdk/generated/src/models/FolderMachineRobotsDto.ts
3926
+ function FolderMachineRobotsDtoToJSON(json) {
3927
+ return FolderMachineRobotsDtoToJSONTyped(json, false);
3928
+ }
3929
+ function FolderMachineRobotsDtoToJSONTyped(value, ignoreDiscriminator = false) {
3930
+ if (value == null) {
3931
+ return value;
3932
+ }
3933
+ return {
3934
+ MachineId: value["machineId"],
3935
+ FolderId: value["folderId"],
3936
+ AddedRobotIds: value["addedRobotIds"],
3937
+ RemovedRobotIds: value["removedRobotIds"]
3938
+ };
3939
+ }
3940
+
3941
+ // ../orchestrator-sdk/generated/src/models/FolderUpdateNameDescriptionRequest.ts
3942
+ function FolderUpdateNameDescriptionRequestToJSON(json) {
3943
+ return FolderUpdateNameDescriptionRequestToJSONTyped(json, false);
3944
+ }
3945
+ function FolderUpdateNameDescriptionRequestToJSONTyped(value, ignoreDiscriminator = false) {
3946
+ if (value == null) {
3947
+ return value;
3948
+ }
3949
+ return {
3950
+ name: value["name"],
3951
+ description: value["description"]
3916
3952
  };
3917
3953
  }
3918
3954
 
@@ -4036,30 +4072,12 @@ function ODataValueOfIEnumerableOfMachineFolderDtoFromJSONTyped(json, ignoreDisc
4036
4072
  function ODataValueOfIEnumerableOfMoveFolderMachineChangeFromJSON(json) {
4037
4073
  return ODataValueOfIEnumerableOfMoveFolderMachineChangeFromJSONTyped(json, false);
4038
4074
  }
4039
- function ODataValueOfIEnumerableOfMoveFolderMachineChangeFromJSONTyped(json, ignoreDiscriminator) {
4040
- if (json == null) {
4041
- return json;
4042
- }
4043
- return {
4044
- value: json["value"] == null ? undefined : json["value"].map(MoveFolderMachineChangeFromJSON)
4045
- };
4046
- }
4047
-
4048
- // ../orchestrator-sdk/generated/src/models/UserRoleDto.ts
4049
- function UserRoleDtoFromJSON(json) {
4050
- return UserRoleDtoFromJSONTyped(json, false);
4051
- }
4052
- function UserRoleDtoFromJSONTyped(json, ignoreDiscriminator) {
4075
+ function ODataValueOfIEnumerableOfMoveFolderMachineChangeFromJSONTyped(json, ignoreDiscriminator) {
4053
4076
  if (json == null) {
4054
4077
  return json;
4055
4078
  }
4056
4079
  return {
4057
- userId: json["UserId"] == null ? undefined : json["UserId"],
4058
- roleId: json["RoleId"] == null ? undefined : json["RoleId"],
4059
- userName: json["UserName"] == null ? undefined : json["UserName"],
4060
- roleName: json["RoleName"] == null ? undefined : json["RoleName"],
4061
- roleType: json["RoleType"] == null ? undefined : json["RoleType"],
4062
- id: json["Id"] == null ? undefined : json["Id"]
4080
+ value: json["value"] == null ? undefined : json["value"].map(MoveFolderMachineChangeFromJSON)
4063
4081
  };
4064
4082
  }
4065
4083
 
@@ -5440,6 +5458,12 @@ async function createOrchestratorConfig(options) {
5440
5458
  };
5441
5459
  if (options?.folderId) {
5442
5460
  headers["X-UIPATH-OrganizationUnitId"] = options.folderId;
5461
+ } else if (options?.folderKey && options?.folderPath) {
5462
+ throw new Error("Provide either folderKey or folderPath, not both.");
5463
+ } else if (options?.folderKey) {
5464
+ headers["X-UIPATH-FolderKey"] = options.folderKey;
5465
+ } else if (options?.folderPath) {
5466
+ headers["X-UIPATH-FolderPath"] = options.folderPath;
5443
5467
  }
5444
5468
  return new Configuration2({
5445
5469
  basePath: orchestratorBasePath,
@@ -5464,40 +5488,42 @@ var registerTestcaseCommand = (program) => {
5464
5488
  if (!ctx)
5465
5489
  return;
5466
5490
  const { tmConfig, projectId } = ctx;
5467
- try {
5468
- const testCasesApi = new TestCasesApi(tmConfig);
5469
- const testCase = await testCasesApi.testCasesCreate({
5491
+ const testCasesApi = new TestCasesApi(tmConfig);
5492
+ const [error, testCase] = await catchError7(testCasesApi.testCasesCreate({
5493
+ projectId,
5494
+ uiPathTestManagementHubTestManagementAbstractionsDTOsCreateTestCaseRequest: {
5495
+ name: options.name,
5496
+ description: options.description ?? "",
5470
5497
  projectId,
5471
- uiPathTestManagementHubTestManagementAbstractionsDTOsCreateTestCaseRequest: {
5472
- name: options.name,
5473
- description: options.description ?? "",
5474
- projectId,
5475
- version: options.version
5476
- }
5498
+ version: options.version
5499
+ }
5500
+ }));
5501
+ if (error) {
5502
+ const { message, details } = await extractErrorDetails6(error, {
5503
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
5477
5504
  });
5478
- OutputFormatter7.success(new SuccessOutput6("TestCaseCreate", {
5479
- TestCaseKey: testCase.objKey ?? "",
5480
- Id: testCase.id ?? "",
5481
- Name: testCase.name ?? "",
5482
- Description: testCase.description ?? "",
5483
- Version: testCase.version ?? ""
5484
- }));
5485
- } catch (error) {
5486
- const { message, details } = await extractErrorDetails(error);
5487
5505
  OutputFormatter7.error({
5488
5506
  Result: "Failure",
5489
5507
  Message: message,
5490
5508
  Instructions: details
5491
5509
  });
5492
5510
  processContext6.exit(1);
5511
+ return;
5493
5512
  }
5513
+ OutputFormatter7.success(new SuccessOutput6("TestCaseCreate", {
5514
+ TestCaseKey: testCase.objKey ?? "",
5515
+ Id: testCase.id ?? "",
5516
+ Name: testCase.name ?? "",
5517
+ Description: testCase.description ?? "",
5518
+ Version: testCase.version ?? ""
5519
+ }));
5494
5520
  });
5495
5521
  testcaseCmd.command("list").description("List all test cases in a Test Manager project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").option("--filter <text>", "Filter test cases by name or key").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5496
5522
  const ctx = await resolveCommandContext(options);
5497
5523
  if (!ctx)
5498
5524
  return;
5499
5525
  const { tmConfig, projectId } = ctx;
5500
- try {
5526
+ const [error, rows] = await catchError7((async () => {
5501
5527
  const testCasesApi = new TestCasesApi(tmConfig);
5502
5528
  const all = [];
5503
5529
  const top = 50;
@@ -5508,250 +5534,364 @@ var registerTestcaseCommand = (program) => {
5508
5534
  top,
5509
5535
  skip,
5510
5536
  orderby: "name asc",
5511
- ...options.filter && { search: options.filter }
5537
+ ...options.filter && {
5538
+ search: options.filter
5539
+ }
5512
5540
  });
5513
- const items = page.data ?? [];
5541
+ const pageRecord = page;
5542
+ const items = pageRecord.data ?? [];
5514
5543
  all.push(...items);
5515
- const total = page.paging?.total ?? items.length;
5544
+ const paging = pageRecord.paging;
5545
+ const total = paging?.total ?? items.length;
5516
5546
  skip += top;
5517
5547
  if (skip >= total || items.length < top)
5518
5548
  break;
5519
5549
  }
5520
- const rows = all.map((tc) => ({
5550
+ return all.map((tc) => ({
5521
5551
  TestCaseKey: tc.objKey ?? "",
5522
5552
  Name: tc.name ?? "",
5523
5553
  Version: tc.version ?? "",
5524
5554
  Description: tc.description ?? ""
5525
5555
  }));
5526
- OutputFormatter7.success(new SuccessOutput6("TestCasesList", rows));
5527
- } catch (error) {
5528
- const { message, details } = await extractErrorDetails(error);
5556
+ })());
5557
+ if (error) {
5558
+ const { message, details } = await extractErrorDetails6(error, {
5559
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
5560
+ });
5529
5561
  OutputFormatter7.error({
5530
5562
  Result: "Failure",
5531
5563
  Message: message,
5532
5564
  Instructions: details
5533
5565
  });
5534
5566
  processContext6.exit(1);
5567
+ return;
5535
5568
  }
5569
+ OutputFormatter7.success(new SuccessOutput6("TestCasesList", rows));
5536
5570
  });
5537
5571
  testcaseCmd.command("delete").description("Delete a test case by its key.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case object key (e.g. LEO-42)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5538
5572
  const ctx = await resolveCommandContext(options);
5539
5573
  if (!ctx)
5540
5574
  return;
5541
5575
  const { tmConfig, projectId } = ctx;
5542
- try {
5543
- const testCasesApi = new TestCasesApi(tmConfig);
5544
- const testCaseKey = options.testCaseKey;
5545
- const page = await testCasesApi.testCasesGetTestCases({
5546
- projectId,
5547
- search: testCaseKey,
5548
- top: 50
5576
+ const testCasesApi = new TestCasesApi(tmConfig);
5577
+ const testCaseKey = options.testCaseKey;
5578
+ const [resolveError, page] = await catchError7(testCasesApi.testCasesGetTestCases({
5579
+ projectId,
5580
+ search: testCaseKey,
5581
+ top: 50
5582
+ }));
5583
+ if (resolveError) {
5584
+ const { message, details } = await extractErrorDetails6(resolveError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5585
+ OutputFormatter7.error({
5586
+ Result: "Failure",
5587
+ Message: message,
5588
+ Instructions: details
5549
5589
  });
5550
- const items = page.data ?? [];
5551
- const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5552
- if (!testCase?.id) {
5553
- OutputFormatter7.error({
5554
- Result: "Failure",
5555
- Message: `Test case '${testCaseKey}' not found.`
5556
- });
5557
- processContext6.exit(1);
5558
- return;
5559
- }
5560
- await testCasesApi.testCasesDelete({
5561
- projectId,
5562
- id: testCase.id
5590
+ processContext6.exit(1);
5591
+ return;
5592
+ }
5593
+ const pageRecord = page;
5594
+ const items = pageRecord.data ?? [];
5595
+ const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5596
+ if (!testCase?.id) {
5597
+ OutputFormatter7.error({
5598
+ Result: "Failure",
5599
+ Message: `Test case '${testCaseKey}' not found.`
5563
5600
  });
5564
- OutputFormatter7.success(new SuccessOutput6("TestCaseDelete", {
5565
- TestCaseKey: testCaseKey,
5566
- Id: testCase.id,
5567
- Result: "Deleted"
5568
- }));
5569
- } catch (error) {
5570
- const { message, details } = await extractErrorDetails(error);
5601
+ processContext6.exit(1);
5602
+ return;
5603
+ }
5604
+ const [deleteError] = await catchError7(testCasesApi.testCasesDelete({
5605
+ projectId,
5606
+ id: testCase.id
5607
+ }));
5608
+ if (deleteError) {
5609
+ const { message, details } = await extractErrorDetails6(deleteError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5571
5610
  OutputFormatter7.error({
5572
5611
  Result: "Failure",
5573
5612
  Message: message,
5574
5613
  Instructions: details
5575
5614
  });
5576
5615
  processContext6.exit(1);
5616
+ return;
5577
5617
  }
5618
+ OutputFormatter7.success(new SuccessOutput6("TestCaseDelete", {
5619
+ TestCaseKey: testCaseKey,
5620
+ Id: testCase.id,
5621
+ Result: "Deleted"
5622
+ }));
5578
5623
  });
5579
- testcaseCmd.command("link-automation").description("Link an Orchestrator package automation to a test case.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case object key (e.g. LEO:2)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'bun run start orch folders list')").requiredOption("--package-name <name>", "Orchestrator package identifier (e.g. ProjCSCrossTestCases)").requiredOption("--test-name <name>", "Test case name inside the package (e.g. MyLeoTest2)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5624
+ testcaseCmd.command("link-automation").description("Link an Orchestrator package automation to a test case.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case object key (e.g. LEO:2)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'uip or folders list')").requiredOption("--package-name <name>", "Orchestrator package identifier (e.g. ProjCSCrossTestCases)").requiredOption("--test-name <name>", "Test case name inside the package (e.g. MyLeoTest2)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5580
5625
  const ctx = await resolveCommandContext(options);
5581
5626
  if (!ctx)
5582
5627
  return;
5583
5628
  const { tmConfig, tmBaseUrl, projectId, accessToken } = ctx;
5584
5629
  const authHeader = { Authorization: `Bearer ${accessToken}` };
5585
- try {
5586
- const testCasesApi = new TestCasesApi(tmConfig);
5587
- const testCaseKey = options.testCaseKey;
5588
- const page = await testCasesApi.testCasesGetTestCases({
5589
- projectId,
5590
- search: testCaseKey,
5591
- top: 50
5630
+ const testCasesApi = new TestCasesApi(tmConfig);
5631
+ const testCaseKey = options.testCaseKey;
5632
+ const [resolveError, page] = await catchError7(testCasesApi.testCasesGetTestCases({
5633
+ projectId,
5634
+ search: testCaseKey,
5635
+ top: 50
5636
+ }));
5637
+ if (resolveError) {
5638
+ const { message, details } = await extractErrorDetails6(resolveError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5639
+ OutputFormatter7.error({
5640
+ Result: "Failure",
5641
+ Message: message,
5642
+ Instructions: details
5592
5643
  });
5593
- const items = page.data ?? [];
5594
- const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5595
- if (!testCase?.id) {
5596
- OutputFormatter7.error({
5597
- Result: "Failure",
5598
- Message: `Test case '${testCaseKey}' not found.`
5599
- });
5600
- processContext6.exit(1);
5601
- return;
5602
- }
5603
- const foldersApi = await createApiClient(FoldersApi, {
5604
- tenant: options.tenant
5644
+ processContext6.exit(1);
5645
+ return;
5646
+ }
5647
+ const pageRecord = page;
5648
+ const items = pageRecord.data ?? [];
5649
+ const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5650
+ if (!testCase?.id) {
5651
+ OutputFormatter7.error({
5652
+ Result: "Failure",
5653
+ Message: `Test case '${testCaseKey}' not found.`
5605
5654
  });
5606
- const foldersResult = await foldersApi.foldersGet({
5607
- $filter: `Key eq ${options.folderKey}`,
5608
- $top: 1
5655
+ processContext6.exit(1);
5656
+ return;
5657
+ }
5658
+ const [folderApiError, foldersApi] = await catchError7(createApiClient(FoldersApi, {
5659
+ tenant: options.tenant
5660
+ }));
5661
+ if (folderApiError) {
5662
+ const { message, details } = await extractErrorDetails6(folderApiError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5663
+ OutputFormatter7.error({
5664
+ Result: "Failure",
5665
+ Message: message,
5666
+ Instructions: details
5609
5667
  });
5610
- const folderMatch = foldersResult.value?.[0];
5611
- if (!folderMatch?.displayName) {
5612
- OutputFormatter7.error({
5613
- Result: "Failure",
5614
- Message: `Folder with key '${options.folderKey}' not found.`
5615
- });
5616
- processContext6.exit(1);
5617
- return;
5618
- }
5619
- const folderDisplayName = folderMatch.displayName;
5620
- const search = encodeURIComponent(options.testName);
5621
- const entryPointsRes = await fetch(`${tmBaseUrl}/api/v2/${projectId}/orchestrator/packageentrypoints?Top=100&Skip=0&Search=${search}&folderKey=${options.folderKey}&DistinctByPackageEntryPointIdAndPackageName=true`, { headers: authHeader });
5622
- if (!entryPointsRes.ok)
5623
- throw new Error(`Failed to look up package entry points: ${entryPointsRes.status} ${entryPointsRes.statusText}`);
5624
- const entryPointsData = await entryPointsRes.json();
5625
- const entryPoints = entryPointsData.data ?? entryPointsData ?? [];
5626
- const entryPoint = entryPoints.find((ep) => (ep.packageName ?? ep.packageIdentifier)?.toLowerCase() === options.packageName.toLowerCase() && ep.name?.toLowerCase() === options.testName.toLowerCase());
5627
- if (!entryPoint) {
5628
- OutputFormatter7.error({
5629
- Result: "Failure",
5630
- Message: `Test '${options.testName}' not found in package '${options.packageName}' for folder '${options.folderKey}'.`
5631
- });
5632
- processContext6.exit(1);
5633
- return;
5634
- }
5635
- const packageEntryPointUniqueId = entryPoint.packageEntryPointId;
5636
- const updateRes = await fetch(`${tmBaseUrl}/api/v2/${projectId}/testcases/${testCase.id}/updatepackageautomation`, {
5637
- method: "POST",
5638
- headers: {
5639
- ...authHeader,
5640
- "Content-Type": "application/json"
5641
- },
5642
- body: JSON.stringify({
5643
- testCaseId: testCase.id,
5644
- packageEntryPointUniqueId,
5645
- packageIdentifier: options.packageName,
5646
- packageEntryPointName: options.testName,
5647
- folderKey: options.folderKey,
5648
- packageSourceName: folderDisplayName
5649
- })
5668
+ processContext6.exit(1);
5669
+ return;
5670
+ }
5671
+ const [foldersError, foldersResult] = await catchError7(foldersApi.foldersGet({
5672
+ $filter: `Key eq ${options.folderKey}`,
5673
+ $top: 1
5674
+ }));
5675
+ if (foldersError) {
5676
+ const { message, details } = await extractErrorDetails6(foldersError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5677
+ OutputFormatter7.error({
5678
+ Result: "Failure",
5679
+ Message: message,
5680
+ Instructions: details
5650
5681
  });
5651
- if (!updateRes.ok) {
5652
- const body = await updateRes.text().catch(() => "");
5653
- throw new Error(`HTTP ${updateRes.status} ${updateRes.statusText}${body ? `: ${body}` : ""}`);
5654
- }
5655
- OutputFormatter7.success(new SuccessOutput6("TestCaseLinkAutomation", {
5656
- TestCaseKey: testCaseKey,
5657
- PackageName: options.packageName,
5658
- PackageSource: folderDisplayName,
5659
- TestName: options.testName,
5660
- Result: "Linked"
5661
- }));
5662
- } catch (error) {
5663
- const { message, details } = await extractErrorDetails(error);
5682
+ processContext6.exit(1);
5683
+ return;
5684
+ }
5685
+ const folderMatch = foldersResult.value?.[0];
5686
+ if (!folderMatch?.displayName) {
5687
+ OutputFormatter7.error({
5688
+ Result: "Failure",
5689
+ Message: `Folder with key '${options.folderKey}' not found.`
5690
+ });
5691
+ processContext6.exit(1);
5692
+ return;
5693
+ }
5694
+ const folderDisplayName = folderMatch.displayName;
5695
+ const search = encodeURIComponent(options.testName);
5696
+ const [epFetchError, entryPointsRes] = await catchError7(fetch(`${tmBaseUrl}/api/v2/${projectId}/orchestrator/packageentrypoints?Top=100&Skip=0&Search=${search}&folderKey=${options.folderKey}&DistinctByPackageEntryPointIdAndPackageName=true`, { headers: authHeader }));
5697
+ if (epFetchError) {
5698
+ const { message, details } = await extractErrorDetails6(epFetchError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5699
+ OutputFormatter7.error({
5700
+ Result: "Failure",
5701
+ Message: message,
5702
+ Instructions: details
5703
+ });
5704
+ processContext6.exit(1);
5705
+ return;
5706
+ }
5707
+ if (!entryPointsRes.ok) {
5708
+ const { message, details } = await extractErrorDetails6(new Error(`Failed to look up package entry points: ${entryPointsRes.status} ${entryPointsRes.statusText}`), { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5709
+ OutputFormatter7.error({
5710
+ Result: "Failure",
5711
+ Message: message,
5712
+ Instructions: details
5713
+ });
5714
+ processContext6.exit(1);
5715
+ return;
5716
+ }
5717
+ const entryPointsData = await entryPointsRes.json();
5718
+ const entryPoints = entryPointsData.data ?? entryPointsData ?? [];
5719
+ const entryPoint = entryPoints.find((ep) => (ep.packageName ?? ep.packageIdentifier)?.toLowerCase() === options.packageName.toLowerCase() && ep.name?.toLowerCase() === options.testName.toLowerCase());
5720
+ if (!entryPoint) {
5721
+ OutputFormatter7.error({
5722
+ Result: "Failure",
5723
+ Message: `Test '${options.testName}' not found in package '${options.packageName}' for folder '${options.folderKey}'.`
5724
+ });
5725
+ processContext6.exit(1);
5726
+ return;
5727
+ }
5728
+ const packageEntryPointUniqueId = entryPoint.packageEntryPointId;
5729
+ const [updateError, updateRes] = await catchError7(fetch(`${tmBaseUrl}/api/v2/${projectId}/testcases/${testCase.id}/updatepackageautomation`, {
5730
+ method: "POST",
5731
+ headers: {
5732
+ ...authHeader,
5733
+ "Content-Type": "application/json"
5734
+ },
5735
+ body: JSON.stringify({
5736
+ testCaseId: testCase.id,
5737
+ packageEntryPointUniqueId,
5738
+ packageIdentifier: options.packageName,
5739
+ packageEntryPointName: options.testName,
5740
+ folderKey: options.folderKey,
5741
+ packageSourceName: folderDisplayName
5742
+ })
5743
+ }));
5744
+ if (updateError) {
5745
+ const { message, details } = await extractErrorDetails6(updateError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5746
+ OutputFormatter7.error({
5747
+ Result: "Failure",
5748
+ Message: message,
5749
+ Instructions: details
5750
+ });
5751
+ processContext6.exit(1);
5752
+ return;
5753
+ }
5754
+ if (!updateRes.ok) {
5755
+ const body = await updateRes.text().catch(() => "");
5756
+ const { message, details } = await extractErrorDetails6(new Error(`HTTP ${updateRes.status} ${updateRes.statusText}${body ? `: ${body}` : ""}`), { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5664
5757
  OutputFormatter7.error({
5665
5758
  Result: "Failure",
5666
5759
  Message: message,
5667
5760
  Instructions: details
5668
5761
  });
5669
5762
  processContext6.exit(1);
5763
+ return;
5670
5764
  }
5765
+ OutputFormatter7.success(new SuccessOutput6("TestCaseLinkAutomation", {
5766
+ TestCaseKey: testCaseKey,
5767
+ PackageName: options.packageName,
5768
+ PackageSource: folderDisplayName,
5769
+ TestName: options.testName,
5770
+ Result: "Linked"
5771
+ }));
5671
5772
  });
5672
5773
  testcaseCmd.command("update").description("Update a test case name or description.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case key (e.g. LEO:1)").option("--name <name>", "New test case name").option("--description <text>", "New test case description").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5673
5774
  const ctx = await resolveCommandContext(options);
5674
5775
  if (!ctx)
5675
5776
  return;
5676
5777
  const { tmConfig, projectId } = ctx;
5677
- try {
5678
- const testCasesApi = new TestCasesApi(tmConfig);
5679
- const all = await testCasesApi.testCasesGetTestCases({
5680
- projectId
5778
+ const testCasesApi = new TestCasesApi(tmConfig);
5779
+ const [resolveError, all] = await catchError7(testCasesApi.testCasesGetTestCases({ projectId }));
5780
+ if (resolveError) {
5781
+ const { message, details } = await extractErrorDetails6(resolveError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5782
+ OutputFormatter7.error({
5783
+ Result: "Failure",
5784
+ Message: message,
5785
+ Instructions: details
5681
5786
  });
5682
- const items = all.data ?? [];
5683
- const testCase = items.find((tc) => tc.objKey?.toLowerCase() === options.testCaseKey.toLowerCase());
5684
- if (!testCase)
5685
- throw new Error(`Test case '${options.testCaseKey}' not found.`);
5686
- const operations = [];
5687
- if (options.name)
5688
- operations.push({
5689
- op: "replace",
5690
- path: "/name",
5691
- value: options.name
5692
- });
5693
- if (options.description !== undefined)
5694
- operations.push({
5695
- op: "replace",
5696
- path: "/description",
5697
- value: options.description
5698
- });
5699
- if (operations.length === 0)
5700
- throw new Error("Provide at least --name or --description to update.");
5701
- await testCasesApi.testCasesPatch({
5702
- id: testCase.id,
5703
- projectId,
5704
- operations
5787
+ processContext6.exit(1);
5788
+ return;
5789
+ }
5790
+ const allRecord = all;
5791
+ const items = allRecord.data ?? [];
5792
+ const testCase = items.find((tc) => tc.objKey?.toLowerCase() === options.testCaseKey.toLowerCase());
5793
+ if (!testCase) {
5794
+ OutputFormatter7.error({
5795
+ Result: "Failure",
5796
+ Message: `Test case '${options.testCaseKey}' not found.`,
5797
+ Instructions: `Test case '${options.testCaseKey}' not found.`
5705
5798
  });
5706
- OutputFormatter7.success(new SuccessOutput6("TestCaseUpdate", {
5707
- TestCaseKey: options.testCaseKey,
5708
- Name: options.name ?? testCase.name ?? "",
5709
- Description: options.description ?? testCase.description ?? "",
5710
- Result: "Updated"
5711
- }));
5712
- } catch (error) {
5713
- const { message, details } = await extractErrorDetails(error);
5799
+ processContext6.exit(1);
5800
+ return;
5801
+ }
5802
+ const operations = [];
5803
+ if (options.name)
5804
+ operations.push({
5805
+ op: "replace",
5806
+ path: "/name",
5807
+ value: options.name
5808
+ });
5809
+ if (options.description !== undefined)
5810
+ operations.push({
5811
+ op: "replace",
5812
+ path: "/description",
5813
+ value: options.description
5814
+ });
5815
+ if (operations.length === 0) {
5816
+ OutputFormatter7.error({
5817
+ Result: "Failure",
5818
+ Message: "Provide at least --name or --description to update.",
5819
+ Instructions: "Provide at least --name or --description to update."
5820
+ });
5821
+ processContext6.exit(1);
5822
+ return;
5823
+ }
5824
+ const [patchError] = await catchError7(testCasesApi.testCasesPatch({
5825
+ id: testCase.id,
5826
+ projectId,
5827
+ operations
5828
+ }));
5829
+ if (patchError) {
5830
+ const { message, details } = await extractErrorDetails6(patchError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5714
5831
  OutputFormatter7.error({
5715
5832
  Result: "Failure",
5716
5833
  Message: message,
5717
5834
  Instructions: details
5718
5835
  });
5719
5836
  processContext6.exit(1);
5837
+ return;
5720
5838
  }
5839
+ OutputFormatter7.success(new SuccessOutput6("TestCaseUpdate", {
5840
+ TestCaseKey: options.testCaseKey,
5841
+ Name: options.name ?? testCase.name ?? "",
5842
+ Description: options.description ?? testCase.description ?? "",
5843
+ Result: "Updated"
5844
+ }));
5721
5845
  });
5722
5846
  testcaseCmd.command("list-testsets").description("List test sets that contain a given test case.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case key (e.g. LEO:1)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5723
5847
  const ctx = await resolveCommandContext(options);
5724
5848
  if (!ctx)
5725
5849
  return;
5726
5850
  const { tmConfig, projectId } = ctx;
5727
- try {
5728
- const testCasesApi = new TestCasesApi(tmConfig);
5729
- const all = await testCasesApi.testCasesGetTestCases({
5730
- projectId
5851
+ const testCasesApi = new TestCasesApi(tmConfig);
5852
+ const [resolveError, all] = await catchError7(testCasesApi.testCasesGetTestCases({ projectId }));
5853
+ if (resolveError) {
5854
+ const { message, details } = await extractErrorDetails6(resolveError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5855
+ OutputFormatter7.error({
5856
+ Result: "Failure",
5857
+ Message: message,
5858
+ Instructions: details
5731
5859
  });
5732
- const items = all.data ?? [];
5733
- const testCase = items.find((tc) => tc.objKey?.toLowerCase() === options.testCaseKey.toLowerCase());
5734
- if (!testCase)
5735
- throw new Error(`Test case '${options.testCaseKey}' not found.`);
5736
- const testSets = await testCasesApi.testCasesGetAssignedTestSets({
5737
- id: testCase.id,
5738
- projectId
5860
+ processContext6.exit(1);
5861
+ return;
5862
+ }
5863
+ const allRecord = all;
5864
+ const items = allRecord.data ?? [];
5865
+ const testCase = items.find((tc) => tc.objKey?.toLowerCase() === options.testCaseKey.toLowerCase());
5866
+ if (!testCase) {
5867
+ OutputFormatter7.error({
5868
+ Result: "Failure",
5869
+ Message: `Test case '${options.testCaseKey}' not found.`,
5870
+ Instructions: `Test case '${options.testCaseKey}' not found.`
5739
5871
  });
5740
- const rows = testSets.map((ts) => ({
5741
- TestSetKey: ts.objKey ?? "",
5742
- Name: ts.name ?? "",
5743
- FolderKey: ts.folderKey ?? ""
5744
- }));
5745
- OutputFormatter7.success(new SuccessOutput6("TestCaseTestSetsList", rows));
5746
- } catch (error) {
5747
- const { message, details } = await extractErrorDetails(error);
5872
+ processContext6.exit(1);
5873
+ return;
5874
+ }
5875
+ const [testSetsError, testSets] = await catchError7(testCasesApi.testCasesGetAssignedTestSets({
5876
+ id: testCase.id,
5877
+ projectId
5878
+ }));
5879
+ if (testSetsError) {
5880
+ const { message, details } = await extractErrorDetails6(testSetsError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5748
5881
  OutputFormatter7.error({
5749
5882
  Result: "Failure",
5750
5883
  Message: message,
5751
5884
  Instructions: details
5752
5885
  });
5753
5886
  processContext6.exit(1);
5887
+ return;
5754
5888
  }
5889
+ const rows = testSets.map((ts) => ({
5890
+ TestSetKey: ts.objKey ?? "",
5891
+ Name: ts.name ?? "",
5892
+ FolderKey: ts.folderKey ?? ""
5893
+ }));
5894
+ OutputFormatter7.success(new SuccessOutput6("TestCaseTestSetsList", rows));
5755
5895
  });
5756
5896
  testcaseCmd.command("unlink-automation").description("Unlink the automation from a test case.").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--test-case-key <key>", "Test case object key (e.g. LEO:2)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5757
5897
  const ctx = await resolveCommandContext(options);
@@ -5759,70 +5899,90 @@ var registerTestcaseCommand = (program) => {
5759
5899
  return;
5760
5900
  const { tmConfig, tmBaseUrl, projectId, accessToken } = ctx;
5761
5901
  const authHeader = { Authorization: `Bearer ${accessToken}` };
5762
- try {
5763
- const testCasesApi = new TestCasesApi(tmConfig);
5764
- const testCaseKey = options.testCaseKey;
5765
- const page = await testCasesApi.testCasesGetTestCases({
5766
- projectId,
5767
- search: testCaseKey,
5768
- top: 50
5902
+ const testCasesApi = new TestCasesApi(tmConfig);
5903
+ const testCaseKey = options.testCaseKey;
5904
+ const [resolveError, page] = await catchError7(testCasesApi.testCasesGetTestCases({
5905
+ projectId,
5906
+ search: testCaseKey,
5907
+ top: 50
5908
+ }));
5909
+ if (resolveError) {
5910
+ const { message, details } = await extractErrorDetails6(resolveError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5911
+ OutputFormatter7.error({
5912
+ Result: "Failure",
5913
+ Message: message,
5914
+ Instructions: details
5769
5915
  });
5770
- const items = page.data ?? [];
5771
- const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5772
- if (!testCase?.id) {
5773
- OutputFormatter7.error({
5774
- Result: "Failure",
5775
- Message: `Test case '${testCaseKey}' not found.`
5776
- });
5777
- processContext6.exit(1);
5778
- return;
5779
- }
5780
- const updateRes = await fetch(`${tmBaseUrl}/api/v2/${projectId}/testcases/${testCase.id}/updatepackageautomation`, {
5781
- method: "POST",
5782
- headers: {
5783
- ...authHeader,
5784
- "Content-Type": "application/json"
5785
- },
5786
- body: JSON.stringify({
5787
- testCaseId: testCase.id,
5788
- packageEntryPointUniqueId: null,
5789
- packageIdentifier: null,
5790
- packageEntryPointName: null,
5791
- folderKey: null,
5792
- packageSourceName: null
5793
- })
5916
+ processContext6.exit(1);
5917
+ return;
5918
+ }
5919
+ const pageRecord = page;
5920
+ const items = pageRecord.data ?? [];
5921
+ const testCase = items.find((tc) => tc.objKey?.toLowerCase() === testCaseKey.toLowerCase());
5922
+ if (!testCase?.id) {
5923
+ OutputFormatter7.error({
5924
+ Result: "Failure",
5925
+ Message: `Test case '${testCaseKey}' not found.`
5794
5926
  });
5795
- if (!updateRes.ok) {
5796
- const body = await updateRes.text().catch(() => "");
5797
- throw new Error(`HTTP ${updateRes.status} ${updateRes.statusText}${body ? `: ${body}` : ""}`);
5798
- }
5799
- OutputFormatter7.success(new SuccessOutput6("TestCaseUnlinkAutomation", {
5800
- TestCaseKey: testCaseKey,
5801
- Result: "Unlinked"
5802
- }));
5803
- } catch (error) {
5804
- const { message, details } = await extractErrorDetails(error);
5927
+ processContext6.exit(1);
5928
+ return;
5929
+ }
5930
+ const [updateError, updateRes] = await catchError7(fetch(`${tmBaseUrl}/api/v2/${projectId}/testcases/${testCase.id}/updatepackageautomation`, {
5931
+ method: "POST",
5932
+ headers: {
5933
+ ...authHeader,
5934
+ "Content-Type": "application/json"
5935
+ },
5936
+ body: JSON.stringify({
5937
+ testCaseId: testCase.id,
5938
+ packageEntryPointUniqueId: null,
5939
+ packageIdentifier: null,
5940
+ packageEntryPointName: null,
5941
+ folderKey: null,
5942
+ packageSourceName: null
5943
+ })
5944
+ }));
5945
+ if (updateError) {
5946
+ const { message, details } = await extractErrorDetails6(updateError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5947
+ OutputFormatter7.error({
5948
+ Result: "Failure",
5949
+ Message: message,
5950
+ Instructions: details
5951
+ });
5952
+ processContext6.exit(1);
5953
+ return;
5954
+ }
5955
+ if (!updateRes.ok) {
5956
+ const body = await updateRes.text().catch(() => "");
5957
+ const { message, details } = await extractErrorDetails6(new Error(`HTTP ${updateRes.status} ${updateRes.statusText}${body ? `: ${body}` : ""}`), { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5805
5958
  OutputFormatter7.error({
5806
5959
  Result: "Failure",
5807
5960
  Message: message,
5808
5961
  Instructions: details
5809
5962
  });
5810
5963
  processContext6.exit(1);
5964
+ return;
5811
5965
  }
5966
+ OutputFormatter7.success(new SuccessOutput6("TestCaseUnlinkAutomation", {
5967
+ TestCaseKey: testCaseKey,
5968
+ Result: "Unlinked"
5969
+ }));
5812
5970
  });
5813
- testcaseCmd.command("list-automations").description("List test entry points available in an Orchestrator folder (use with link-automation).").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'uip orch folders list')").option("--package-name <name>", "Filter by package name (case-insensitive substring)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5971
+ testcaseCmd.command("list-automations").description("List test entry points available in an Orchestrator folder (use with link-automation).").requiredOption("--project-key <key>", "Test Manager project key (e.g. LEO)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'uip or folders list')").option("--package-name <name>", "Filter by package name (case-insensitive substring)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext6, async (options) => {
5814
5972
  const ctx = await resolveCommandContext(options);
5815
5973
  if (!ctx)
5816
5974
  return;
5817
5975
  const { tmBaseUrl, accessToken, projectId } = ctx;
5818
- try {
5976
+ const [error, rows] = await catchError7((async () => {
5819
5977
  const all = [];
5820
5978
  const top = 100;
5821
5979
  let skip = 0;
5822
5980
  while (true) {
5823
5981
  const url = `${tmBaseUrl}/api/v2/${projectId}/orchestrator/packageentrypoints` + `?Top=${top}&Skip=${skip}&folderKey=${options.folderKey}` + `&DistinctByPackageEntryPointIdAndPackageName=true`;
5824
5982
  const res = await fetch(url, {
5825
- headers: { Authorization: `Bearer ${accessToken}` }
5983
+ headers: {
5984
+ Authorization: `Bearer ${accessToken}`
5985
+ }
5826
5986
  });
5827
5987
  if (!res.ok) {
5828
5988
  const body = await res.text().catch(() => "");
@@ -5831,32 +5991,39 @@ var registerTestcaseCommand = (program) => {
5831
5991
  const data = await res.json();
5832
5992
  const items = data.data ?? data ?? [];
5833
5993
  all.push(...items);
5834
- const total = data.paging?.total ?? data.total ?? items.length;
5994
+ const paging = data.paging;
5995
+ const total = paging?.total ?? data.total ?? items.length;
5835
5996
  skip += top;
5836
5997
  if (skip >= total || items.length < top)
5837
5998
  break;
5838
5999
  }
5839
6000
  const filtered = options.packageName ? all.filter((ep) => ep.packageName?.toLowerCase() === options.packageName.toLowerCase()) : all;
5840
- const rows = filtered.map((ep) => ({
6001
+ return filtered.map((ep) => ({
5841
6002
  PackageName: ep.packageName ?? "",
5842
6003
  TestName: ep.name ?? "",
5843
6004
  PackageVersion: ep.packageAppVersion ?? ""
5844
6005
  }));
5845
- OutputFormatter7.success(new SuccessOutput6("TestAutomationsList", rows));
5846
- } catch (error) {
5847
- const { message, details } = await extractErrorDetails(error);
6006
+ })());
6007
+ if (error) {
6008
+ const { message, details } = await extractErrorDetails6(error, {
6009
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6010
+ });
5848
6011
  OutputFormatter7.error({
5849
6012
  Result: "Failure",
5850
6013
  Message: message,
5851
6014
  Instructions: details
5852
6015
  });
5853
6016
  processContext6.exit(1);
6017
+ return;
5854
6018
  }
6019
+ OutputFormatter7.success(new SuccessOutput6("TestAutomationsList", rows));
5855
6020
  });
5856
6021
  };
5857
6022
 
5858
6023
  // src/commands/testset.ts
5859
6024
  import {
6025
+ catchError as catchError8,
6026
+ extractErrorDetails as extractErrorDetails7,
5860
6027
  logger as logger6,
5861
6028
  OutputFormatter as OutputFormatter8,
5862
6029
  processContext as processContext7,
@@ -5869,263 +6036,397 @@ var registerTestsetCommand = (program) => {
5869
6036
  const ctx = await resolveCommandContext(options);
5870
6037
  if (!ctx)
5871
6038
  return;
5872
- const { tmConfig, projectId } = ctx;
5873
- try {
5874
- const testSetsApi = new TestSetsApi(tmConfig);
5875
- const apiResponse = await testSetsApi.testSetsCreateRaw({
5876
- projectId,
5877
- uiPathTestManagementHubTestManagementAbstractionsDTOsCreateTestSetRequest: {
5878
- name: options.name,
5879
- description: options.description ?? "",
5880
- projectId
5881
- }
6039
+ const { tmConfig, projectId } = ctx;
6040
+ const testSetsApi = new TestSetsApi(tmConfig);
6041
+ const [error, apiResponse] = await catchError8(testSetsApi.testSetsCreateRaw({
6042
+ projectId,
6043
+ uiPathTestManagementHubTestManagementAbstractionsDTOsCreateTestSetRequest: {
6044
+ name: options.name,
6045
+ description: options.description ?? "",
6046
+ projectId
6047
+ }
6048
+ }));
6049
+ if (error) {
6050
+ const { message, details } = await extractErrorDetails7(error, {
6051
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6052
+ });
6053
+ OutputFormatter8.error({
6054
+ Result: "Failure",
6055
+ Message: message,
6056
+ Instructions: details
6057
+ });
6058
+ processContext7.exit(1);
6059
+ return;
6060
+ }
6061
+ const [jsonError, testSet] = await catchError8(apiResponse.raw.json());
6062
+ if (jsonError) {
6063
+ const { message, details } = await extractErrorDetails7(jsonError, {
6064
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
5882
6065
  });
5883
- const testSet = await apiResponse.raw.json();
5884
- OutputFormatter8.success(new SuccessOutput7("TestSetCreate", {
5885
- TestSetKey: testSet.objKey ?? "",
5886
- Name: testSet.name ?? options.name,
5887
- Description: testSet.description ?? ""
5888
- }));
5889
- } catch (error) {
5890
- const { message, details } = await extractErrorDetails(error);
5891
6066
  OutputFormatter8.error({
5892
6067
  Result: "Failure",
5893
6068
  Message: message,
5894
6069
  Instructions: details
5895
6070
  });
5896
6071
  processContext7.exit(1);
6072
+ return;
5897
6073
  }
6074
+ OutputFormatter8.success(new SuccessOutput7("TestSetCreate", {
6075
+ TestSetKey: testSet.objKey ?? "",
6076
+ Name: testSet.name ?? options.name,
6077
+ Description: testSet.description ?? ""
6078
+ }));
5898
6079
  });
5899
6080
  testsetCmd.command("delete").description("Delete a test set by its key.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
5900
6081
  const ctx = await resolveCommandContext(options);
5901
6082
  if (!ctx)
5902
6083
  return;
5903
6084
  const { tmConfig, projectId } = ctx;
5904
- try {
5905
- const testSetsApi = new TestSetsApi(tmConfig);
5906
- const testSetKey = options.testSetKey;
5907
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
5908
- objKey: testSetKey,
5909
- projectId
6085
+ const testSetsApi = new TestSetsApi(tmConfig);
6086
+ const testSetKey = options.testSetKey;
6087
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6088
+ objKey: testSetKey,
6089
+ projectId
6090
+ }));
6091
+ if (error) {
6092
+ const { message, details } = await extractErrorDetails7(error, {
6093
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
5910
6094
  });
5911
- if (!testSet.id) {
5912
- OutputFormatter8.error({
5913
- Result: "Failure",
5914
- Message: `Test set '${testSetKey}' not found.`
5915
- });
5916
- processContext7.exit(1);
5917
- return;
5918
- }
5919
- await testSetsApi.testSetsDelete({
5920
- id: testSet.id,
5921
- projectId
6095
+ OutputFormatter8.error({
6096
+ Result: "Failure",
6097
+ Message: message,
6098
+ Instructions: details
5922
6099
  });
5923
- OutputFormatter8.success(new SuccessOutput7("TestSetDelete", {
5924
- TestSetKey: testSetKey,
5925
- Id: testSet.id,
5926
- Result: "Deleted"
5927
- }));
5928
- } catch (error) {
5929
- const { message, details } = await extractErrorDetails(error);
6100
+ processContext7.exit(1);
6101
+ return;
6102
+ }
6103
+ if (!testSet.id) {
6104
+ OutputFormatter8.error({
6105
+ Result: "Failure",
6106
+ Message: `Test set '${testSetKey}' not found.`
6107
+ });
6108
+ processContext7.exit(1);
6109
+ return;
6110
+ }
6111
+ const [deleteError] = await catchError8(testSetsApi.testSetsDelete({
6112
+ id: testSet.id,
6113
+ projectId
6114
+ }));
6115
+ if (deleteError) {
6116
+ const { message, details } = await extractErrorDetails7(deleteError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5930
6117
  OutputFormatter8.error({
5931
6118
  Result: "Failure",
5932
6119
  Message: message,
5933
6120
  Instructions: details
5934
6121
  });
5935
6122
  processContext7.exit(1);
6123
+ return;
5936
6124
  }
6125
+ OutputFormatter8.success(new SuccessOutput7("TestSetDelete", {
6126
+ TestSetKey: testSetKey,
6127
+ Id: testSet.id,
6128
+ Result: "Deleted"
6129
+ }));
5937
6130
  });
5938
6131
  testsetCmd.command("add-testcases").description("Add test cases to a test set.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42)").requiredOption("--test-case-keys <keys>", "Comma-separated test case keys to add (e.g. DEMO:1,DEMO:2)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
5939
6132
  const ctx = await resolveCommandContext(options);
5940
6133
  if (!ctx)
5941
6134
  return;
5942
6135
  const { tmConfig, projectId } = ctx;
5943
- try {
5944
- const testSetsApi = new TestSetsApi(tmConfig);
5945
- const testCasesApi = new TestCasesApi(tmConfig);
5946
- const testSetKey = options.testSetKey;
5947
- const testCaseKeys = options.testCaseKeys.split(",").map((k) => k.trim()).filter(Boolean);
5948
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
5949
- objKey: testSetKey,
5950
- projectId
6136
+ const testSetsApi = new TestSetsApi(tmConfig);
6137
+ const testCasesApi = new TestCasesApi(tmConfig);
6138
+ const testSetKey = options.testSetKey;
6139
+ const testCaseKeys = options.testCaseKeys.split(",").map((k) => k.trim()).filter(Boolean);
6140
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6141
+ objKey: testSetKey,
6142
+ projectId
6143
+ }));
6144
+ if (error) {
6145
+ const { message, details } = await extractErrorDetails7(error, {
6146
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6147
+ });
6148
+ OutputFormatter8.error({
6149
+ Result: "Failure",
6150
+ Message: message,
6151
+ Instructions: details
6152
+ });
6153
+ processContext7.exit(1);
6154
+ return;
6155
+ }
6156
+ if (!testSet.id) {
6157
+ OutputFormatter8.error({
6158
+ Result: "Failure",
6159
+ Message: `Test set '${testSetKey}' not found.`
5951
6160
  });
5952
- if (!testSet.id) {
6161
+ processContext7.exit(1);
6162
+ return;
6163
+ }
6164
+ const testCaseIds = [];
6165
+ for (const tcKey of testCaseKeys) {
6166
+ const [tcError, page] = await catchError8(testCasesApi.testCasesGetTestCases({
6167
+ projectId,
6168
+ search: tcKey,
6169
+ top: 50
6170
+ }));
6171
+ if (tcError) {
6172
+ const { message, details } = await extractErrorDetails7(tcError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5953
6173
  OutputFormatter8.error({
5954
6174
  Result: "Failure",
5955
- Message: `Test set '${testSetKey}' not found.`
6175
+ Message: message,
6176
+ Instructions: details
5956
6177
  });
5957
6178
  processContext7.exit(1);
5958
6179
  return;
5959
6180
  }
5960
- const testCaseIds = [];
5961
- for (const tcKey of testCaseKeys) {
5962
- const page = await testCasesApi.testCasesGetTestCases({
5963
- projectId,
5964
- search: tcKey,
5965
- top: 50
6181
+ const items = page.data ?? [];
6182
+ const tc = items.find((t) => t.objKey?.toLowerCase() === tcKey.toLowerCase());
6183
+ if (!tc?.id) {
6184
+ OutputFormatter8.error({
6185
+ Result: "Failure",
6186
+ Message: `Test case '${tcKey}' not found.`
5966
6187
  });
5967
- const items = page.data ?? [];
5968
- const tc = items.find((t) => t.objKey?.toLowerCase() === tcKey.toLowerCase());
5969
- if (!tc?.id) {
5970
- OutputFormatter8.error({
5971
- Result: "Failure",
5972
- Message: `Test case '${tcKey}' not found.`
5973
- });
5974
- processContext7.exit(1);
5975
- return;
5976
- }
5977
- testCaseIds.push(tc.id);
6188
+ processContext7.exit(1);
6189
+ return;
5978
6190
  }
5979
- await testSetsApi.testSetsAssignTestCases({
5980
- id: testSet.id,
5981
- projectId,
5982
- requestBody: testCaseIds
5983
- });
5984
- OutputFormatter8.success(new SuccessOutput7("TestSetAddTestCases", {
5985
- TestSetKey: testSetKey,
5986
- Added: testCaseKeys.join(", "),
5987
- Result: "Added"
5988
- }));
5989
- } catch (error) {
5990
- const { message, details } = await extractErrorDetails(error);
6191
+ testCaseIds.push(tc.id);
6192
+ }
6193
+ const [assignError] = await catchError8(testSetsApi.testSetsAssignTestCases({
6194
+ id: testSet.id,
6195
+ projectId,
6196
+ requestBody: testCaseIds
6197
+ }));
6198
+ if (assignError) {
6199
+ const { message, details } = await extractErrorDetails7(assignError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
5991
6200
  OutputFormatter8.error({
5992
6201
  Result: "Failure",
5993
6202
  Message: message,
5994
6203
  Instructions: details
5995
6204
  });
5996
6205
  processContext7.exit(1);
6206
+ return;
5997
6207
  }
6208
+ OutputFormatter8.success(new SuccessOutput7("TestSetAddTestCases", {
6209
+ TestSetKey: testSetKey,
6210
+ Added: testCaseKeys.join(", "),
6211
+ Result: "Added"
6212
+ }));
5998
6213
  });
5999
6214
  testsetCmd.command("update").description("Update a test set name or description.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42)").option("--name <name>", "New test set name").option("--description <text>", "New test set description").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
6000
6215
  const ctx = await resolveCommandContext(options);
6001
6216
  if (!ctx)
6002
6217
  return;
6003
6218
  const { tmConfig, projectId } = ctx;
6004
- try {
6005
- const testSetsApi = new TestSetsApi(tmConfig);
6006
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6007
- objKey: options.testSetKey,
6008
- projectId
6219
+ const testSetsApi = new TestSetsApi(tmConfig);
6220
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6221
+ objKey: options.testSetKey,
6222
+ projectId
6223
+ }));
6224
+ if (error) {
6225
+ const { message, details } = await extractErrorDetails7(error, {
6226
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6009
6227
  });
6010
- if (!testSet.id)
6011
- throw new Error(`Test set '${options.testSetKey}' not found.`);
6012
- if (!options.name && options.description === undefined)
6013
- throw new Error("Provide at least --name or --description to update.");
6014
- await testSetsApi.testSetsUpdate({
6015
- id: testSet.id,
6016
- projectId,
6017
- uiPathTestManagementHubTestManagementAbstractionsDTOsUpdateTestSetRequest: {
6018
- name: options.name ?? testSet.name,
6019
- description: options.description ?? testSet.description
6020
- }
6228
+ OutputFormatter8.error({
6229
+ Result: "Failure",
6230
+ Message: message,
6231
+ Instructions: details
6021
6232
  });
6022
- OutputFormatter8.success(new SuccessOutput7("TestSetUpdate", {
6023
- TestSetKey: options.testSetKey,
6024
- Name: options.name ?? testSet.name ?? "",
6025
- Description: options.description ?? testSet.description ?? "",
6026
- Result: "Updated"
6027
- }));
6028
- } catch (error) {
6029
- const { message, details } = await extractErrorDetails(error);
6233
+ processContext7.exit(1);
6234
+ return;
6235
+ }
6236
+ if (!testSet.id) {
6237
+ OutputFormatter8.error({
6238
+ Result: "Failure",
6239
+ Message: `Test set '${options.testSetKey}' not found.`
6240
+ });
6241
+ processContext7.exit(1);
6242
+ return;
6243
+ }
6244
+ if (!options.name && options.description === undefined) {
6245
+ OutputFormatter8.error({
6246
+ Result: "Failure",
6247
+ Message: "Provide at least --name or --description to update."
6248
+ });
6249
+ processContext7.exit(1);
6250
+ return;
6251
+ }
6252
+ const [updateError] = await catchError8(testSetsApi.testSetsUpdate({
6253
+ id: testSet.id,
6254
+ projectId,
6255
+ uiPathTestManagementHubTestManagementAbstractionsDTOsUpdateTestSetRequest: {
6256
+ name: options.name ?? testSet.name,
6257
+ description: options.description ?? testSet.description
6258
+ }
6259
+ }));
6260
+ if (updateError) {
6261
+ const { message, details } = await extractErrorDetails7(updateError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6030
6262
  OutputFormatter8.error({
6031
6263
  Result: "Failure",
6032
6264
  Message: message,
6033
6265
  Instructions: details
6034
6266
  });
6035
6267
  processContext7.exit(1);
6268
+ return;
6036
6269
  }
6270
+ OutputFormatter8.success(new SuccessOutput7("TestSetUpdate", {
6271
+ TestSetKey: options.testSetKey,
6272
+ Name: options.name ?? testSet.name ?? "",
6273
+ Description: options.description ?? testSet.description ?? "",
6274
+ Result: "Updated"
6275
+ }));
6037
6276
  });
6038
6277
  testsetCmd.command("remove-testcases").description("Remove test cases from a test set.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42)").requiredOption("--test-case-keys <keys>", "Comma-separated test case keys to remove (e.g. DEMO:1,DEMO:2)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
6039
6278
  const ctx = await resolveCommandContext(options);
6040
6279
  if (!ctx)
6041
6280
  return;
6042
6281
  const { tmConfig, projectId } = ctx;
6043
- try {
6044
- const testSetsApi = new TestSetsApi(tmConfig);
6045
- const testCasesApi = new TestCasesApi(tmConfig);
6046
- const testSetKey = options.testSetKey;
6047
- const testCaseKeys = options.testCaseKeys.split(",").map((k) => k.trim()).filter(Boolean);
6048
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6049
- objKey: testSetKey,
6050
- projectId
6282
+ const testSetsApi = new TestSetsApi(tmConfig);
6283
+ const testCasesApi = new TestCasesApi(tmConfig);
6284
+ const testSetKey = options.testSetKey;
6285
+ const testCaseKeys = options.testCaseKeys.split(",").map((k) => k.trim()).filter(Boolean);
6286
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6287
+ objKey: testSetKey,
6288
+ projectId
6289
+ }));
6290
+ if (error) {
6291
+ const { message, details } = await extractErrorDetails7(error, {
6292
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6051
6293
  });
6052
- if (!testSet.id)
6053
- throw new Error(`Test set '${testSetKey}' not found.`);
6054
- const testCaseIds = [];
6055
- for (const tcKey of testCaseKeys) {
6056
- const page = await testCasesApi.testCasesGetTestCases({
6057
- projectId,
6058
- search: tcKey,
6059
- top: 50
6060
- });
6061
- const items = page.data ?? [];
6062
- const tc = items.find((t) => t.objKey?.toLowerCase() === tcKey.toLowerCase());
6063
- if (!tc?.id)
6064
- throw new Error(`Test case '${tcKey}' not found.`);
6065
- testCaseIds.push(tc.id);
6066
- }
6067
- await testSetsApi.testSetsUnassignTestCases({
6068
- id: testSet.id,
6069
- projectId,
6070
- testCaseIds
6294
+ OutputFormatter8.error({
6295
+ Result: "Failure",
6296
+ Message: message,
6297
+ Instructions: details
6071
6298
  });
6072
- OutputFormatter8.success(new SuccessOutput7("TestSetRemoveTestCases", {
6073
- TestSetKey: testSetKey,
6074
- Removed: testCaseKeys.join(", "),
6075
- Result: "Removed"
6299
+ processContext7.exit(1);
6300
+ return;
6301
+ }
6302
+ if (!testSet.id) {
6303
+ OutputFormatter8.error({
6304
+ Result: "Failure",
6305
+ Message: `Test set '${testSetKey}' not found.`
6306
+ });
6307
+ processContext7.exit(1);
6308
+ return;
6309
+ }
6310
+ const testCaseIds = [];
6311
+ for (const tcKey of testCaseKeys) {
6312
+ const [tcError, page] = await catchError8(testCasesApi.testCasesGetTestCases({
6313
+ projectId,
6314
+ search: tcKey,
6315
+ top: 50
6076
6316
  }));
6077
- } catch (error) {
6078
- const { message, details } = await extractErrorDetails(error);
6317
+ if (tcError) {
6318
+ const { message, details } = await extractErrorDetails7(tcError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6319
+ OutputFormatter8.error({
6320
+ Result: "Failure",
6321
+ Message: message,
6322
+ Instructions: details
6323
+ });
6324
+ processContext7.exit(1);
6325
+ return;
6326
+ }
6327
+ const items = page.data ?? [];
6328
+ const tc = items.find((t) => t.objKey?.toLowerCase() === tcKey.toLowerCase());
6329
+ if (!tc?.id) {
6330
+ OutputFormatter8.error({
6331
+ Result: "Failure",
6332
+ Message: `Test case '${tcKey}' not found.`
6333
+ });
6334
+ processContext7.exit(1);
6335
+ return;
6336
+ }
6337
+ testCaseIds.push(tc.id);
6338
+ }
6339
+ const [unassignError] = await catchError8(testSetsApi.testSetsUnassignTestCases({
6340
+ id: testSet.id,
6341
+ projectId,
6342
+ testCaseIds
6343
+ }));
6344
+ if (unassignError) {
6345
+ const { message, details } = await extractErrorDetails7(unassignError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6079
6346
  OutputFormatter8.error({
6080
6347
  Result: "Failure",
6081
6348
  Message: message,
6082
6349
  Instructions: details
6083
6350
  });
6084
6351
  processContext7.exit(1);
6352
+ return;
6085
6353
  }
6354
+ OutputFormatter8.success(new SuccessOutput7("TestSetRemoveTestCases", {
6355
+ TestSetKey: testSetKey,
6356
+ Removed: testCaseKeys.join(", "),
6357
+ Result: "Removed"
6358
+ }));
6086
6359
  });
6087
6360
  testsetCmd.command("list-testcases").description("List test cases assigned to a test set.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42)").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
6088
6361
  const ctx = await resolveCommandContext(options);
6089
6362
  if (!ctx)
6090
6363
  return;
6091
6364
  const { tmConfig, projectId } = ctx;
6092
- try {
6093
- const testSetsApi = new TestSetsApi(tmConfig);
6094
- const testCasesApi = new TestCasesApi(tmConfig);
6095
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6096
- objKey: options.testSetKey,
6097
- projectId
6365
+ const testSetsApi = new TestSetsApi(tmConfig);
6366
+ const testCasesApi = new TestCasesApi(tmConfig);
6367
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6368
+ objKey: options.testSetKey,
6369
+ projectId
6370
+ }));
6371
+ if (error) {
6372
+ const { message, details } = await extractErrorDetails7(error, {
6373
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6098
6374
  });
6099
- if (!testSet.id)
6100
- throw new Error(`Test set '${options.testSetKey}' not found.`);
6101
- const ids = await testSetsApi.testSetsGetAssignedTestCaseIds({
6102
- id: testSet.id,
6103
- projectId
6375
+ OutputFormatter8.error({
6376
+ Result: "Failure",
6377
+ Message: message,
6378
+ Instructions: details
6104
6379
  });
6105
- if (ids.length === 0) {
6106
- OutputFormatter8.success(new SuccessOutput7("TestSetTestCasesList", []));
6107
- return;
6108
- }
6109
- const testCases = await testCasesApi.testCasesBatch({
6110
- projectId,
6111
- ids
6380
+ processContext7.exit(1);
6381
+ return;
6382
+ }
6383
+ if (!testSet.id) {
6384
+ OutputFormatter8.error({
6385
+ Result: "Failure",
6386
+ Message: `Test set '${options.testSetKey}' not found.`
6112
6387
  });
6113
- const rows = testCases.map((tc) => ({
6114
- TestCaseKey: tc.objKey ?? "",
6115
- Name: tc.name ?? "",
6116
- Version: tc.version ?? "",
6117
- Description: tc.description ?? ""
6118
- }));
6119
- OutputFormatter8.success(new SuccessOutput7("TestSetTestCasesList", rows));
6120
- } catch (error) {
6121
- const { message, details } = await extractErrorDetails(error);
6388
+ processContext7.exit(1);
6389
+ return;
6390
+ }
6391
+ const [idsError, ids] = await catchError8(testSetsApi.testSetsGetAssignedTestCaseIds({
6392
+ id: testSet.id,
6393
+ projectId
6394
+ }));
6395
+ if (idsError) {
6396
+ const { message, details } = await extractErrorDetails7(idsError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6397
+ OutputFormatter8.error({
6398
+ Result: "Failure",
6399
+ Message: message,
6400
+ Instructions: details
6401
+ });
6402
+ processContext7.exit(1);
6403
+ return;
6404
+ }
6405
+ if (ids.length === 0) {
6406
+ OutputFormatter8.success(new SuccessOutput7("TestSetTestCasesList", []));
6407
+ return;
6408
+ }
6409
+ const [batchError, testCases] = await catchError8(testCasesApi.testCasesBatch({
6410
+ projectId,
6411
+ ids
6412
+ }));
6413
+ if (batchError) {
6414
+ const { message, details } = await extractErrorDetails7(batchError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6122
6415
  OutputFormatter8.error({
6123
6416
  Result: "Failure",
6124
6417
  Message: message,
6125
6418
  Instructions: details
6126
6419
  });
6127
6420
  processContext7.exit(1);
6421
+ return;
6128
6422
  }
6423
+ const rows = testCases.map((tc) => ({
6424
+ TestCaseKey: tc.objKey ?? "",
6425
+ Name: tc.name ?? "",
6426
+ Version: tc.version ?? "",
6427
+ Description: tc.description ?? ""
6428
+ }));
6429
+ OutputFormatter8.success(new SuccessOutput7("TestSetTestCasesList", rows));
6129
6430
  });
6130
6431
  testsetCmd.command("execute").description("Execute a test set and return the execution ID.").requiredOption("--test-set-key <key>", "Test set object key (e.g. DEMO:42). The project key is derived from the prefix (e.g. DEMO).").option("--execution-type <type>", [
6131
6432
  "Type of test cases to execute.",
@@ -6139,73 +6440,97 @@ var registerTestsetCommand = (program) => {
6139
6440
  if (!ctx)
6140
6441
  return;
6141
6442
  const { tmConfig, projectId } = ctx;
6142
- try {
6143
- const testSetKey = options.testSetKey;
6144
- const testSetsApi = new TestSetsApi(tmConfig);
6145
- logger6.info(`Resolving test set '${testSetKey}'`);
6146
- const testSet = await testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6147
- objKey: testSetKey,
6148
- projectId
6443
+ const testSetKey = options.testSetKey;
6444
+ const testSetsApi = new TestSetsApi(tmConfig);
6445
+ logger6.info(`Resolving test set '${testSetKey}'`);
6446
+ const [error, testSet] = await catchError8(testSetsApi.testSetsGetTestSetByObjKeyAndProjectId({
6447
+ objKey: testSetKey,
6448
+ projectId
6449
+ }));
6450
+ if (error) {
6451
+ const { message, details } = await extractErrorDetails7(error, {
6452
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6453
+ });
6454
+ OutputFormatter8.error({
6455
+ Result: "Failure",
6456
+ Message: message,
6457
+ Instructions: details
6458
+ });
6459
+ processContext7.exit(1);
6460
+ return;
6461
+ }
6462
+ if (!testSet.id) {
6463
+ OutputFormatter8.error({
6464
+ Result: "Failure",
6465
+ Message: `Test set '${testSetKey}' not found.`
6149
6466
  });
6150
- if (!testSet.id) {
6467
+ processContext7.exit(1);
6468
+ return;
6469
+ }
6470
+ if (options.inputPath) {
6471
+ const [overrideError] = await catchError8(overrideTestSetParameters(tmConfig, projectId, testSet.id, options.inputPath));
6472
+ if (overrideError) {
6473
+ const { message, details } = await extractErrorDetails7(overrideError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6151
6474
  OutputFormatter8.error({
6152
6475
  Result: "Failure",
6153
- Message: `Test set '${testSetKey}' not found.`
6476
+ Message: message,
6477
+ Instructions: details
6154
6478
  });
6155
6479
  processContext7.exit(1);
6156
6480
  return;
6157
6481
  }
6158
- if (options.inputPath) {
6159
- await overrideTestSetParameters(tmConfig, projectId, testSet.id, options.inputPath);
6160
- }
6161
- logger6.info(`Starting execution for test set '${testSetKey}' (${testSet.id})`);
6162
- const execution = await testSetsApi.testSetsStartExecute({
6163
- id: testSet.id,
6164
- projectId,
6165
- executionType: options.executionType
6166
- });
6167
- OutputFormatter8.success(new SuccessOutput7("TestSetExecute", {
6168
- ExecutionId: execution.id ?? "",
6169
- TestSetKey: testSetKey,
6170
- Status: execution.status ?? "Running",
6171
- StartTime: execution.created?.toISOString() ?? ""
6172
- }));
6173
- } catch (error) {
6174
- const { message, details } = await extractErrorDetails(error);
6482
+ }
6483
+ logger6.info(`Starting execution for test set '${testSetKey}' (${testSet.id})`);
6484
+ const [execError, execution] = await catchError8(testSetsApi.testSetsStartExecute({
6485
+ id: testSet.id,
6486
+ projectId,
6487
+ executionType: options.executionType
6488
+ }));
6489
+ if (execError) {
6490
+ const { message, details } = await extractErrorDetails7(execError, { forbiddenMessage: TM_FORBIDDEN_MESSAGE });
6175
6491
  OutputFormatter8.error({
6176
6492
  Result: "Failure",
6177
6493
  Message: message,
6178
6494
  Instructions: details
6179
6495
  });
6180
6496
  processContext7.exit(1);
6497
+ return;
6181
6498
  }
6499
+ OutputFormatter8.success(new SuccessOutput7("TestSetExecute", {
6500
+ ExecutionId: execution.id ?? "",
6501
+ TestSetKey: testSetKey,
6502
+ Status: execution.status ?? "Running",
6503
+ StartTime: execution.created?.toISOString() ?? ""
6504
+ }));
6182
6505
  });
6183
6506
  testsetCmd.command("list").description("List test sets in a Test Manager project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. DEMO)").option("--folder-key <uuid>", "Filter by Orchestrator folder key (UUID, from 'or folders list')").option("--filter <text>", "Filter test sets by name").option("-t, --tenant <name>", "Tenant name (defaults to authenticated tenant)").option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").trackedAction(processContext7, async (options) => {
6184
6507
  const ctx = await resolveCommandContext(options);
6185
6508
  if (!ctx)
6186
6509
  return;
6187
6510
  const { tmConfig, projectId } = ctx;
6188
- try {
6189
- const folderKey = options.folderKey;
6190
- const testSetsApi = new TestSetsApi(tmConfig);
6191
- logger6.info("Fetching test sets");
6192
- const allTestSets = await fetchAllTestSets(testSetsApi, projectId, options.filter);
6193
- const filtered = folderKey ? allTestSets.filter((ts) => ts.folderKey === folderKey) : allTestSets;
6194
- const rows = filtered.map((ts) => ({
6195
- TestSetKey: ts.objKey ?? "",
6196
- Name: ts.name ?? "",
6197
- FolderKey: ts.folderKey ?? ""
6198
- }));
6199
- OutputFormatter8.success(new SuccessOutput7("TestSetsList", rows));
6200
- } catch (error) {
6201
- const { message, details } = await extractErrorDetails(error);
6511
+ const folderKey = options.folderKey;
6512
+ const testSetsApi = new TestSetsApi(tmConfig);
6513
+ logger6.info("Fetching test sets");
6514
+ const [error, allTestSets] = await catchError8(fetchAllTestSets(testSetsApi, projectId, options.filter));
6515
+ if (error) {
6516
+ const { message, details } = await extractErrorDetails7(error, {
6517
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6518
+ });
6202
6519
  OutputFormatter8.error({
6203
6520
  Result: "Failure",
6204
6521
  Message: message,
6205
6522
  Instructions: details
6206
6523
  });
6207
6524
  processContext7.exit(1);
6525
+ return;
6208
6526
  }
6527
+ const filtered = folderKey ? allTestSets.filter((ts) => ts.folderKey === folderKey) : allTestSets;
6528
+ const rows = filtered.map((ts) => ({
6529
+ TestSetKey: ts.objKey ?? "",
6530
+ Name: ts.name ?? "",
6531
+ FolderKey: ts.folderKey ?? ""
6532
+ }));
6533
+ OutputFormatter8.success(new SuccessOutput7("TestSetsList", rows));
6209
6534
  });
6210
6535
  };
6211
6536
  async function fetchAllTestSets(api, projectId, filter) {
@@ -6222,7 +6547,8 @@ async function fetchAllTestSets(api, projectId, filter) {
6222
6547
  });
6223
6548
  const items = page.data ?? [];
6224
6549
  all.push(...items);
6225
- const total = page.paging?.total ?? items.length;
6550
+ const paging = page.paging;
6551
+ const total = paging?.total ?? items.length;
6226
6552
  skip += top;
6227
6553
  if (skip >= total || items.length < top)
6228
6554
  break;
@@ -6262,8 +6588,10 @@ async function overrideTestSetParameters(tmConfig, projectId, testSetId, inputPa
6262
6588
 
6263
6589
  // src/commands/wait.ts
6264
6590
  import {
6265
- logger as logger7,
6591
+ extractErrorDetails as extractErrorDetails8,
6266
6592
  OutputFormatter as OutputFormatter9,
6593
+ PollOutcome,
6594
+ pollUntil,
6267
6595
  processContext as processContext8,
6268
6596
  SuccessOutput as SuccessOutput8
6269
6597
  } from "@uipath/common";
@@ -6278,57 +6606,56 @@ var registerWaitCommand = (program) => {
6278
6606
  const executionsApi = new TestExecutionsApi(tmConfig);
6279
6607
  const executionId = options.executionId;
6280
6608
  const timeoutMs = Number(options.timeout) * 1000;
6281
- const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : null;
6282
- const startedAt = Date.now();
6283
- let lastLogAt = 0;
6284
- let consecutiveErrors = 0;
6285
- const MAX_CONSECUTIVE_ERRORS = 3;
6286
- while (true) {
6287
- let stats;
6288
- try {
6289
- stats = await executionsApi.testExecutionsGetByIdWithStats({
6290
- id: executionId,
6291
- projectId
6292
- });
6293
- consecutiveErrors = 0;
6294
- } catch (pollError) {
6295
- consecutiveErrors++;
6296
- const msg = pollError instanceof Error ? pollError.message : String(pollError);
6297
- logger7.warn(`[wait] poll error (${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS}): ${msg}`);
6298
- if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS)
6299
- throw pollError;
6300
- await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
6301
- continue;
6302
- }
6609
+ const result = await pollUntil({
6610
+ fn: () => executionsApi.testExecutionsGetByIdWithStats({
6611
+ id: executionId,
6612
+ projectId
6613
+ }),
6614
+ until: (stats) => TERMINAL_STATUSES.has((stats.status ?? "pending").toLowerCase()),
6615
+ getStatus: (stats) => stats.status ?? "pending",
6616
+ label: `execution ${executionId}`,
6617
+ logPrefix: "wait",
6618
+ intervalMs: POLL_INTERVAL_MS,
6619
+ timeoutMs,
6620
+ logIntervalMs: POLL_INTERVAL_MS,
6621
+ maxConsecutiveErrors: 3,
6622
+ signal: processContext8.pollSignal
6623
+ });
6624
+ if (result.outcome === PollOutcome.Completed && result.data) {
6625
+ const stats = result.data;
6303
6626
  const status = stats.status ?? "pending";
6304
- const elapsedMs = Date.now() - startedAt;
6305
- if (elapsedMs - lastLogAt >= 60000) {
6306
- logger7.info(`[wait] execution ${executionId} — status: ${status}, elapsed: ${msToDuration(elapsedMs)}`);
6307
- lastLogAt = elapsedMs;
6308
- }
6309
- if (TERMINAL_STATUSES.has(status.toLowerCase())) {
6310
- const endTime = stats.executionFinished?.toISOString() ?? new Date().toISOString();
6311
- const durationMs = stats.duration ?? 0;
6312
- OutputFormatter9.success(new SuccessOutput8("WaitComplete", {
6313
- ExecutionId: executionId,
6314
- Status: status,
6315
- EndTime: endTime,
6316
- Duration: msToDuration(durationMs)
6317
- }));
6318
- return;
6319
- }
6320
- if (deadline !== null && Date.now() + POLL_INTERVAL_MS > deadline) {
6321
- OutputFormatter9.error({
6322
- Result: "Failure",
6323
- Message: `Timed out after ${options.timeout}s waiting for execution '${executionId}'. Last status: ${status}.`
6324
- });
6325
- processContext8.exit(1);
6326
- return;
6327
- }
6328
- await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
6627
+ const endTime = stats.executionFinished?.toISOString() ?? new Date().toISOString();
6628
+ const durationMs = stats.duration ?? 0;
6629
+ OutputFormatter9.success(new SuccessOutput8("WaitComplete", {
6630
+ ExecutionId: executionId,
6631
+ Status: status,
6632
+ EndTime: endTime,
6633
+ Duration: msToDuration(durationMs)
6634
+ }));
6635
+ return;
6329
6636
  }
6637
+ const lastStatus = result.data?.status ?? "unknown";
6638
+ const EXIT_CODES = {
6639
+ [PollOutcome.Timeout]: 2,
6640
+ [PollOutcome.Failed]: 1,
6641
+ [PollOutcome.Interrupted]: 1,
6642
+ [PollOutcome.Aborted]: 1
6643
+ };
6644
+ const messages = {
6645
+ [PollOutcome.Timeout]: `Timed out after ${options.timeout}s waiting for execution '${executionId}'. Last status: ${lastStatus}.`,
6646
+ [PollOutcome.Failed]: `Polling failed for execution '${executionId}': ${result.error?.message ?? "too many consecutive errors"}`,
6647
+ [PollOutcome.Interrupted]: `Polling interrupted for execution '${executionId}'.`,
6648
+ [PollOutcome.Aborted]: `Polling aborted for execution '${executionId}'.`
6649
+ };
6650
+ OutputFormatter9.error({
6651
+ Result: "Failure",
6652
+ Message: messages[result.outcome] ?? `Polling failed for execution '${executionId}'.`
6653
+ });
6654
+ processContext8.exit(EXIT_CODES[result.outcome] ?? 1);
6330
6655
  } catch (error) {
6331
- const { message, details } = await extractErrorDetails(error);
6656
+ const { message, details } = await extractErrorDetails8(error, {
6657
+ forbiddenMessage: TM_FORBIDDEN_MESSAGE
6658
+ });
6332
6659
  OutputFormatter9.error({
6333
6660
  Result: "Failure",
6334
6661
  Message: message,
@@ -6346,7 +6673,7 @@ var metadata = {
6346
6673
  description: "Manage test cases, test sets, executions, and results.",
6347
6674
  commandPrefix: "tm"
6348
6675
  };
6349
- var registerCommands = (program) => {
6676
+ var registerCommands = async (program) => {
6350
6677
  registerAttachmentCommand(program);
6351
6678
  registerProjectCommand(program);
6352
6679
  registerExecutionCommand(program);