@uipath/data-fabric-tool 1.1.0 → 1.196.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tool.js +6246 -5365
- package/package.json +16 -24
- package/src/commands/choice-sets.spec.ts +571 -83
- package/src/commands/choice-sets.ts +561 -147
- package/src/commands/entities.spec.ts +109 -159
- package/src/commands/entities.ts +181 -372
- package/src/commands/files.spec.ts +62 -34
- package/src/commands/files.ts +51 -88
- package/src/commands/records.spec.ts +188 -206
- package/src/commands/records.ts +133 -330
- package/src/tool.ts +5 -1
- package/src/utils/input.spec.ts +127 -0
- package/src/utils/input.ts +30 -1
- package/src/utils/output.spec.ts +91 -0
- package/src/utils/output.ts +69 -0
- package/src/utils/sdk-client.spec.ts +59 -0
- package/src/utils/sdk-client.ts +23 -0
- package/src/utils/pagination.ts +0 -10
|
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
3
3
|
|
|
4
4
|
vi.mock("../utils/sdk-client", () => ({
|
|
5
5
|
createDataFabricClient: vi.fn(),
|
|
6
|
+
connectOrFail: vi.fn(),
|
|
6
7
|
}));
|
|
7
8
|
|
|
8
9
|
vi.mock("@uipath/common", async (importOriginal) => {
|
|
@@ -23,7 +24,7 @@ vi.mock("@uipath/filesystem", () => ({
|
|
|
23
24
|
}));
|
|
24
25
|
|
|
25
26
|
import { OutputFormatter } from "@uipath/common";
|
|
26
|
-
import {
|
|
27
|
+
import { connectOrFail } from "../utils/sdk-client";
|
|
27
28
|
import { registerRecordsCommand } from "./records";
|
|
28
29
|
|
|
29
30
|
function buildProgram(): Command {
|
|
@@ -66,7 +67,7 @@ function mockSdk(overrides: Record<string, unknown> = {}) {
|
|
|
66
67
|
...overrides,
|
|
67
68
|
},
|
|
68
69
|
};
|
|
69
|
-
vi.mocked(
|
|
70
|
+
vi.mocked(connectOrFail).mockResolvedValue(sdk as never);
|
|
70
71
|
return sdk;
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -83,13 +84,14 @@ describe("records list", () => {
|
|
|
83
84
|
expect(cmd?.commands.map((c) => c.name())).toContain("list");
|
|
84
85
|
});
|
|
85
86
|
|
|
86
|
-
it("should list records successfully", async () => {
|
|
87
|
+
it("should list records successfully (raw SDK shape)", async () => {
|
|
87
88
|
const sdk = mockSdk();
|
|
88
|
-
|
|
89
|
+
const rawResult = {
|
|
89
90
|
items: [{ Id: "rec-1", name: "test" }],
|
|
90
91
|
totalCount: 1,
|
|
91
92
|
hasNextPage: false,
|
|
92
|
-
}
|
|
93
|
+
};
|
|
94
|
+
vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
|
|
93
95
|
|
|
94
96
|
const program = buildProgram();
|
|
95
97
|
await program.parseAsync([
|
|
@@ -107,22 +109,20 @@ describe("records list", () => {
|
|
|
107
109
|
expect.objectContaining({
|
|
108
110
|
Result: "Success",
|
|
109
111
|
Code: "RecordList",
|
|
110
|
-
Data:
|
|
111
|
-
TotalCount: 1,
|
|
112
|
-
HasNextPage: false,
|
|
113
|
-
}),
|
|
112
|
+
Data: rawResult,
|
|
114
113
|
}),
|
|
115
114
|
);
|
|
116
115
|
});
|
|
117
116
|
|
|
118
|
-
it("should pass cursor to SDK and
|
|
117
|
+
it("should pass cursor to SDK and return the raw paginated response", async () => {
|
|
119
118
|
const sdk = mockSdk();
|
|
120
|
-
|
|
119
|
+
const rawResult = {
|
|
121
120
|
items: [{ Id: "rec-2" }],
|
|
122
121
|
totalCount: 100,
|
|
123
122
|
hasNextPage: true,
|
|
124
|
-
nextCursor: "cursor-abc",
|
|
125
|
-
}
|
|
123
|
+
nextCursor: { value: "cursor-abc" },
|
|
124
|
+
};
|
|
125
|
+
vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
|
|
126
126
|
|
|
127
127
|
const program = buildProgram();
|
|
128
128
|
await program.parseAsync([
|
|
@@ -141,16 +141,15 @@ describe("records list", () => {
|
|
|
141
141
|
});
|
|
142
142
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
143
143
|
expect.objectContaining({
|
|
144
|
-
Data:
|
|
145
|
-
HasNextPage: true,
|
|
146
|
-
NextCursor: "cursor-abc",
|
|
147
|
-
}),
|
|
144
|
+
Data: rawResult,
|
|
148
145
|
}),
|
|
149
146
|
);
|
|
150
147
|
});
|
|
151
148
|
|
|
152
|
-
it("should return empty list when no records exist", async () => {
|
|
153
|
-
mockSdk();
|
|
149
|
+
it("should return empty list when no records exist (raw SDK shape)", async () => {
|
|
150
|
+
const sdk = mockSdk();
|
|
151
|
+
const rawResult = { items: [], totalCount: 0 };
|
|
152
|
+
vi.mocked(sdk.entities.getAllRecords).mockResolvedValue(rawResult);
|
|
154
153
|
|
|
155
154
|
const program = buildProgram();
|
|
156
155
|
await program.parseAsync([
|
|
@@ -165,7 +164,7 @@ describe("records list", () => {
|
|
|
165
164
|
expect.objectContaining({
|
|
166
165
|
Result: "Success",
|
|
167
166
|
Code: "RecordList",
|
|
168
|
-
Data:
|
|
167
|
+
Data: rawResult,
|
|
169
168
|
}),
|
|
170
169
|
);
|
|
171
170
|
expect(process.exitCode).not.toBe(1);
|
|
@@ -361,10 +360,9 @@ describe("records list client error", () => {
|
|
|
361
360
|
process.exitCode = undefined;
|
|
362
361
|
});
|
|
363
362
|
|
|
364
|
-
it("should
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
);
|
|
363
|
+
it("should bail when SDK connection fails on list", async () => {
|
|
364
|
+
const sdk = mockSdk();
|
|
365
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
368
366
|
const program = buildProgram();
|
|
369
367
|
await program.parseAsync([
|
|
370
368
|
"node",
|
|
@@ -373,20 +371,14 @@ describe("records list client error", () => {
|
|
|
373
371
|
"list",
|
|
374
372
|
"entity-id",
|
|
375
373
|
]);
|
|
376
|
-
expect(
|
|
377
|
-
|
|
378
|
-
Result: "Failure",
|
|
379
|
-
Message: "Error connecting to Data Fabric",
|
|
380
|
-
}),
|
|
381
|
-
);
|
|
382
|
-
expect(process.exitCode).toBe(1);
|
|
374
|
+
expect(sdk.entities.getAllRecords).not.toHaveBeenCalled();
|
|
375
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
383
376
|
});
|
|
384
377
|
|
|
385
|
-
it("should
|
|
378
|
+
it("should pass through the raw list result verbatim", async () => {
|
|
379
|
+
const rawResult = { items: [], hasNextPage: false };
|
|
386
380
|
const sdk = mockSdk({
|
|
387
|
-
getAllRecords: vi
|
|
388
|
-
.fn()
|
|
389
|
-
.mockResolvedValue({ items: [], hasNextPage: false }),
|
|
381
|
+
getAllRecords: vi.fn().mockResolvedValue(rawResult),
|
|
390
382
|
});
|
|
391
383
|
const program = buildProgram();
|
|
392
384
|
await program.parseAsync([
|
|
@@ -399,11 +391,7 @@ describe("records list client error", () => {
|
|
|
399
391
|
expect(sdk.entities.getAllRecords).toHaveBeenCalled();
|
|
400
392
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
401
393
|
expect.objectContaining({
|
|
402
|
-
Data:
|
|
403
|
-
TotalCount: 0,
|
|
404
|
-
Records: [],
|
|
405
|
-
HasNextPage: false,
|
|
406
|
-
}),
|
|
394
|
+
Data: rawResult,
|
|
407
395
|
}),
|
|
408
396
|
);
|
|
409
397
|
});
|
|
@@ -496,10 +484,9 @@ describe("records get client error", () => {
|
|
|
496
484
|
process.exitCode = undefined;
|
|
497
485
|
});
|
|
498
486
|
|
|
499
|
-
it("should
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
);
|
|
487
|
+
it("should bail when SDK connection fails on get", async () => {
|
|
488
|
+
const sdk = mockSdk();
|
|
489
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
503
490
|
const program = buildProgram();
|
|
504
491
|
await program.parseAsync([
|
|
505
492
|
"node",
|
|
@@ -509,13 +496,8 @@ describe("records get client error", () => {
|
|
|
509
496
|
"entity-id",
|
|
510
497
|
"rec-1",
|
|
511
498
|
]);
|
|
512
|
-
expect(
|
|
513
|
-
|
|
514
|
-
Result: "Failure",
|
|
515
|
-
Message: "Error connecting to Data Fabric",
|
|
516
|
-
}),
|
|
517
|
-
);
|
|
518
|
-
expect(process.exitCode).toBe(1);
|
|
499
|
+
expect(sdk.entities.getRecordById).not.toHaveBeenCalled();
|
|
500
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
519
501
|
});
|
|
520
502
|
});
|
|
521
503
|
|
|
@@ -630,10 +612,9 @@ describe("records insert", () => {
|
|
|
630
612
|
expect(process.exitCode).toBe(1);
|
|
631
613
|
});
|
|
632
614
|
|
|
633
|
-
it("should
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
);
|
|
615
|
+
it("should bail when SDK connection fails on insert", async () => {
|
|
616
|
+
const sdk = mockSdk();
|
|
617
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
637
618
|
const program = buildProgram();
|
|
638
619
|
await program.parseAsync([
|
|
639
620
|
"node",
|
|
@@ -644,13 +625,8 @@ describe("records insert", () => {
|
|
|
644
625
|
"--body",
|
|
645
626
|
'{"amount":100}',
|
|
646
627
|
]);
|
|
647
|
-
expect(
|
|
648
|
-
|
|
649
|
-
Result: "Failure",
|
|
650
|
-
Message: "Error connecting to Data Fabric",
|
|
651
|
-
}),
|
|
652
|
-
);
|
|
653
|
-
expect(process.exitCode).toBe(1);
|
|
628
|
+
expect(sdk.entities.insertRecordById).not.toHaveBeenCalled();
|
|
629
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
654
630
|
});
|
|
655
631
|
|
|
656
632
|
it("should handle batch insert result without successRecords/failureRecords", async () => {
|
|
@@ -977,10 +953,9 @@ describe("records update client/batch errors", () => {
|
|
|
977
953
|
process.exitCode = undefined;
|
|
978
954
|
});
|
|
979
955
|
|
|
980
|
-
it("should
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
);
|
|
956
|
+
it("should bail when SDK connection fails on update", async () => {
|
|
957
|
+
const sdk = mockSdk();
|
|
958
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
984
959
|
const program = buildProgram();
|
|
985
960
|
await program.parseAsync([
|
|
986
961
|
"node",
|
|
@@ -991,13 +966,8 @@ describe("records update client/batch errors", () => {
|
|
|
991
966
|
"--body",
|
|
992
967
|
'{"Id":"rec-1"}',
|
|
993
968
|
]);
|
|
994
|
-
expect(
|
|
995
|
-
|
|
996
|
-
Result: "Failure",
|
|
997
|
-
Message: "Error connecting to Data Fabric",
|
|
998
|
-
}),
|
|
999
|
-
);
|
|
1000
|
-
expect(process.exitCode).toBe(1);
|
|
969
|
+
expect(sdk.entities.updateRecordById).not.toHaveBeenCalled();
|
|
970
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
1001
971
|
});
|
|
1002
972
|
|
|
1003
973
|
it("should handle batch update result without successRecords/failureRecords", async () => {
|
|
@@ -1097,6 +1067,9 @@ describe("records delete", () => {
|
|
|
1097
1067
|
"entity-id",
|
|
1098
1068
|
"rec-1",
|
|
1099
1069
|
"rec-2",
|
|
1070
|
+
"--yes",
|
|
1071
|
+
"--reason",
|
|
1072
|
+
"test cleanup",
|
|
1100
1073
|
]);
|
|
1101
1074
|
|
|
1102
1075
|
expect(sdk.entities.deleteRecordsById).toHaveBeenCalledWith(
|
|
@@ -1123,6 +1096,9 @@ describe("records delete", () => {
|
|
|
1123
1096
|
"delete",
|
|
1124
1097
|
"entity-id",
|
|
1125
1098
|
"rec-1",
|
|
1099
|
+
"--yes",
|
|
1100
|
+
"--reason",
|
|
1101
|
+
"test cleanup",
|
|
1126
1102
|
]);
|
|
1127
1103
|
expect(sdk.entities.deleteRecordsById).toHaveBeenCalled();
|
|
1128
1104
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
@@ -1149,6 +1125,9 @@ describe("records delete", () => {
|
|
|
1149
1125
|
"delete",
|
|
1150
1126
|
"entity-id",
|
|
1151
1127
|
"rec-1",
|
|
1128
|
+
"--yes",
|
|
1129
|
+
"--reason",
|
|
1130
|
+
"test cleanup",
|
|
1152
1131
|
]);
|
|
1153
1132
|
|
|
1154
1133
|
expect(OutputFormatter.error).toHaveBeenCalledWith(
|
|
@@ -1172,6 +1151,9 @@ describe("records delete", () => {
|
|
|
1172
1151
|
"entity-id",
|
|
1173
1152
|
"rec-1",
|
|
1174
1153
|
"rec-2",
|
|
1154
|
+
"--yes",
|
|
1155
|
+
"--reason",
|
|
1156
|
+
"test cleanup",
|
|
1175
1157
|
]);
|
|
1176
1158
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
1177
1159
|
expect.objectContaining({
|
|
@@ -1185,18 +1167,38 @@ describe("records delete", () => {
|
|
|
1185
1167
|
);
|
|
1186
1168
|
expect(process.exitCode).toBe(1);
|
|
1187
1169
|
});
|
|
1188
|
-
});
|
|
1189
1170
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1171
|
+
it("should accept --confirm as a deprecated alias for --yes", async () => {
|
|
1172
|
+
const sdk = mockSdk();
|
|
1173
|
+
|
|
1174
|
+
const program = buildProgram();
|
|
1175
|
+
await program.parseAsync([
|
|
1176
|
+
"node",
|
|
1177
|
+
"test",
|
|
1178
|
+
"records",
|
|
1179
|
+
"delete",
|
|
1180
|
+
"entity-id",
|
|
1181
|
+
"rec-1",
|
|
1182
|
+
"--confirm",
|
|
1183
|
+
"--reason",
|
|
1184
|
+
"test cleanup",
|
|
1185
|
+
]);
|
|
1195
1186
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1187
|
+
expect(sdk.entities.deleteRecordsById).toHaveBeenCalledWith(
|
|
1188
|
+
"entity-id",
|
|
1189
|
+
["rec-1"],
|
|
1190
|
+
);
|
|
1191
|
+
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
1192
|
+
expect.objectContaining({
|
|
1193
|
+
Result: "Success",
|
|
1194
|
+
Code: "RecordsDeleted",
|
|
1195
|
+
}),
|
|
1199
1196
|
);
|
|
1197
|
+
});
|
|
1198
|
+
|
|
1199
|
+
it("should require confirmation: without --yes, exit 1 and SDK not called", async () => {
|
|
1200
|
+
const sdk = mockSdk();
|
|
1201
|
+
|
|
1200
1202
|
const program = buildProgram();
|
|
1201
1203
|
await program.parseAsync([
|
|
1202
1204
|
"node",
|
|
@@ -1205,17 +1207,63 @@ describe("records delete client error", () => {
|
|
|
1205
1207
|
"delete",
|
|
1206
1208
|
"entity-id",
|
|
1207
1209
|
"rec-1",
|
|
1210
|
+
"--reason",
|
|
1211
|
+
"test cleanup",
|
|
1208
1212
|
]);
|
|
1213
|
+
|
|
1214
|
+
expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
|
|
1215
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
1216
|
+
expect(process.exitCode).toBe(1);
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
it("should require --reason when confirmation is present", async () => {
|
|
1220
|
+
const sdk = mockSdk();
|
|
1221
|
+
|
|
1222
|
+
const program = buildProgram();
|
|
1223
|
+
await program.parseAsync([
|
|
1224
|
+
"node",
|
|
1225
|
+
"test",
|
|
1226
|
+
"records",
|
|
1227
|
+
"delete",
|
|
1228
|
+
"entity-id",
|
|
1229
|
+
"rec-1",
|
|
1230
|
+
"--yes",
|
|
1231
|
+
]);
|
|
1232
|
+
|
|
1233
|
+
expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
|
|
1209
1234
|
expect(OutputFormatter.error).toHaveBeenCalledWith(
|
|
1210
1235
|
expect.objectContaining({
|
|
1211
1236
|
Result: "Failure",
|
|
1212
|
-
Message: "
|
|
1237
|
+
Message: "Reason required for destructive operation",
|
|
1213
1238
|
}),
|
|
1214
1239
|
);
|
|
1215
1240
|
expect(process.exitCode).toBe(1);
|
|
1216
1241
|
});
|
|
1217
1242
|
});
|
|
1218
1243
|
|
|
1244
|
+
describe("records delete client error", () => {
|
|
1245
|
+
beforeEach(() => {
|
|
1246
|
+
vi.resetAllMocks();
|
|
1247
|
+
process.exitCode = undefined;
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1250
|
+
it("should bail when SDK connection fails on delete", async () => {
|
|
1251
|
+
const sdk = mockSdk();
|
|
1252
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
1253
|
+
const program = buildProgram();
|
|
1254
|
+
await program.parseAsync([
|
|
1255
|
+
"node",
|
|
1256
|
+
"test",
|
|
1257
|
+
"records",
|
|
1258
|
+
"delete",
|
|
1259
|
+
"entity-id",
|
|
1260
|
+
"rec-1",
|
|
1261
|
+
]);
|
|
1262
|
+
expect(sdk.entities.deleteRecordsById).not.toHaveBeenCalled();
|
|
1263
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
1264
|
+
});
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1219
1267
|
describe("records insert via --file", () => {
|
|
1220
1268
|
beforeEach(() => {
|
|
1221
1269
|
vi.resetAllMocks();
|
|
@@ -1305,13 +1353,14 @@ describe("records query", () => {
|
|
|
1305
1353
|
process.exitCode = undefined;
|
|
1306
1354
|
});
|
|
1307
1355
|
|
|
1308
|
-
it("should query records without filters (no --body)", async () => {
|
|
1356
|
+
it("should query records without filters (no --body) and return raw shape", async () => {
|
|
1309
1357
|
const sdk = mockSdk();
|
|
1310
|
-
|
|
1358
|
+
const rawResult = {
|
|
1311
1359
|
items: [{ Id: "rec-1", title: "test" }],
|
|
1312
1360
|
totalCount: 1,
|
|
1313
1361
|
hasNextPage: false,
|
|
1314
|
-
}
|
|
1362
|
+
};
|
|
1363
|
+
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
|
|
1315
1364
|
|
|
1316
1365
|
const program = buildProgram();
|
|
1317
1366
|
await program.parseAsync([
|
|
@@ -1330,10 +1379,7 @@ describe("records query", () => {
|
|
|
1330
1379
|
expect.objectContaining({
|
|
1331
1380
|
Result: "Success",
|
|
1332
1381
|
Code: "RecordQuery",
|
|
1333
|
-
Data:
|
|
1334
|
-
TotalCount: 1,
|
|
1335
|
-
HasNextPage: false,
|
|
1336
|
-
}),
|
|
1382
|
+
Data: rawResult,
|
|
1337
1383
|
}),
|
|
1338
1384
|
);
|
|
1339
1385
|
});
|
|
@@ -1421,7 +1467,7 @@ describe("records query", () => {
|
|
|
1421
1467
|
expect.objectContaining({
|
|
1422
1468
|
Result: "Success",
|
|
1423
1469
|
Code: "RecordQuery",
|
|
1424
|
-
Data: expect.objectContaining({
|
|
1470
|
+
Data: expect.objectContaining({ totalCount: 2 }),
|
|
1425
1471
|
}),
|
|
1426
1472
|
);
|
|
1427
1473
|
});
|
|
@@ -1470,8 +1516,8 @@ describe("records query", () => {
|
|
|
1470
1516
|
Result: "Success",
|
|
1471
1517
|
Code: "RecordQuery",
|
|
1472
1518
|
Data: expect.objectContaining({
|
|
1473
|
-
|
|
1474
|
-
|
|
1519
|
+
totalCount: 2,
|
|
1520
|
+
items: [
|
|
1475
1521
|
{ status: "Open", total: 12 },
|
|
1476
1522
|
{ status: "Closed", total: 5 },
|
|
1477
1523
|
],
|
|
@@ -1527,12 +1573,13 @@ describe("records query", () => {
|
|
|
1527
1573
|
|
|
1528
1574
|
it("should pass custom --limit and --cursor to queryRecordsById", async () => {
|
|
1529
1575
|
const sdk = mockSdk();
|
|
1530
|
-
|
|
1576
|
+
const rawResult = {
|
|
1531
1577
|
items: [{ Id: "rec-3" }],
|
|
1532
1578
|
totalCount: 100,
|
|
1533
1579
|
hasNextPage: true,
|
|
1534
|
-
nextCursor: "next-cursor-xyz",
|
|
1535
|
-
}
|
|
1580
|
+
nextCursor: { value: "next-cursor-xyz" },
|
|
1581
|
+
};
|
|
1582
|
+
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
|
|
1536
1583
|
|
|
1537
1584
|
const program = buildProgram();
|
|
1538
1585
|
await program.parseAsync([
|
|
@@ -1556,10 +1603,7 @@ describe("records query", () => {
|
|
|
1556
1603
|
);
|
|
1557
1604
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
1558
1605
|
expect.objectContaining({
|
|
1559
|
-
Data:
|
|
1560
|
-
HasNextPage: true,
|
|
1561
|
-
NextCursor: "next-cursor-xyz",
|
|
1562
|
-
}),
|
|
1606
|
+
Data: rawResult,
|
|
1563
1607
|
}),
|
|
1564
1608
|
);
|
|
1565
1609
|
});
|
|
@@ -1627,10 +1671,9 @@ describe("records query", () => {
|
|
|
1627
1671
|
expect(process.exitCode).toBe(1);
|
|
1628
1672
|
});
|
|
1629
1673
|
|
|
1630
|
-
it("should
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
);
|
|
1674
|
+
it("should bail when SDK connection fails on query", async () => {
|
|
1675
|
+
const sdk = mockSdk();
|
|
1676
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
1634
1677
|
const program = buildProgram();
|
|
1635
1678
|
await program.parseAsync([
|
|
1636
1679
|
"node",
|
|
@@ -1639,13 +1682,8 @@ describe("records query", () => {
|
|
|
1639
1682
|
"query",
|
|
1640
1683
|
"entity-id",
|
|
1641
1684
|
]);
|
|
1642
|
-
expect(
|
|
1643
|
-
|
|
1644
|
-
Result: "Failure",
|
|
1645
|
-
Message: "Error connecting to Data Fabric",
|
|
1646
|
-
}),
|
|
1647
|
-
);
|
|
1648
|
-
expect(process.exitCode).toBe(1);
|
|
1685
|
+
expect(sdk.entities.queryRecordsById).not.toHaveBeenCalled();
|
|
1686
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
1649
1687
|
});
|
|
1650
1688
|
|
|
1651
1689
|
it("should error when query API fails", async () => {
|
|
@@ -1877,10 +1915,9 @@ describe("records import", () => {
|
|
|
1877
1915
|
expect(process.exitCode).toBe(1);
|
|
1878
1916
|
});
|
|
1879
1917
|
|
|
1880
|
-
it("should
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
);
|
|
1918
|
+
it("should bail when SDK connection fails on import", async () => {
|
|
1919
|
+
const sdk = mockSdk();
|
|
1920
|
+
vi.mocked(connectOrFail).mockResolvedValue(undefined);
|
|
1884
1921
|
|
|
1885
1922
|
const { getFileSystem } = await import("@uipath/filesystem");
|
|
1886
1923
|
vi.mocked(getFileSystem).mockReturnValue({
|
|
@@ -1900,13 +1937,8 @@ describe("records import", () => {
|
|
|
1900
1937
|
"data.csv",
|
|
1901
1938
|
]);
|
|
1902
1939
|
|
|
1903
|
-
expect(
|
|
1904
|
-
|
|
1905
|
-
Result: "Failure",
|
|
1906
|
-
Message: "Error connecting to Data Fabric",
|
|
1907
|
-
}),
|
|
1908
|
-
);
|
|
1909
|
-
expect(process.exitCode).toBe(1);
|
|
1940
|
+
expect(sdk.entities.importRecordsById).not.toHaveBeenCalled();
|
|
1941
|
+
expect(OutputFormatter.success).not.toHaveBeenCalled();
|
|
1910
1942
|
});
|
|
1911
1943
|
});
|
|
1912
1944
|
|
|
@@ -1940,14 +1972,14 @@ describe("records query — pagination", () => {
|
|
|
1940
1972
|
const call = vi.mocked(OutputFormatter.success).mock
|
|
1941
1973
|
.calls[0][0] as unknown as {
|
|
1942
1974
|
Data: {
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1975
|
+
totalCount: number;
|
|
1976
|
+
items: unknown[];
|
|
1977
|
+
hasNextPage: boolean;
|
|
1946
1978
|
};
|
|
1947
1979
|
};
|
|
1948
|
-
expect(call.Data.
|
|
1949
|
-
expect(call.Data.
|
|
1950
|
-
expect(call.Data.
|
|
1980
|
+
expect(call.Data.totalCount).toBe(3);
|
|
1981
|
+
expect(call.Data.items).toHaveLength(3);
|
|
1982
|
+
expect(call.Data.hasNextPage).toBe(false);
|
|
1951
1983
|
});
|
|
1952
1984
|
|
|
1953
1985
|
it("should return first page with cursor when paginated", async () => {
|
|
@@ -1956,7 +1988,7 @@ describe("records query — pagination", () => {
|
|
|
1956
1988
|
items: [{ Id: "r1" }, { Id: "r2" }],
|
|
1957
1989
|
totalCount: 5,
|
|
1958
1990
|
hasNextPage: true,
|
|
1959
|
-
nextCursor: "cursor-page2",
|
|
1991
|
+
nextCursor: { value: "cursor-page2" },
|
|
1960
1992
|
});
|
|
1961
1993
|
|
|
1962
1994
|
const program = buildProgram();
|
|
@@ -1977,16 +2009,16 @@ describe("records query — pagination", () => {
|
|
|
1977
2009
|
const call = vi.mocked(OutputFormatter.success).mock
|
|
1978
2010
|
.calls[0][0] as unknown as {
|
|
1979
2011
|
Data: {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
2012
|
+
totalCount: number;
|
|
2013
|
+
items: unknown[];
|
|
2014
|
+
hasNextPage: boolean;
|
|
2015
|
+
nextCursor: { value: string };
|
|
1984
2016
|
};
|
|
1985
2017
|
};
|
|
1986
|
-
expect(call.Data.
|
|
1987
|
-
expect(call.Data.
|
|
1988
|
-
expect(call.Data.
|
|
1989
|
-
expect(call.Data.
|
|
2018
|
+
expect(call.Data.totalCount).toBe(5);
|
|
2019
|
+
expect(call.Data.items).toHaveLength(2);
|
|
2020
|
+
expect(call.Data.hasNextPage).toBe(true);
|
|
2021
|
+
expect(call.Data.nextCursor).toEqual({ value: "cursor-page2" });
|
|
1990
2022
|
});
|
|
1991
2023
|
|
|
1992
2024
|
it("should pass cursor to second page request", async () => {
|
|
@@ -1995,7 +2027,7 @@ describe("records query — pagination", () => {
|
|
|
1995
2027
|
items: [{ Id: "r3" }, { Id: "r4" }],
|
|
1996
2028
|
totalCount: 5,
|
|
1997
2029
|
hasNextPage: true,
|
|
1998
|
-
nextCursor: "cursor-page3",
|
|
2030
|
+
nextCursor: { value: "cursor-page3" },
|
|
1999
2031
|
});
|
|
2000
2032
|
|
|
2001
2033
|
const program = buildProgram();
|
|
@@ -2021,8 +2053,8 @@ describe("records query — pagination", () => {
|
|
|
2021
2053
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
2022
2054
|
expect.objectContaining({
|
|
2023
2055
|
Data: expect.objectContaining({
|
|
2024
|
-
|
|
2025
|
-
|
|
2056
|
+
hasNextPage: true,
|
|
2057
|
+
nextCursor: { value: "cursor-page3" },
|
|
2026
2058
|
}),
|
|
2027
2059
|
}),
|
|
2028
2060
|
);
|
|
@@ -2034,7 +2066,7 @@ describe("records query — pagination", () => {
|
|
|
2034
2066
|
items: [{ Id: "r1", status: "active" }],
|
|
2035
2067
|
totalCount: 10,
|
|
2036
2068
|
hasNextPage: true,
|
|
2037
|
-
nextCursor: "cur-next",
|
|
2069
|
+
nextCursor: { value: "cur-next" },
|
|
2038
2070
|
});
|
|
2039
2071
|
|
|
2040
2072
|
const body = JSON.stringify({
|
|
@@ -2074,67 +2106,14 @@ describe("records query — pagination", () => {
|
|
|
2074
2106
|
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
2075
2107
|
expect.objectContaining({
|
|
2076
2108
|
Data: expect.objectContaining({
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2109
|
+
totalCount: 10,
|
|
2110
|
+
hasNextPage: true,
|
|
2111
|
+
nextCursor: { value: "cur-next" },
|
|
2080
2112
|
}),
|
|
2081
2113
|
}),
|
|
2082
2114
|
);
|
|
2083
2115
|
});
|
|
2084
2116
|
|
|
2085
|
-
it("should omit NextCursor when hasNextPage is false", async () => {
|
|
2086
|
-
const sdk = mockSdk();
|
|
2087
|
-
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
|
|
2088
|
-
items: [{ Id: "r1" }],
|
|
2089
|
-
totalCount: 1,
|
|
2090
|
-
hasNextPage: false,
|
|
2091
|
-
});
|
|
2092
|
-
|
|
2093
|
-
const program = buildProgram();
|
|
2094
|
-
await program.parseAsync([
|
|
2095
|
-
"node",
|
|
2096
|
-
"test",
|
|
2097
|
-
"records",
|
|
2098
|
-
"query",
|
|
2099
|
-
"entity-id",
|
|
2100
|
-
]);
|
|
2101
|
-
|
|
2102
|
-
const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
|
|
2103
|
-
Data: Record<string, unknown>;
|
|
2104
|
-
};
|
|
2105
|
-
expect(call.Data).not.toHaveProperty("NextCursor");
|
|
2106
|
-
});
|
|
2107
|
-
|
|
2108
|
-
it("should normalise cursor object {value} returned by SDK to a plain string", async () => {
|
|
2109
|
-
const sdk = mockSdk();
|
|
2110
|
-
// SDK may return PaginationCursor = { value: string } instead of a raw string
|
|
2111
|
-
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
|
|
2112
|
-
items: [{ Id: "r1" }, { Id: "r2" }],
|
|
2113
|
-
totalCount: 4,
|
|
2114
|
-
hasNextPage: true,
|
|
2115
|
-
nextCursor: { value: "cursor-as-object" } as unknown as string,
|
|
2116
|
-
});
|
|
2117
|
-
|
|
2118
|
-
const program = buildProgram();
|
|
2119
|
-
await program.parseAsync([
|
|
2120
|
-
"node",
|
|
2121
|
-
"test",
|
|
2122
|
-
"records",
|
|
2123
|
-
"query",
|
|
2124
|
-
"entity-id",
|
|
2125
|
-
"--limit",
|
|
2126
|
-
"2",
|
|
2127
|
-
]);
|
|
2128
|
-
|
|
2129
|
-
const call = vi.mocked(OutputFormatter.success).mock
|
|
2130
|
-
.calls[0][0] as unknown as {
|
|
2131
|
-
Data: { NextCursor: unknown };
|
|
2132
|
-
};
|
|
2133
|
-
// Must be a plain string, not the object
|
|
2134
|
-
expect(typeof call.Data.NextCursor).toBe("string");
|
|
2135
|
-
expect(call.Data.NextCursor).toBe("cursor-as-object");
|
|
2136
|
-
});
|
|
2137
|
-
|
|
2138
2117
|
it("should use default limit 50 when --cursor is given without --limit", async () => {
|
|
2139
2118
|
const sdk = mockSdk();
|
|
2140
2119
|
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue({
|
|
@@ -2240,14 +2219,14 @@ describe("records query — pagination", () => {
|
|
|
2240
2219
|
expect(process.exitCode).toBe(1);
|
|
2241
2220
|
});
|
|
2242
2221
|
|
|
2243
|
-
it("should
|
|
2222
|
+
it("should pass cursor through on the last page and return the raw result", async () => {
|
|
2244
2223
|
const sdk = mockSdk();
|
|
2245
|
-
|
|
2224
|
+
const rawResult = {
|
|
2246
2225
|
items: [{ Id: "r5" }],
|
|
2247
2226
|
totalCount: 5,
|
|
2248
2227
|
hasNextPage: false,
|
|
2249
|
-
|
|
2250
|
-
|
|
2228
|
+
};
|
|
2229
|
+
vi.mocked(sdk.entities.queryRecordsById).mockResolvedValue(rawResult);
|
|
2251
2230
|
|
|
2252
2231
|
const program = buildProgram();
|
|
2253
2232
|
await program.parseAsync([
|
|
@@ -2269,11 +2248,11 @@ describe("records query — pagination", () => {
|
|
|
2269
2248
|
cursor: { value: "cursor-page2" },
|
|
2270
2249
|
}),
|
|
2271
2250
|
);
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2251
|
+
expect(OutputFormatter.success).toHaveBeenCalledWith(
|
|
2252
|
+
expect.objectContaining({
|
|
2253
|
+
Data: rawResult,
|
|
2254
|
+
}),
|
|
2255
|
+
);
|
|
2277
2256
|
});
|
|
2278
2257
|
});
|
|
2279
2258
|
|
|
@@ -2347,6 +2326,9 @@ describe("records — negative scenarios", () => {
|
|
|
2347
2326
|
"delete",
|
|
2348
2327
|
"entity-id",
|
|
2349
2328
|
"nonexistent-record-id",
|
|
2329
|
+
"--yes",
|
|
2330
|
+
"--reason",
|
|
2331
|
+
"test cleanup",
|
|
2350
2332
|
]);
|
|
2351
2333
|
|
|
2352
2334
|
expect(OutputFormatter.error).toHaveBeenCalledWith(
|