@uipath/test-manager-tool 1.202.0-preview.136 → 1.202.0-preview.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.js +1 -1
- package/dist/{tool-ff6s9vph.js → tool-vg7ewhsa.js} +388 -52
- package/dist/tool.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -91,6 +91,7 @@ Success responses: `{ "Result": "Success", "Code": "...", "Data": ... }`. Errors
|
|
|
91
91
|
| `uip tm testcases add` | Add test cases to a test set. |
|
|
92
92
|
| `uip tm testcases remove` | Remove test cases from a test set. |
|
|
93
93
|
| `uip tm testcases link-automation` | Link an Orchestrator package automation to a test case. |
|
|
94
|
+
| `uip tm testcases link-package` | Create and link a test case for every test in an Orchestrator package, in one call. |
|
|
94
95
|
| `uip tm testcases unlink-automation` | Unlink the automation from a test case. |
|
|
95
96
|
| `uip tm testcases list-automations` | List test entry points available in an Orchestrator folder. |
|
|
96
97
|
| `uip tm testcases list-result-history` | List result history for a specific test case. |
|
package/dist/index.js
CHANGED
|
@@ -11179,7 +11179,7 @@ var require_lib3 = __commonJS(function(exports, module) {
|
|
|
11179
11179
|
var package_default = {
|
|
11180
11180
|
name: "@uipath/test-manager-tool",
|
|
11181
11181
|
license: "MIT",
|
|
11182
|
-
version: "1.202.0-preview.
|
|
11182
|
+
version: "1.202.0-preview.137",
|
|
11183
11183
|
description: "Manage test cases, test sets, executions, and results.",
|
|
11184
11184
|
private: false,
|
|
11185
11185
|
repository: {
|
|
@@ -13527,6 +13527,14 @@ var RETRY_HINTS = [
|
|
|
13527
13527
|
"RetryAfter30Seconds",
|
|
13528
13528
|
"RetryAfter60Seconds"
|
|
13529
13529
|
];
|
|
13530
|
+
var CLI_ERROR_CODE_VALUES = new Set(CLI_ERROR_CODES);
|
|
13531
|
+
var RETRY_HINT_VALUES = new Set(RETRY_HINTS);
|
|
13532
|
+
function isCliErrorCode(value) {
|
|
13533
|
+
return typeof value === "string" && CLI_ERROR_CODE_VALUES.has(value);
|
|
13534
|
+
}
|
|
13535
|
+
function isRetryHint(value) {
|
|
13536
|
+
return typeof value === "string" && RETRY_HINT_VALUES.has(value);
|
|
13537
|
+
}
|
|
13530
13538
|
var RESULTS = {
|
|
13531
13539
|
Success: "Success",
|
|
13532
13540
|
Failure: "Failure",
|
|
@@ -14346,8 +14354,6 @@ function emitInvocationRequest(name, success, properties) {
|
|
|
14346
14354
|
|
|
14347
14355
|
// ../common/src/trackedAction.ts
|
|
14348
14356
|
var pollSignalSlot = singleton("PollSignal");
|
|
14349
|
-
var cliErrorCodeValues = new Set(CLI_ERROR_CODES);
|
|
14350
|
-
var retryHintValues = new Set(RETRY_HINTS);
|
|
14351
14357
|
var TELEMETRY_COMMAND_ARG_PREFIX = "uip.cmd.arg.";
|
|
14352
14358
|
var processContext = {
|
|
14353
14359
|
exit: (code) => {
|
|
@@ -14435,12 +14441,6 @@ function deriveCommandPath(cmd) {
|
|
|
14435
14441
|
}
|
|
14436
14442
|
return commandTelemetryName(parts);
|
|
14437
14443
|
}
|
|
14438
|
-
function isCliErrorCode(value) {
|
|
14439
|
-
return typeof value === "string" && cliErrorCodeValues.has(value);
|
|
14440
|
-
}
|
|
14441
|
-
function isRetryHint(value) {
|
|
14442
|
-
return typeof value === "string" && retryHintValues.has(value);
|
|
14443
|
-
}
|
|
14444
14444
|
function isErrorContext(value) {
|
|
14445
14445
|
return value !== null && typeof value === "object";
|
|
14446
14446
|
}
|
|
@@ -14833,6 +14833,11 @@ function instructionsFor(ctx, err) {
|
|
|
14833
14833
|
}
|
|
14834
14834
|
}
|
|
14835
14835
|
}
|
|
14836
|
+
// ../common/src/guid.ts
|
|
14837
|
+
var GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14838
|
+
function isGuid(value) {
|
|
14839
|
+
return GUID_REGEX.test(value);
|
|
14840
|
+
}
|
|
14836
14841
|
// ../common/src/host-global-options.ts
|
|
14837
14842
|
var HOST_GLOBAL_OPTIONS_WITH_VALUE = [
|
|
14838
14843
|
"--output",
|
|
@@ -23461,6 +23466,7 @@ function msToDuration2(ms) {
|
|
|
23461
23466
|
function calcPassRate(passed, total) {
|
|
23462
23467
|
return total > 0 ? Math.round(passed / total * 1000) / 10 : 0;
|
|
23463
23468
|
}
|
|
23469
|
+
var DEFAULT_TEST_CASE_VERSION = "1.0.0";
|
|
23464
23470
|
var TM_FORBIDDEN_MESSAGE = "Forbidden (403). Ensure the account has the required Test Manager permissions (TestExecution.Read, TestSet.Read, etc.).";
|
|
23465
23471
|
var TM_LICENSED_USER_FORBIDDEN_MESSAGE = "Forbidden (403). This operation requires a Test Manager license. Contact your tenant admin to assign a license, or use a read-only command.";
|
|
23466
23472
|
var TM_NOT_AVAILABLE_MESSAGE = "Test Manager is not enabled for this tenant.";
|
|
@@ -35860,6 +35866,189 @@ async function findTestCasesByLabels(testCasesApi, projectId, labels, maxMatches
|
|
|
35860
35866
|
}
|
|
35861
35867
|
}
|
|
35862
35868
|
|
|
35869
|
+
// src/utils/package-automation.ts
|
|
35870
|
+
function instructiveError(message, instructions, errorCode2, retry = "RetryWillNotFix") {
|
|
35871
|
+
const error = new Error(message);
|
|
35872
|
+
error.instructions = instructions;
|
|
35873
|
+
error.errorCode = errorCode2;
|
|
35874
|
+
error.retry = retry;
|
|
35875
|
+
return error;
|
|
35876
|
+
}
|
|
35877
|
+
function readInstructions(error) {
|
|
35878
|
+
const candidate = error;
|
|
35879
|
+
return typeof candidate?.instructions === "string" ? candidate.instructions : undefined;
|
|
35880
|
+
}
|
|
35881
|
+
function readClassification(error) {
|
|
35882
|
+
const candidate = error;
|
|
35883
|
+
return {
|
|
35884
|
+
errorCode: isCliErrorCode(candidate?.errorCode) ? candidate.errorCode : undefined,
|
|
35885
|
+
retry: isRetryHint(candidate?.retry) ? candidate.retry : undefined
|
|
35886
|
+
};
|
|
35887
|
+
}
|
|
35888
|
+
var ENTRY_POINT_PAGE_SIZE = 100;
|
|
35889
|
+
var ENTRY_POINT_MAX_PAGES = 50;
|
|
35890
|
+
async function resolveAutomationFolder(folderKey, tenant) {
|
|
35891
|
+
if (!isGuid(folderKey)) {
|
|
35892
|
+
throw instructiveError(`Folder key '${folderKey}' is not a UUID.`, "Pass the folder's Key from 'uip or folders list'.", "invalid_argument");
|
|
35893
|
+
}
|
|
35894
|
+
const foldersApi = await createApiClient(FoldersApi, { tenant });
|
|
35895
|
+
const result = await foldersApi.foldersGet({
|
|
35896
|
+
$filter: `Key eq ${folderKey}`,
|
|
35897
|
+
$top: 1
|
|
35898
|
+
});
|
|
35899
|
+
const folder = result.value?.[0];
|
|
35900
|
+
if (!folder?.displayName) {
|
|
35901
|
+
throw instructiveError(`Folder with key '${folderKey}' not found.`, "List the folders you can see with 'uip or folders list' and pass one of their Key values.", "not_found");
|
|
35902
|
+
}
|
|
35903
|
+
return {
|
|
35904
|
+
displayName: folder.displayName,
|
|
35905
|
+
linkFolderKey: folder.feedType === FolderDtoFeedTypeEnum.Processes ? null : folderKey
|
|
35906
|
+
};
|
|
35907
|
+
}
|
|
35908
|
+
function readEntryPointPage(response) {
|
|
35909
|
+
if (Array.isArray(response)) {
|
|
35910
|
+
return { items: response };
|
|
35911
|
+
}
|
|
35912
|
+
const record = response ?? {};
|
|
35913
|
+
const items = record.data ?? [];
|
|
35914
|
+
const paging = record.paging;
|
|
35915
|
+
const total = paging?.total ?? record.total;
|
|
35916
|
+
return { items, total };
|
|
35917
|
+
}
|
|
35918
|
+
function matchesPackageName(entryPoint, packageName) {
|
|
35919
|
+
return (entryPoint.packageName ?? "").toLowerCase() === packageName.toLowerCase();
|
|
35920
|
+
}
|
|
35921
|
+
async function fetchPackageEntryPoints(orchestratorApi, projectId, folderKey, search = "") {
|
|
35922
|
+
const all = [];
|
|
35923
|
+
for (let page = 0;; page++) {
|
|
35924
|
+
if (page >= ENTRY_POINT_MAX_PAGES) {
|
|
35925
|
+
throw instructiveError(`Folder exposes more than ${ENTRY_POINT_MAX_PAGES * ENTRY_POINT_PAGE_SIZE} test entry points.`, "Narrow the selection with --package-name or --test-name.", "invalid_argument");
|
|
35926
|
+
}
|
|
35927
|
+
const response = await orchestratorApi.orchestratorGetUniquePackageEntryPoints(toGetPackageEntryPointsRequest(projectId, folderKey ?? null, true, search, ENTRY_POINT_PAGE_SIZE, page * ENTRY_POINT_PAGE_SIZE));
|
|
35928
|
+
const { items, total } = readEntryPointPage(response);
|
|
35929
|
+
all.push(...items);
|
|
35930
|
+
if (all.length >= (total ?? all.length) || items.length < ENTRY_POINT_PAGE_SIZE) {
|
|
35931
|
+
break;
|
|
35932
|
+
}
|
|
35933
|
+
}
|
|
35934
|
+
return all;
|
|
35935
|
+
}
|
|
35936
|
+
var TEST_CASE_PAGE_SIZE = 200;
|
|
35937
|
+
var TEST_CASE_MAX_PAGES = 50;
|
|
35938
|
+
async function fetchTestCasesByName(testCasesApi, projectId) {
|
|
35939
|
+
const byName = new Map;
|
|
35940
|
+
for (let page = 0;; page++) {
|
|
35941
|
+
if (page >= TEST_CASE_MAX_PAGES) {
|
|
35942
|
+
throw instructiveError(`Project holds more than ${TEST_CASE_MAX_PAGES * TEST_CASE_PAGE_SIZE} test cases — too many to index for automation linking.`, "Link the automations from a smaller Test Manager project, or use 'uip tm testcases link-automation' per test.", "invalid_argument");
|
|
35943
|
+
}
|
|
35944
|
+
const response = await testCasesApi.testCasesGetTestCases({
|
|
35945
|
+
projectId,
|
|
35946
|
+
top: TEST_CASE_PAGE_SIZE,
|
|
35947
|
+
skip: page * TEST_CASE_PAGE_SIZE,
|
|
35948
|
+
orderby: "name asc"
|
|
35949
|
+
});
|
|
35950
|
+
const items = response.data ?? [];
|
|
35951
|
+
for (const testCase of items) {
|
|
35952
|
+
const key = (testCase.name ?? "").toLowerCase();
|
|
35953
|
+
if (!key || byName.has(key))
|
|
35954
|
+
continue;
|
|
35955
|
+
byName.set(key, {
|
|
35956
|
+
id: testCase.id ?? "",
|
|
35957
|
+
objKey: testCase.objKey ?? ""
|
|
35958
|
+
});
|
|
35959
|
+
}
|
|
35960
|
+
const total = response.paging?.total ?? byName.size;
|
|
35961
|
+
if ((page + 1) * TEST_CASE_PAGE_SIZE >= total || items.length < TEST_CASE_PAGE_SIZE) {
|
|
35962
|
+
break;
|
|
35963
|
+
}
|
|
35964
|
+
}
|
|
35965
|
+
return byName;
|
|
35966
|
+
}
|
|
35967
|
+
async function linkPackageEntryPoints(testCasesApi, input) {
|
|
35968
|
+
const { projectId, entryPoints, folder, dryRun: dryRun2 } = input;
|
|
35969
|
+
assertDistinctEntryPointNames(entryPoints);
|
|
35970
|
+
const byName = await fetchTestCasesByName(testCasesApi, projectId);
|
|
35971
|
+
const rows = [];
|
|
35972
|
+
for (const entryPoint of entryPoints) {
|
|
35973
|
+
const testName = entryPoint.name ?? "";
|
|
35974
|
+
const existing = byName.get(testName.toLowerCase());
|
|
35975
|
+
if (dryRun2) {
|
|
35976
|
+
rows.push(toRow(entryPoint, existing, existing ? "WouldReuse" : "WouldCreate"));
|
|
35977
|
+
continue;
|
|
35978
|
+
}
|
|
35979
|
+
const [failure, linked] = await catchError(createAndLink(testCasesApi, {
|
|
35980
|
+
projectId,
|
|
35981
|
+
entryPoint,
|
|
35982
|
+
existing,
|
|
35983
|
+
folder
|
|
35984
|
+
}));
|
|
35985
|
+
if (failure) {
|
|
35986
|
+
throw wrapLinkFailure(failure, testName, rows.length, entryPoints.length);
|
|
35987
|
+
}
|
|
35988
|
+
byName.set(testName.toLowerCase(), linked.testCase);
|
|
35989
|
+
rows.push(toRow(entryPoint, linked.testCase, linked.action));
|
|
35990
|
+
}
|
|
35991
|
+
return rows;
|
|
35992
|
+
}
|
|
35993
|
+
function wrapLinkFailure(failure, testName, done, total) {
|
|
35994
|
+
const original = failure;
|
|
35995
|
+
const wrapped = new Error(`Linked ${done} of ${total} tests, then failed on '${testName}': ${failure.message}`, { cause: failure });
|
|
35996
|
+
if (original.status !== undefined)
|
|
35997
|
+
wrapped.status = original.status;
|
|
35998
|
+
if (original.response !== undefined)
|
|
35999
|
+
wrapped.response = original.response;
|
|
36000
|
+
wrapped.instructions = "Run the same command again — test cases that already exist are reused, so it picks up where it stopped.";
|
|
36001
|
+
return wrapped;
|
|
36002
|
+
}
|
|
36003
|
+
function toRow(entryPoint, testCase, action) {
|
|
36004
|
+
return {
|
|
36005
|
+
TestName: entryPoint.name ?? "",
|
|
36006
|
+
PackageName: entryPoint.packageName ?? "",
|
|
36007
|
+
PackageVersion: entryPoint.packageAppVersion ?? "",
|
|
36008
|
+
TestCaseKey: testCase?.objKey ?? "",
|
|
36009
|
+
TestCaseId: testCase?.id ?? "",
|
|
36010
|
+
Action: action
|
|
36011
|
+
};
|
|
36012
|
+
}
|
|
36013
|
+
function assertDistinctEntryPointNames(entryPoints) {
|
|
36014
|
+
const seen = new Set;
|
|
36015
|
+
const collisions = new Set;
|
|
36016
|
+
for (const entryPoint of entryPoints) {
|
|
36017
|
+
const key = (entryPoint.name ?? "").toLowerCase();
|
|
36018
|
+
if (seen.has(key))
|
|
36019
|
+
collisions.add(entryPoint.name ?? "");
|
|
36020
|
+
seen.add(key);
|
|
36021
|
+
}
|
|
36022
|
+
if (collisions.size > 0) {
|
|
36023
|
+
throw instructiveError(`Test names appear in more than one package: ${[...collisions].join(", ")}. A test case can hold one automation, so linking both would overwrite the first.`, "Pass --package-name to pick which package's tests to link, or --test-name to link the ones that do not collide.", "invalid_argument");
|
|
36024
|
+
}
|
|
36025
|
+
}
|
|
36026
|
+
async function createAndLink(testCasesApi, input) {
|
|
36027
|
+
const { projectId, entryPoint, existing, folder } = input;
|
|
36028
|
+
const testName = entryPoint.name ?? "";
|
|
36029
|
+
let testCase = existing;
|
|
36030
|
+
if (!testCase) {
|
|
36031
|
+
const created = await testCasesApi.testCasesCreate({
|
|
36032
|
+
projectId,
|
|
36033
|
+
uiPathTestManagementHubTestManagementAbstractionsDTOsCreateTestCaseRequest: {
|
|
36034
|
+
name: testName,
|
|
36035
|
+
description: "",
|
|
36036
|
+
projectId,
|
|
36037
|
+
version: DEFAULT_TEST_CASE_VERSION
|
|
36038
|
+
}
|
|
36039
|
+
});
|
|
36040
|
+
testCase = { id: created.id ?? "", objKey: created.objKey ?? "" };
|
|
36041
|
+
}
|
|
36042
|
+
await testCasesApi.testCasesUpdateTestCasePackageAutomation(toUpdatePackageAutomationRequest(testCase.id, projectId, {
|
|
36043
|
+
packageEntryPointUniqueId: entryPoint.packageEntryPointId ?? null,
|
|
36044
|
+
packageIdentifier: entryPoint.packageName ?? null,
|
|
36045
|
+
packageEntryPointName: testName,
|
|
36046
|
+
folderKey: folder.linkFolderKey,
|
|
36047
|
+
packageSourceName: folder.displayName
|
|
36048
|
+
}));
|
|
36049
|
+
return { testCase, action: existing ? "Reused" : "Created" };
|
|
36050
|
+
}
|
|
36051
|
+
|
|
35863
36052
|
// src/utils/step-input.ts
|
|
35864
36053
|
function hasScalarStep(options) {
|
|
35865
36054
|
return options.description !== undefined || options.expectedResult !== undefined || options.actionType !== undefined || options.clipboardData !== undefined || options.orderNo !== undefined;
|
|
@@ -36060,6 +36249,67 @@ var TESTCASE_LINK_AUTOMATION_EXAMPLES = [
|
|
|
36060
36249
|
}
|
|
36061
36250
|
}
|
|
36062
36251
|
];
|
|
36252
|
+
var TESTCASE_LINK_PACKAGE_EXAMPLES = [
|
|
36253
|
+
{
|
|
36254
|
+
Description: "Create and link a test case for every test in one Orchestrator package",
|
|
36255
|
+
Command: "uip tm testcases link-package --project-key DEMO --folder-key f0f0f0f0-0000-0000-0000-000000000001 --package-name InvoiceTests",
|
|
36256
|
+
Output: {
|
|
36257
|
+
Code: "TestCaseLinkPackage",
|
|
36258
|
+
Data: [
|
|
36259
|
+
{
|
|
36260
|
+
TestName: "SmokeTest",
|
|
36261
|
+
PackageName: "InvoiceTests",
|
|
36262
|
+
PackageVersion: "1.0.2",
|
|
36263
|
+
TestCaseKey: "DEMO:7",
|
|
36264
|
+
TestCaseId: "a1b2c3d4-0000-0000-0000-000000000007",
|
|
36265
|
+
Action: "Created"
|
|
36266
|
+
},
|
|
36267
|
+
{
|
|
36268
|
+
TestName: "RegressionTest",
|
|
36269
|
+
PackageName: "InvoiceTests",
|
|
36270
|
+
PackageVersion: "1.0.2",
|
|
36271
|
+
TestCaseKey: "DEMO:3",
|
|
36272
|
+
TestCaseId: "a1b2c3d4-0000-0000-0000-000000000003",
|
|
36273
|
+
Action: "Reused"
|
|
36274
|
+
}
|
|
36275
|
+
]
|
|
36276
|
+
}
|
|
36277
|
+
},
|
|
36278
|
+
{
|
|
36279
|
+
Description: "Preview what would be created and linked, without writing",
|
|
36280
|
+
Command: "uip tm testcases link-package --project-key DEMO --folder-key f0f0f0f0-0000-0000-0000-000000000001 --package-name InvoiceTests --dry-run",
|
|
36281
|
+
Output: {
|
|
36282
|
+
Code: "TestCaseLinkPackageDryRun",
|
|
36283
|
+
Data: [
|
|
36284
|
+
{
|
|
36285
|
+
TestName: "SmokeTest",
|
|
36286
|
+
PackageName: "InvoiceTests",
|
|
36287
|
+
PackageVersion: "1.0.2",
|
|
36288
|
+
TestCaseKey: "",
|
|
36289
|
+
TestCaseId: "",
|
|
36290
|
+
Action: "WouldCreate"
|
|
36291
|
+
}
|
|
36292
|
+
]
|
|
36293
|
+
}
|
|
36294
|
+
},
|
|
36295
|
+
{
|
|
36296
|
+
Description: "Link only two named tests out of the package",
|
|
36297
|
+
Command: "uip tm testcases link-package --project-key DEMO --folder-key f0f0f0f0-0000-0000-0000-000000000001 --package-name InvoiceTests --test-name SmokeTest RegressionTest",
|
|
36298
|
+
Output: {
|
|
36299
|
+
Code: "TestCaseLinkPackage",
|
|
36300
|
+
Data: [
|
|
36301
|
+
{
|
|
36302
|
+
TestName: "SmokeTest",
|
|
36303
|
+
PackageName: "InvoiceTests",
|
|
36304
|
+
PackageVersion: "1.0.2",
|
|
36305
|
+
TestCaseKey: "DEMO:7",
|
|
36306
|
+
TestCaseId: "a1b2c3d4-0000-0000-0000-000000000007",
|
|
36307
|
+
Action: "Reused"
|
|
36308
|
+
}
|
|
36309
|
+
]
|
|
36310
|
+
}
|
|
36311
|
+
}
|
|
36312
|
+
];
|
|
36063
36313
|
var TESTCASE_UPDATE_EXAMPLES = [
|
|
36064
36314
|
{
|
|
36065
36315
|
Description: "Rename a test case",
|
|
@@ -36401,9 +36651,39 @@ async function emitTmFailure2(error) {
|
|
|
36401
36651
|
});
|
|
36402
36652
|
processContext.exit(1);
|
|
36403
36653
|
}
|
|
36654
|
+
async function linkPackage(tmConfig, projectId, options) {
|
|
36655
|
+
const folder = await resolveAutomationFolder(options.folderKey, options.tenant);
|
|
36656
|
+
const entryPoints = await fetchPackageEntryPoints(new OrchestratorApi(tmConfig), projectId, options.folderKey);
|
|
36657
|
+
const selected = selectEntryPoints(entryPoints, options);
|
|
36658
|
+
if (selected.length === 0) {
|
|
36659
|
+
throw new Error(describeEmptySelection(options));
|
|
36660
|
+
}
|
|
36661
|
+
return linkPackageEntryPoints(new TestCasesApi(tmConfig), {
|
|
36662
|
+
projectId,
|
|
36663
|
+
entryPoints: selected,
|
|
36664
|
+
folder,
|
|
36665
|
+
dryRun: options.dryRun === true
|
|
36666
|
+
});
|
|
36667
|
+
}
|
|
36668
|
+
function selectEntryPoints(entryPoints, options) {
|
|
36669
|
+
const wantedTests = options.testName?.map((name) => name.toLowerCase());
|
|
36670
|
+
return entryPoints.filter((entryPoint) => {
|
|
36671
|
+
if (options.packageName !== undefined && !matchesPackageName(entryPoint, options.packageName)) {
|
|
36672
|
+
return false;
|
|
36673
|
+
}
|
|
36674
|
+
return wantedTests === undefined || wantedTests.includes((entryPoint.name ?? "").toLowerCase());
|
|
36675
|
+
});
|
|
36676
|
+
}
|
|
36677
|
+
function describeEmptySelection(options) {
|
|
36678
|
+
const scope = [
|
|
36679
|
+
options.packageName ? `package '${options.packageName}'` : undefined,
|
|
36680
|
+
options.testName?.length ? `tests '${options.testName.join("', '")}'` : undefined
|
|
36681
|
+
].filter((part) => part !== undefined).join(" and ");
|
|
36682
|
+
return scope ? `No test entry points found for ${scope} in folder '${options.folderKey}'.` : `No test entry points found in folder '${options.folderKey}'.`;
|
|
36683
|
+
}
|
|
36404
36684
|
var registerTestcaseCommand = (program2) => {
|
|
36405
36685
|
const testcaseCmd = program2.command("testcases").description("Manage Test Manager test cases");
|
|
36406
|
-
testcaseCmd.command("create").description("Create a new test case in a Test Manager project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. DEMO)").requiredOption("--name <name>", "Name of the test case").option("--description <text>", "Description for the test case").option("--version <version>", "Version of the test case",
|
|
36686
|
+
testcaseCmd.command("create").description("Create a new test case in a Test Manager project.").requiredOption("--project-key <key>", "Test Manager project key (e.g. DEMO)").requiredOption("--name <name>", "Name of the test case").option("--description <text>", "Description for the test case").option("--version <version>", "Version of the test case", DEFAULT_TEST_CASE_VERSION).addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").examples(TESTCASE_CREATE_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
36407
36687
|
const [authError, ctx] = await catchError(initializeContextWithProject(options));
|
|
36408
36688
|
if (authError) {
|
|
36409
36689
|
OutputFormatter.error({
|
|
@@ -36649,11 +36929,15 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36649
36929
|
top: 50
|
|
36650
36930
|
}));
|
|
36651
36931
|
if (resolveError) {
|
|
36652
|
-
const { message, details } = await extractErrorDetails2(resolveError, {
|
|
36932
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(resolveError, {
|
|
36933
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
36934
|
+
});
|
|
36653
36935
|
OutputFormatter.error({
|
|
36654
|
-
Result:
|
|
36936
|
+
Result: result,
|
|
36937
|
+
ErrorCode: errorCode2,
|
|
36655
36938
|
Message: message,
|
|
36656
|
-
Instructions: details
|
|
36939
|
+
Instructions: details,
|
|
36940
|
+
Retry: retry
|
|
36657
36941
|
});
|
|
36658
36942
|
processContext.exit(1);
|
|
36659
36943
|
return;
|
|
@@ -36669,15 +36953,30 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36669
36953
|
processContext.exit(1);
|
|
36670
36954
|
return;
|
|
36671
36955
|
}
|
|
36956
|
+
if (!isGuid(options.folderKey)) {
|
|
36957
|
+
OutputFormatter.error({
|
|
36958
|
+
Result: RESULTS.Failure,
|
|
36959
|
+
ErrorCode: "invalid_argument",
|
|
36960
|
+
Message: `Folder key '${options.folderKey}' is not a UUID.`,
|
|
36961
|
+
Instructions: "Pass the folder's Key from 'uip or folders list'.",
|
|
36962
|
+
Retry: "RetryWillNotFix"
|
|
36963
|
+
});
|
|
36964
|
+
processContext.exit(1);
|
|
36965
|
+
return;
|
|
36966
|
+
}
|
|
36672
36967
|
const [folderApiError, foldersApi] = await catchError(createApiClient(FoldersApi, {
|
|
36673
36968
|
tenant: options.tenant
|
|
36674
36969
|
}));
|
|
36675
36970
|
if (folderApiError) {
|
|
36676
|
-
const { message, details } = await extractErrorDetails2(folderApiError, {
|
|
36971
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(folderApiError, {
|
|
36972
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
36973
|
+
});
|
|
36677
36974
|
OutputFormatter.error({
|
|
36678
|
-
Result:
|
|
36975
|
+
Result: result,
|
|
36976
|
+
ErrorCode: errorCode2,
|
|
36679
36977
|
Message: message,
|
|
36680
|
-
Instructions: details
|
|
36978
|
+
Instructions: details,
|
|
36979
|
+
Retry: retry
|
|
36681
36980
|
});
|
|
36682
36981
|
processContext.exit(1);
|
|
36683
36982
|
return;
|
|
@@ -36687,11 +36986,15 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36687
36986
|
$top: 1
|
|
36688
36987
|
}));
|
|
36689
36988
|
if (foldersError) {
|
|
36690
|
-
const { message, details } = await extractErrorDetails2(foldersError, {
|
|
36989
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(foldersError, {
|
|
36990
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
36991
|
+
});
|
|
36691
36992
|
OutputFormatter.error({
|
|
36692
|
-
Result:
|
|
36993
|
+
Result: result,
|
|
36994
|
+
ErrorCode: errorCode2,
|
|
36693
36995
|
Message: message,
|
|
36694
|
-
Instructions: details
|
|
36996
|
+
Instructions: details,
|
|
36997
|
+
Retry: retry
|
|
36695
36998
|
});
|
|
36696
36999
|
processContext.exit(1);
|
|
36697
37000
|
return;
|
|
@@ -36700,7 +37003,10 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36700
37003
|
if (!folderMatch?.displayName) {
|
|
36701
37004
|
OutputFormatter.error({
|
|
36702
37005
|
Result: RESULTS.Failure,
|
|
36703
|
-
|
|
37006
|
+
ErrorCode: "not_found",
|
|
37007
|
+
Message: `Folder with key '${options.folderKey}' not found.`,
|
|
37008
|
+
Instructions: "List the folders you can see with 'uip or folders list' and pass one of their Key values.",
|
|
37009
|
+
Retry: "RetryWillNotFix"
|
|
36704
37010
|
});
|
|
36705
37011
|
processContext.exit(1);
|
|
36706
37012
|
return;
|
|
@@ -36708,11 +37014,15 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36708
37014
|
const folderDisplayName = folderMatch.displayName;
|
|
36709
37015
|
const [epError, entryPointsPage] = await catchError(orchestratorApi.orchestratorGetUniquePackageEntryPoints(toGetPackageEntryPointsRequest(projectId, options.folderKey, true, options.testName, 100, 0)));
|
|
36710
37016
|
if (epError) {
|
|
36711
|
-
const { message, details } = await extractErrorDetails2(epError, {
|
|
37017
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(epError, {
|
|
37018
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
37019
|
+
});
|
|
36712
37020
|
OutputFormatter.error({
|
|
36713
|
-
Result:
|
|
37021
|
+
Result: result,
|
|
37022
|
+
ErrorCode: errorCode2,
|
|
36714
37023
|
Message: message,
|
|
36715
|
-
Instructions: details
|
|
37024
|
+
Instructions: details,
|
|
37025
|
+
Retry: retry
|
|
36716
37026
|
});
|
|
36717
37027
|
processContext.exit(1);
|
|
36718
37028
|
return;
|
|
@@ -36734,11 +37044,15 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36734
37044
|
packageSourceName: folderDisplayName
|
|
36735
37045
|
})));
|
|
36736
37046
|
if (updateError) {
|
|
36737
|
-
const { message, details } = await extractErrorDetails2(updateError, {
|
|
37047
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(updateError, {
|
|
37048
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
37049
|
+
});
|
|
36738
37050
|
OutputFormatter.error({
|
|
36739
|
-
Result:
|
|
37051
|
+
Result: result,
|
|
37052
|
+
ErrorCode: errorCode2,
|
|
36740
37053
|
Message: message,
|
|
36741
|
-
Instructions: details
|
|
37054
|
+
Instructions: details,
|
|
37055
|
+
Retry: retry
|
|
36742
37056
|
});
|
|
36743
37057
|
processContext.exit(1);
|
|
36744
37058
|
return;
|
|
@@ -36751,6 +37065,38 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36751
37065
|
Result: "Linked"
|
|
36752
37066
|
}));
|
|
36753
37067
|
});
|
|
37068
|
+
testcaseCmd.command("link-package").description("Create and link a test case for every test in an Orchestrator package, in one call.").requiredOption("--project-key <key>", "Test Manager project key (e.g. DEMO)").requiredOption("--folder-key <uuid>", "Orchestrator folder key UUID (from 'uip or folders list')").option("--package-name <name>", "Only link tests from this package (case-insensitive exact match). Omit to link every test the folder exposes.").option("--test-name <name...>", "Only link these tests (case-insensitive). Omit to link all of them.").option("--dry-run", "Preview which test cases would be created, reused and linked, without writing anything.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").examples(TESTCASE_LINK_PACKAGE_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
37069
|
+
const [authError, ctx] = await catchError(initializeContextWithProject(options));
|
|
37070
|
+
if (authError) {
|
|
37071
|
+
OutputFormatter.error({
|
|
37072
|
+
Result: RESULTS.Failure,
|
|
37073
|
+
Message: authError.message,
|
|
37074
|
+
Instructions: instructionsFor("auth")
|
|
37075
|
+
});
|
|
37076
|
+
processContext.exit(1);
|
|
37077
|
+
return;
|
|
37078
|
+
}
|
|
37079
|
+
if (!ctx)
|
|
37080
|
+
return;
|
|
37081
|
+
const { tmConfig, projectId } = ctx;
|
|
37082
|
+
const [error, rows] = await catchError(linkPackage(tmConfig, projectId, options));
|
|
37083
|
+
if (error) {
|
|
37084
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(error, {
|
|
37085
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
37086
|
+
});
|
|
37087
|
+
const stated = readClassification(error);
|
|
37088
|
+
OutputFormatter.error({
|
|
37089
|
+
Result: result,
|
|
37090
|
+
ErrorCode: stated.errorCode ?? errorCode2,
|
|
37091
|
+
Message: message,
|
|
37092
|
+
Instructions: readInstructions(error) ?? (details && details !== message ? details : `Run 'uip tm testcases list-automations --project-key ${options.projectKey} --folder-key ${options.folderKey}' to see the tests this folder exposes.`),
|
|
37093
|
+
Retry: stated.retry ?? retry
|
|
37094
|
+
});
|
|
37095
|
+
processContext.exit(1);
|
|
37096
|
+
return;
|
|
37097
|
+
}
|
|
37098
|
+
OutputFormatter.success(new SuccessOutput(options.dryRun ? "TestCaseLinkPackageDryRun" : "TestCaseLinkPackage", rows));
|
|
37099
|
+
});
|
|
36754
37100
|
testcaseCmd.command("update").description("Update a test case's name, description, or pre/post-condition.").requiredOption("--project-key <key>", "Test Manager project key (e.g. DEMO)").requiredOption("--test-case-key <key>", "Test case key (e.g. DEMO:1)").option("--name <name>", "New test case name").option("--description <text>", "New test case description").option("--pre-condition <text>", "New precondition (what must be true before running the test)").option("--post-condition <text>", "New postcondition (what should be true after running the test)").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--log-level <level>", "Log verbosity: debug, info, warn, error", "Information").examples(TESTCASE_UPDATE_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
36755
37101
|
const operations = [];
|
|
36756
37102
|
if (options.name !== undefined)
|
|
@@ -36977,32 +37323,22 @@ var registerTestcaseCommand = (program2) => {
|
|
|
36977
37323
|
if (!ctx)
|
|
36978
37324
|
return;
|
|
36979
37325
|
const { tmConfig, projectId } = ctx;
|
|
36980
|
-
const
|
|
36981
|
-
|
|
36982
|
-
|
|
36983
|
-
|
|
36984
|
-
|
|
36985
|
-
|
|
36986
|
-
|
|
36987
|
-
|
|
36988
|
-
|
|
36989
|
-
|
|
36990
|
-
|
|
36991
|
-
|
|
36992
|
-
|
|
36993
|
-
|
|
36994
|
-
return;
|
|
36995
|
-
}
|
|
36996
|
-
const data = entryPointsPage;
|
|
36997
|
-
const items = data.data ?? data ?? [];
|
|
36998
|
-
all.push(...items);
|
|
36999
|
-
const paging = data.paging;
|
|
37000
|
-
const total = paging?.total ?? data.total ?? items.length;
|
|
37001
|
-
skip += top;
|
|
37002
|
-
if (skip >= total || items.length < top)
|
|
37003
|
-
break;
|
|
37326
|
+
const [epError, all] = await catchError(fetchPackageEntryPoints(new OrchestratorApi(tmConfig), projectId, options.folderKey));
|
|
37327
|
+
if (epError) {
|
|
37328
|
+
const { result, errorCode: errorCode2, message, retry, details } = await extractErrorDetails2(epError, {
|
|
37329
|
+
forbiddenMessage: TM_FORBIDDEN_MESSAGE
|
|
37330
|
+
});
|
|
37331
|
+
OutputFormatter.error({
|
|
37332
|
+
Result: result,
|
|
37333
|
+
ErrorCode: errorCode2,
|
|
37334
|
+
Message: message,
|
|
37335
|
+
Instructions: details,
|
|
37336
|
+
Retry: retry
|
|
37337
|
+
});
|
|
37338
|
+
processContext.exit(1);
|
|
37339
|
+
return;
|
|
37004
37340
|
}
|
|
37005
|
-
const filtered = options.packageName ? all.filter((ep) => ep
|
|
37341
|
+
const filtered = options.packageName ? all.filter((ep) => matchesPackageName(ep, options.packageName)) : all;
|
|
37006
37342
|
const rows = filtered.map((ep) => ({
|
|
37007
37343
|
PackageName: ep.packageName ?? "",
|
|
37008
37344
|
TestName: ep.name ?? "",
|
|
@@ -38951,4 +39287,4 @@ var registerCommands = async (program2) => {
|
|
|
38951
39287
|
|
|
38952
39288
|
export { Command, metadata, registerCommands };
|
|
38953
39289
|
|
|
38954
|
-
//# debugId=
|
|
39290
|
+
//# debugId=D5D78FA549BBB2CB64756E2164756E21
|
package/dist/tool.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/test-manager-tool",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "1.202.0-preview.
|
|
4
|
+
"version": "1.202.0-preview.137",
|
|
5
5
|
"description": "Manage test cases, test sets, executions, and results.",
|
|
6
6
|
"private": false,
|
|
7
7
|
"repository": {
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"files": [
|
|
27
27
|
"dist"
|
|
28
28
|
],
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "bbb20a6d3501afc3435a92af9ae2e9f7ab2e34f6"
|
|
30
30
|
}
|