@uipath/data-fabric-tool 1.1.0 → 1.195.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.
@@ -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) => {
@@ -17,8 +18,11 @@ vi.mock("@uipath/common", async (importOriginal) => {
17
18
  });
18
19
 
19
20
  import { OutputFormatter } from "@uipath/common";
20
- import { createDataFabricClient } from "../utils/sdk-client";
21
- import { registerChoiceSetsCommand } from "./choice-sets";
21
+ import { connectOrFail } from "../utils/sdk-client";
22
+ import {
23
+ registerChoiceSetsCommand,
24
+ registerChoiceSetValuesCommand,
25
+ } from "./choice-sets";
22
26
 
23
27
  function buildProgram(): Command {
24
28
  const program = new Command();
@@ -27,6 +31,13 @@ function buildProgram(): Command {
27
31
  return program;
28
32
  }
29
33
 
34
+ function buildValuesProgram(): Command {
35
+ const program = new Command();
36
+ program.name("test").exitOverride();
37
+ registerChoiceSetValuesCommand(program);
38
+ return program;
39
+ }
40
+
30
41
  function mockSdk(overrides: Record<string, unknown> = {}) {
31
42
  const sdk = {
32
43
  entities: {
@@ -36,11 +47,27 @@ function mockSdk(overrides: Record<string, unknown> = {}) {
36
47
  items: [],
37
48
  totalCount: 0,
38
49
  }),
50
+ create: vi.fn().mockResolvedValue("new-choice-set-id"),
51
+ updateById: vi.fn().mockResolvedValue(undefined),
52
+ deleteById: vi.fn().mockResolvedValue(undefined),
53
+ insertValueById: vi.fn().mockResolvedValue({
54
+ id: "v-new",
55
+ name: "travel",
56
+ displayName: "Travel",
57
+ numberId: 1,
58
+ }),
59
+ updateValueById: vi.fn().mockResolvedValue({
60
+ id: "v-1",
61
+ name: "travel",
62
+ displayName: "Business Travel",
63
+ numberId: 1,
64
+ }),
65
+ deleteValuesById: vi.fn().mockResolvedValue(undefined),
39
66
  ...overrides,
40
67
  },
41
68
  },
42
69
  };
43
- vi.mocked(createDataFabricClient).mockResolvedValue(sdk as never);
70
+ vi.mocked(connectOrFail).mockResolvedValue(sdk as never);
44
71
  return sdk;
45
72
  }
46
73
 
@@ -50,18 +77,21 @@ describe("choice-sets list", () => {
50
77
  process.exitCode = undefined;
51
78
  });
52
79
 
53
- it("should register the choice-sets command with list and get subcommands", () => {
80
+ it("should register the choice-sets command with list, list-values, create, update, and delete subcommands", () => {
54
81
  const program = buildProgram();
55
82
  const cmd = program.commands.find((c) => c.name() === "choice-sets");
56
83
  expect(cmd).toBeDefined();
57
84
  const subNames = cmd?.commands.map((c) => c.name()) ?? [];
58
85
  expect(subNames).toContain("list");
59
- expect(subNames).toContain("get");
86
+ expect(subNames).toContain("list-values");
87
+ expect(subNames).toContain("create");
88
+ expect(subNames).toContain("update");
89
+ expect(subNames).toContain("delete");
60
90
  });
61
91
 
62
- it("should list choice sets successfully and expose the runtime ID", async () => {
92
+ it("should list choice sets and return the verbatim SDK response", async () => {
63
93
  const sdk = mockSdk();
64
- vi.mocked(sdk.entities.choicesets.getAll).mockResolvedValue([
94
+ const rawList = [
65
95
  {
66
96
  id: "cs-uuid-1",
67
97
  name: "ExpenseTypes",
@@ -72,8 +102,11 @@ describe("choice-sets list", () => {
72
102
  updatedBy: "u-2",
73
103
  createdTime: "2026-01-01T00:00:00Z",
74
104
  updatedTime: "2026-01-02T00:00:00Z",
75
- } as never,
76
- ]);
105
+ },
106
+ ];
107
+ vi.mocked(sdk.entities.choicesets.getAll).mockResolvedValue(
108
+ rawList as never,
109
+ );
77
110
 
78
111
  const program = buildProgram();
79
112
  await program.parseAsync(["node", "test", "choice-sets", "list"]);
@@ -82,13 +115,7 @@ describe("choice-sets list", () => {
82
115
  expect.objectContaining({
83
116
  Result: "Success",
84
117
  Code: "ChoiceSetList",
85
- Data: expect.arrayContaining([
86
- expect.objectContaining({
87
- ID: "cs-uuid-1",
88
- Name: "ExpenseTypes",
89
- DisplayName: "Expense Types",
90
- }),
91
- ]),
118
+ Data: rawList,
92
119
  }),
93
120
  );
94
121
  });
@@ -122,31 +149,25 @@ describe("choice-sets list", () => {
122
149
  expect(process.exitCode).toBe(1);
123
150
  });
124
151
 
125
- it("should error when SDK connection fails on list", async () => {
126
- vi.mocked(createDataFabricClient).mockRejectedValue(
127
- new Error("Not logged in"),
128
- );
152
+ it("should not proceed with list when the client connection fails", async () => {
153
+ const sdk = mockSdk();
154
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
129
155
  const program = buildProgram();
130
156
  await program.parseAsync(["node", "test", "choice-sets", "list"]);
131
- expect(OutputFormatter.error).toHaveBeenCalledWith(
132
- expect.objectContaining({
133
- Result: "Failure",
134
- Message: "Error connecting to Data Fabric",
135
- }),
136
- );
137
- expect(process.exitCode).toBe(1);
157
+ expect(sdk.entities.choicesets.getAll).not.toHaveBeenCalled();
158
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
138
159
  });
139
160
  });
140
161
 
141
- describe("choice-sets get", () => {
162
+ describe("choice-sets list-values", () => {
142
163
  beforeEach(() => {
143
164
  vi.resetAllMocks();
144
165
  process.exitCode = undefined;
145
166
  });
146
167
 
147
- it("should get values for a choice set", async () => {
168
+ it("should get values for a choice set and return the verbatim SDK response", async () => {
148
169
  const sdk = mockSdk();
149
- vi.mocked(sdk.entities.choicesets.getById).mockResolvedValue({
170
+ const rawResponse = {
150
171
  items: [
151
172
  {
152
173
  id: "v-1",
@@ -159,14 +180,17 @@ describe("choice-sets get", () => {
159
180
  ],
160
181
  totalCount: 1,
161
182
  hasNextPage: false,
162
- });
183
+ };
184
+ vi.mocked(sdk.entities.choicesets.getById).mockResolvedValue(
185
+ rawResponse as never,
186
+ );
163
187
 
164
188
  const program = buildProgram();
165
189
  await program.parseAsync([
166
190
  "node",
167
191
  "test",
168
192
  "choice-sets",
169
- "get",
193
+ "list-values",
170
194
  "cs-1",
171
195
  ]);
172
196
 
@@ -177,43 +201,28 @@ describe("choice-sets get", () => {
177
201
  expect.objectContaining({
178
202
  Result: "Success",
179
203
  Code: "ChoiceSetValues",
180
- Data: expect.objectContaining({
181
- TotalCount: 1,
182
- Values: expect.arrayContaining([
183
- expect.objectContaining({
184
- Id: "v-1",
185
- Name: "travel",
186
- DisplayName: "Travel",
187
- NumberId: 1,
188
- }),
189
- ]),
190
- HasNextPage: false,
191
- }),
204
+ Data: rawResponse,
192
205
  }),
193
206
  );
194
207
  });
195
208
 
196
- it("should pass cursor to choicesets.getById and include NextCursor", async () => {
209
+ it("should pass cursor to choicesets.getById and return the raw response", async () => {
197
210
  const sdk = mockSdk();
198
- vi.mocked(sdk.entities.choicesets.getById).mockResolvedValue({
199
- items: [
200
- {
201
- id: "v-1",
202
- name: "n",
203
- displayName: "N",
204
- numberId: 1,
205
- },
206
- ],
211
+ const rawResponse = {
212
+ items: [{ id: "v-1", name: "n", displayName: "N", numberId: 1 }],
207
213
  totalCount: 100,
208
214
  hasNextPage: true,
209
215
  nextCursor: "next-cur",
210
- });
216
+ };
217
+ vi.mocked(sdk.entities.choicesets.getById).mockResolvedValue(
218
+ rawResponse as never,
219
+ );
211
220
  const program = buildProgram();
212
221
  await program.parseAsync([
213
222
  "node",
214
223
  "test",
215
224
  "choice-sets",
216
- "get",
225
+ "list-values",
217
226
  "cs-1",
218
227
  "--cursor",
219
228
  "prev",
@@ -227,8 +236,8 @@ describe("choice-sets get", () => {
227
236
  expect(OutputFormatter.success).toHaveBeenCalledWith(
228
237
  expect.objectContaining({
229
238
  Data: expect.objectContaining({
230
- HasNextPage: true,
231
- NextCursor: "next-cur",
239
+ hasNextPage: true,
240
+ nextCursor: "next-cur",
232
241
  }),
233
242
  }),
234
243
  );
@@ -246,7 +255,7 @@ describe("choice-sets get", () => {
246
255
  "node",
247
256
  "test",
248
257
  "choice-sets",
249
- "get",
258
+ "list-values",
250
259
  "cs-1",
251
260
  "--offset",
252
261
  "20",
@@ -266,7 +275,7 @@ describe("choice-sets get", () => {
266
275
  "node",
267
276
  "test",
268
277
  "choice-sets",
269
- "get",
278
+ "list-values",
270
279
  "cs-1",
271
280
  "--offset",
272
281
  "10",
@@ -289,7 +298,7 @@ describe("choice-sets get", () => {
289
298
  "node",
290
299
  "test",
291
300
  "choice-sets",
292
- "get",
301
+ "list-values",
293
302
  "cs-1",
294
303
  "--limit",
295
304
  "0",
@@ -310,7 +319,7 @@ describe("choice-sets get", () => {
310
319
  "node",
311
320
  "test",
312
321
  "choice-sets",
313
- "get",
322
+ "list-values",
314
323
  "cs-1",
315
324
  "--offset",
316
325
  "-1",
@@ -334,7 +343,7 @@ describe("choice-sets get", () => {
334
343
  "node",
335
344
  "test",
336
345
  "choice-sets",
337
- "get",
346
+ "list-values",
338
347
  "missing",
339
348
  ]);
340
349
  expect(OutputFormatter.error).toHaveBeenCalledWith(
@@ -346,49 +355,495 @@ describe("choice-sets get", () => {
346
355
  expect(process.exitCode).toBe(1);
347
356
  });
348
357
 
349
- it("should error when SDK connection fails on get", async () => {
350
- vi.mocked(createDataFabricClient).mockRejectedValue(
351
- new Error("Not logged in"),
358
+ it("should not proceed with get when the client connection fails", async () => {
359
+ const sdk = mockSdk();
360
+ vi.mocked(connectOrFail).mockResolvedValue(undefined);
361
+ const program = buildProgram();
362
+ await program.parseAsync([
363
+ "node",
364
+ "test",
365
+ "choice-sets",
366
+ "list-values",
367
+ "cs-1",
368
+ ]);
369
+ expect(sdk.entities.choicesets.getById).not.toHaveBeenCalled();
370
+ expect(OutputFormatter.success).not.toHaveBeenCalled();
371
+ });
372
+ });
373
+
374
+ describe("choice-sets create", () => {
375
+ beforeEach(() => {
376
+ vi.resetAllMocks();
377
+ process.exitCode = undefined;
378
+ });
379
+
380
+ it("should create a choice set with options and return the ID", async () => {
381
+ const sdk = mockSdk();
382
+ const program = buildProgram();
383
+ await program.parseAsync([
384
+ "node",
385
+ "test",
386
+ "choice-sets",
387
+ "create",
388
+ "ExpenseTypes",
389
+ "--display-name",
390
+ "Expense Types",
391
+ "--description",
392
+ "Categories",
393
+ "--folder-key",
394
+ "folder-1",
395
+ ]);
396
+
397
+ expect(sdk.entities.choicesets.create).toHaveBeenCalledWith(
398
+ "ExpenseTypes",
399
+ {
400
+ displayName: "Expense Types",
401
+ description: "Categories",
402
+ folderKey: "folder-1",
403
+ },
404
+ );
405
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
406
+ expect.objectContaining({
407
+ Result: "Success",
408
+ Code: "ChoiceSetCreated",
409
+ Data: { ID: "new-choice-set-id" },
410
+ }),
411
+ );
412
+ });
413
+
414
+ it("should create a choice set with no options (undefined opts)", async () => {
415
+ const sdk = mockSdk();
416
+ const program = buildProgram();
417
+ await program.parseAsync([
418
+ "node",
419
+ "test",
420
+ "choice-sets",
421
+ "create",
422
+ "ExpenseTypes",
423
+ ]);
424
+ expect(sdk.entities.choicesets.create).toHaveBeenCalledWith(
425
+ "ExpenseTypes",
426
+ undefined,
427
+ );
428
+ });
429
+
430
+ it("should output error when create fails", async () => {
431
+ const sdk = mockSdk();
432
+ vi.mocked(sdk.entities.choicesets.create).mockRejectedValue(
433
+ new Error("conflict"),
434
+ );
435
+ const program = buildProgram();
436
+ await program.parseAsync([
437
+ "node",
438
+ "test",
439
+ "choice-sets",
440
+ "create",
441
+ "X",
442
+ ]);
443
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
444
+ expect.objectContaining({
445
+ Result: "Failure",
446
+ Message: "Error creating choice set",
447
+ }),
448
+ );
449
+ expect(process.exitCode).toBe(1);
450
+ });
451
+ });
452
+
453
+ describe("choice-sets update", () => {
454
+ beforeEach(() => {
455
+ vi.resetAllMocks();
456
+ process.exitCode = undefined;
457
+ });
458
+
459
+ it("should update a choice set's metadata", async () => {
460
+ const sdk = mockSdk();
461
+ const program = buildProgram();
462
+ await program.parseAsync([
463
+ "node",
464
+ "test",
465
+ "choice-sets",
466
+ "update",
467
+ "cs-1",
468
+ "--display-name",
469
+ "New Name",
470
+ ]);
471
+ expect(sdk.entities.choicesets.updateById).toHaveBeenCalledWith(
472
+ "cs-1",
473
+ {
474
+ displayName: "New Name",
475
+ },
352
476
  );
477
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
478
+ expect.objectContaining({
479
+ Result: "Success",
480
+ Code: "ChoiceSetUpdated",
481
+ Data: { ID: "cs-1" },
482
+ }),
483
+ );
484
+ });
485
+
486
+ it("should error when no update fields are provided", async () => {
487
+ const sdk = mockSdk();
353
488
  const program = buildProgram();
354
489
  await program.parseAsync([
355
490
  "node",
356
491
  "test",
357
492
  "choice-sets",
358
- "get",
493
+ "update",
359
494
  "cs-1",
360
495
  ]);
496
+ expect(sdk.entities.choicesets.updateById).not.toHaveBeenCalled();
361
497
  expect(OutputFormatter.error).toHaveBeenCalledWith(
362
498
  expect.objectContaining({
363
499
  Result: "Failure",
364
- Message: "Error connecting to Data Fabric",
500
+ Message: "No update fields provided",
365
501
  }),
366
502
  );
367
503
  expect(process.exitCode).toBe(1);
368
504
  });
369
505
 
370
- it("should normalise cursor object {value} to a plain string in NextCursor", async () => {
506
+ it("should output error when update fails", async () => {
371
507
  const sdk = mockSdk();
372
- vi.mocked(sdk.entities.choicesets.getById).mockResolvedValue({
373
- items: [{ id: "v-1", name: "n", displayName: "N", numberId: 1 }],
374
- totalCount: 5,
375
- hasNextPage: true,
376
- nextCursor: { value: "cursor-as-object" } as unknown as string,
377
- });
508
+ vi.mocked(sdk.entities.choicesets.updateById).mockRejectedValue(
509
+ new Error("404"),
510
+ );
378
511
  const program = buildProgram();
379
512
  await program.parseAsync([
380
513
  "node",
381
514
  "test",
382
515
  "choice-sets",
383
- "get",
516
+ "update",
517
+ "missing",
518
+ "--description",
519
+ "x",
520
+ ]);
521
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
522
+ expect.objectContaining({
523
+ Result: "Failure",
524
+ Message: "Error updating choice set 'missing'",
525
+ }),
526
+ );
527
+ expect(process.exitCode).toBe(1);
528
+ });
529
+ });
530
+
531
+ describe("choice-sets delete", () => {
532
+ beforeEach(() => {
533
+ vi.resetAllMocks();
534
+ process.exitCode = undefined;
535
+ });
536
+
537
+ it("should delete a choice set with --confirm and --reason", async () => {
538
+ const sdk = mockSdk();
539
+ const program = buildProgram();
540
+ await program.parseAsync([
541
+ "node",
542
+ "test",
543
+ "choice-sets",
544
+ "delete",
384
545
  "cs-1",
385
- "--limit",
386
- "2",
546
+ "--confirm",
547
+ "--reason",
548
+ "cleanup",
387
549
  ]);
388
- const call = vi.mocked(OutputFormatter.success).mock.calls[0][0] as {
389
- Data: { NextCursor: unknown };
390
- };
391
- expect(typeof call.Data.NextCursor).toBe("string");
392
- expect(call.Data.NextCursor).toBe("cursor-as-object");
550
+ expect(sdk.entities.choicesets.deleteById).toHaveBeenCalledWith("cs-1");
551
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
552
+ expect.objectContaining({
553
+ Result: "Success",
554
+ Code: "ChoiceSetDeleted",
555
+ Data: { ID: "cs-1", Reason: "cleanup" },
556
+ }),
557
+ );
558
+ });
559
+
560
+ it("should require --confirm", async () => {
561
+ const sdk = mockSdk();
562
+ const program = buildProgram();
563
+ await program.parseAsync([
564
+ "node",
565
+ "test",
566
+ "choice-sets",
567
+ "delete",
568
+ "cs-1",
569
+ "--reason",
570
+ "cleanup",
571
+ ]);
572
+ expect(sdk.entities.choicesets.deleteById).not.toHaveBeenCalled();
573
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
574
+ expect.objectContaining({
575
+ Result: "Failure",
576
+ Message: "Confirmation required for destructive operation",
577
+ }),
578
+ );
579
+ expect(process.exitCode).toBe(1);
580
+ });
581
+
582
+ it("should require --reason", async () => {
583
+ const sdk = mockSdk();
584
+ const program = buildProgram();
585
+ await program.parseAsync([
586
+ "node",
587
+ "test",
588
+ "choice-sets",
589
+ "delete",
590
+ "cs-1",
591
+ "--confirm",
592
+ ]);
593
+ expect(sdk.entities.choicesets.deleteById).not.toHaveBeenCalled();
594
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
595
+ expect.objectContaining({
596
+ Result: "Failure",
597
+ Message: "Reason required for destructive operation",
598
+ }),
599
+ );
600
+ expect(process.exitCode).toBe(1);
601
+ });
602
+ });
603
+
604
+ describe("choice-set-values", () => {
605
+ beforeEach(() => {
606
+ vi.resetAllMocks();
607
+ process.exitCode = undefined;
608
+ });
609
+
610
+ it("should register the choice-set-values command with create, update, and delete subcommands", () => {
611
+ const program = buildValuesProgram();
612
+ const cmd = program.commands.find(
613
+ (c) => c.name() === "choice-set-values",
614
+ );
615
+ expect(cmd).toBeDefined();
616
+ const subNames = cmd?.commands.map((c) => c.name()) ?? [];
617
+ expect(subNames).toContain("create");
618
+ expect(subNames).toContain("update");
619
+ expect(subNames).toContain("delete");
620
+ });
621
+
622
+ it("should create a value and project the response", async () => {
623
+ const sdk = mockSdk();
624
+ const program = buildValuesProgram();
625
+ await program.parseAsync([
626
+ "node",
627
+ "test",
628
+ "choice-set-values",
629
+ "create",
630
+ "cs-1",
631
+ "travel",
632
+ "--display-name",
633
+ "Travel",
634
+ ]);
635
+ expect(sdk.entities.choicesets.insertValueById).toHaveBeenCalledWith(
636
+ "cs-1",
637
+ "travel",
638
+ { displayName: "Travel" },
639
+ );
640
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
641
+ expect.objectContaining({
642
+ Result: "Success",
643
+ Code: "ChoiceSetValueCreated",
644
+ Data: expect.objectContaining({
645
+ id: "v-new",
646
+ name: "travel",
647
+ displayName: "Travel",
648
+ numberId: 1,
649
+ }),
650
+ }),
651
+ );
652
+ });
653
+
654
+ it("should create a value with no display name (undefined opts)", async () => {
655
+ const sdk = mockSdk();
656
+ const program = buildValuesProgram();
657
+ await program.parseAsync([
658
+ "node",
659
+ "test",
660
+ "choice-set-values",
661
+ "create",
662
+ "cs-1",
663
+ "travel",
664
+ ]);
665
+ expect(sdk.entities.choicesets.insertValueById).toHaveBeenCalledWith(
666
+ "cs-1",
667
+ "travel",
668
+ undefined,
669
+ );
670
+ });
671
+
672
+ it("should output error when value create fails", async () => {
673
+ const sdk = mockSdk();
674
+ vi.mocked(sdk.entities.choicesets.insertValueById).mockRejectedValue(
675
+ new Error("conflict"),
676
+ );
677
+ const program = buildValuesProgram();
678
+ await program.parseAsync([
679
+ "node",
680
+ "test",
681
+ "choice-set-values",
682
+ "create",
683
+ "cs-1",
684
+ "travel",
685
+ ]);
686
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
687
+ expect.objectContaining({
688
+ Result: "Failure",
689
+ Message: "Error creating value in choice set 'cs-1'",
690
+ }),
691
+ );
692
+ expect(process.exitCode).toBe(1);
693
+ });
694
+
695
+ it("should update a value's display name", async () => {
696
+ const sdk = mockSdk();
697
+ const program = buildValuesProgram();
698
+ await program.parseAsync([
699
+ "node",
700
+ "test",
701
+ "choice-set-values",
702
+ "update",
703
+ "cs-1",
704
+ "v-1",
705
+ "Business Travel",
706
+ ]);
707
+ expect(sdk.entities.choicesets.updateValueById).toHaveBeenCalledWith(
708
+ "cs-1",
709
+ "v-1",
710
+ "Business Travel",
711
+ );
712
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
713
+ expect.objectContaining({
714
+ Result: "Success",
715
+ Code: "ChoiceSetValueUpdated",
716
+ Data: expect.objectContaining({
717
+ id: "v-1",
718
+ displayName: "Business Travel",
719
+ }),
720
+ }),
721
+ );
722
+ });
723
+
724
+ it("should output error when value update fails", async () => {
725
+ const sdk = mockSdk();
726
+ vi.mocked(sdk.entities.choicesets.updateValueById).mockRejectedValue(
727
+ new Error("404"),
728
+ );
729
+ const program = buildValuesProgram();
730
+ await program.parseAsync([
731
+ "node",
732
+ "test",
733
+ "choice-set-values",
734
+ "update",
735
+ "cs-1",
736
+ "missing",
737
+ "X",
738
+ ]);
739
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
740
+ expect.objectContaining({
741
+ Result: "Failure",
742
+ Message: "Error updating value 'missing' in choice set 'cs-1'",
743
+ }),
744
+ );
745
+ expect(process.exitCode).toBe(1);
746
+ });
747
+
748
+ it("should delete values from a comma-separated --ids list", async () => {
749
+ const sdk = mockSdk();
750
+ const program = buildValuesProgram();
751
+ await program.parseAsync([
752
+ "node",
753
+ "test",
754
+ "choice-set-values",
755
+ "delete",
756
+ "cs-1",
757
+ "--ids",
758
+ "v-1, v-2 ,v-3",
759
+ "--confirm",
760
+ "--reason",
761
+ "cleanup",
762
+ ]);
763
+ expect(sdk.entities.choicesets.deleteValuesById).toHaveBeenCalledWith(
764
+ "cs-1",
765
+ ["v-1", "v-2", "v-3"],
766
+ );
767
+ expect(OutputFormatter.success).toHaveBeenCalledWith(
768
+ expect.objectContaining({
769
+ Result: "Success",
770
+ Code: "ChoiceSetValuesDeleted",
771
+ Data: {
772
+ ChoiceSetId: "cs-1",
773
+ DeletedIds: ["v-1", "v-2", "v-3"],
774
+ Reason: "cleanup",
775
+ },
776
+ }),
777
+ );
778
+ });
779
+
780
+ it("should error when --ids is missing or empty", async () => {
781
+ const sdk = mockSdk();
782
+ const program = buildValuesProgram();
783
+ await program.parseAsync([
784
+ "node",
785
+ "test",
786
+ "choice-set-values",
787
+ "delete",
788
+ "cs-1",
789
+ "--confirm",
790
+ "--reason",
791
+ "cleanup",
792
+ ]);
793
+ expect(sdk.entities.choicesets.deleteValuesById).not.toHaveBeenCalled();
794
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
795
+ expect.objectContaining({
796
+ Result: "Failure",
797
+ Message: "No value IDs provided",
798
+ }),
799
+ );
800
+ expect(process.exitCode).toBe(1);
801
+ });
802
+
803
+ it("should require --confirm for value delete", async () => {
804
+ const sdk = mockSdk();
805
+ const program = buildValuesProgram();
806
+ await program.parseAsync([
807
+ "node",
808
+ "test",
809
+ "choice-set-values",
810
+ "delete",
811
+ "cs-1",
812
+ "--ids",
813
+ "v-1",
814
+ "--reason",
815
+ "cleanup",
816
+ ]);
817
+ expect(sdk.entities.choicesets.deleteValuesById).not.toHaveBeenCalled();
818
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
819
+ expect.objectContaining({
820
+ Result: "Failure",
821
+ Message: "Confirmation required for destructive operation",
822
+ }),
823
+ );
824
+ expect(process.exitCode).toBe(1);
825
+ });
826
+
827
+ it("should require --reason for value delete", async () => {
828
+ const sdk = mockSdk();
829
+ const program = buildValuesProgram();
830
+ await program.parseAsync([
831
+ "node",
832
+ "test",
833
+ "choice-set-values",
834
+ "delete",
835
+ "cs-1",
836
+ "--ids",
837
+ "v-1",
838
+ "--confirm",
839
+ ]);
840
+ expect(sdk.entities.choicesets.deleteValuesById).not.toHaveBeenCalled();
841
+ expect(OutputFormatter.error).toHaveBeenCalledWith(
842
+ expect.objectContaining({
843
+ Result: "Failure",
844
+ Message: "Reason required for destructive operation",
845
+ }),
846
+ );
847
+ expect(process.exitCode).toBe(1);
393
848
  });
394
849
  });