@optimizely/ocp-cli 1.2.13 → 1.2.14-beta.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.
Files changed (31) hide show
  1. package/dist/commands/app/Init.js +1 -1
  2. package/dist/commands/app/Init.js.map +1 -1
  3. package/dist/oo-cli.manifest.json +1 -1
  4. package/package.json +10 -6
  5. package/src/commands/app/Init.ts +1 -1
  6. package/src/test/e2e/__tests__/accounts/accounts.test.ts +120 -0
  7. package/src/test/e2e/__tests__/availability/availability.test.ts +156 -0
  8. package/src/test/e2e/__tests__/directory/directory.test.ts +668 -0
  9. package/src/test/e2e/__tests__/jobs/jobs.test.ts +487 -0
  10. package/src/test/e2e/__tests__/review/review.test.ts +355 -0
  11. package/src/test/e2e/config/fixture-loader.ts +130 -0
  12. package/src/test/e2e/config/setup.ts +29 -0
  13. package/src/test/e2e/config/test-data-config.ts +27 -0
  14. package/src/test/e2e/config/test-data-helpers.ts +23 -0
  15. package/src/test/e2e/fixtures/baselines/accounts/whoami.txt +11 -0
  16. package/src/test/e2e/fixtures/baselines/accounts/whois.txt +4 -0
  17. package/src/test/e2e/fixtures/baselines/directory/info.txt +7 -0
  18. package/src/test/e2e/fixtures/baselines/directory/list.txt +4 -0
  19. package/src/test/e2e/fixtures/baselines/jobs/list.txt +4 -0
  20. package/src/test/e2e/fixtures/baselines/review/list.txt +4 -0
  21. package/src/test/e2e/lib/base-test.ts +150 -0
  22. package/src/test/e2e/lib/command-discovery.ts +324 -0
  23. package/src/test/e2e/utils/baseline-normalizer.ts +79 -0
  24. package/src/test/e2e/utils/cli-executor.ts +349 -0
  25. package/src/test/e2e/utils/command-registry.ts +99 -0
  26. package/src/test/e2e/utils/output-validator.ts +661 -0
  27. package/src/test/setup.ts +3 -1
  28. package/src/test/tsconfig.json +17 -0
  29. package/dist/test/setup.d.ts +0 -0
  30. package/dist/test/setup.js +0 -4
  31. package/dist/test/setup.js.map +0 -1
@@ -0,0 +1,668 @@
1
+ import { BaseE2ETest } from '../../lib/base-test';
2
+ import { testData } from '../../config/test-data-helpers';
3
+
4
+ class DirectoryE2ETest extends BaseE2ETest {
5
+ // Directory list commands
6
+ async runListCommand(appId?: string, options?: { allStatuses?: boolean; availability?: string; useShortFlags?: boolean }) {
7
+ const args = ['directory', 'list'];
8
+ if (appId) {
9
+ args.push(appId);
10
+ }
11
+ if (options?.allStatuses) {
12
+ args.push('--allStatuses');
13
+ }
14
+ if (options?.availability) {
15
+ // Test both short and long forms based on option
16
+ if (options.useShortFlags) {
17
+ args.push(`-a=${options.availability}`);
18
+ } else {
19
+ args.push(`--availability=${options.availability}`);
20
+ }
21
+ }
22
+ return this.execute(args);
23
+ }
24
+
25
+ async runInfoCommand(appId: string, availability?: string, useShortFlags?: boolean) {
26
+ const args = ['directory', 'info', appId];
27
+ if (availability) {
28
+ if (useShortFlags) {
29
+ args.push(`-a=${availability}`);
30
+ } else {
31
+ args.push(`--availability=${availability}`);
32
+ }
33
+ }
34
+ return this.execute(args);
35
+ }
36
+
37
+ async runStatusCommand(appId?: string, availability?: string, useShortFlags?: boolean) {
38
+ const args = ['directory', 'status'];
39
+ if (appId) {
40
+ args.push(appId);
41
+ }
42
+ if (availability) {
43
+ if (useShortFlags) {
44
+ args.push(`-a=${availability}`);
45
+ } else {
46
+ args.push(`--availability=${availability}`);
47
+ }
48
+ }
49
+ return this.execute(args);
50
+ }
51
+
52
+ async runListFunctionsCommand(appId: string, trackerId: string, availability?: string, useShortFlags?: boolean) {
53
+ const args = ['directory', 'list-functions', appId, trackerId];
54
+ if (availability) {
55
+ if (useShortFlags) {
56
+ args.push(`-a=${availability}`);
57
+ } else {
58
+ args.push(`--availability=${availability}`);
59
+ }
60
+ }
61
+ return this.execute(args);
62
+ }
63
+
64
+ async runListGlobalFunctionsCommand(appId: string, availability?: string, useShortFlags?: boolean) {
65
+ const args = ['directory', 'list-global-functions', appId];
66
+ if (availability) {
67
+ if (useShortFlags) {
68
+ args.push(`-a=${availability}`);
69
+ } else {
70
+ args.push(`--availability=${availability}`);
71
+ }
72
+ }
73
+ return this.execute(args);
74
+ }
75
+
76
+ async runListInstallsCommand(appVersion: string, availability?: string, useShortFlags?: boolean) {
77
+ const args = ['directory', 'list-installs', appVersion];
78
+ if (availability) {
79
+ if (useShortFlags) {
80
+ args.push(`-a=${availability}`);
81
+ } else {
82
+ args.push(`--availability=${availability}`);
83
+ }
84
+ }
85
+ return this.execute(args);
86
+ }
87
+
88
+ async runListSourceFunctionsCommand(appId: string, trackerId: string, availability?: string, useShortFlags?: boolean) {
89
+ const args = ['directory', 'list-source-functions', appId, trackerId];
90
+ if (availability) {
91
+ if (useShortFlags) {
92
+ args.push(`-a=${availability}`);
93
+ } else {
94
+ args.push(`--availability=${availability}`);
95
+ }
96
+ }
97
+ return this.execute(args);
98
+ }
99
+
100
+ // Public wrapper methods to access protected assertions
101
+ public checkSuccess(result: any) {
102
+ this.assertSuccess(result);
103
+ }
104
+
105
+ public checkFailure(result: any) {
106
+ this.assertFailure(result);
107
+ }
108
+
109
+ public checkOutputContains(result: any, text: string) {
110
+ this.assertOutputContains(result, text);
111
+ }
112
+
113
+ public checkOutputMatchesBaseline(result: any, baselinePath: string, maxLines?: number) {
114
+ this.assertOutputMatchesBaseline(result, baselinePath, maxLines);
115
+ }
116
+
117
+ public clearHistory() {
118
+ this.cliExecutor.clearProcessHistory();
119
+ }
120
+
121
+ public executePublic(args: string[], options?: any) {
122
+ return this.execute(args, options);
123
+ }
124
+ }
125
+
126
+ describe('Directory Commands E2E Tests', () => {
127
+ let testInstance: DirectoryE2ETest;
128
+
129
+ beforeAll(() => {
130
+ testInstance = new DirectoryE2ETest();
131
+ });
132
+
133
+ afterAll(async () => {
134
+ if (testInstance) {
135
+ await testInstance.cleanup();
136
+ }
137
+ });
138
+
139
+ afterEach(() => {
140
+ // Clean up process history after each test
141
+ if (testInstance) {
142
+ testInstance.clearHistory();
143
+ }
144
+ });
145
+
146
+ describe('directory list', () => {
147
+ it('should list all directory entries successfully', async () => {
148
+ const result = await testInstance.runListCommand();
149
+
150
+ if (result.exitCode !== 0) {
151
+ // only allow failure if the user is not allowed to list all directory entries
152
+ expect(result.stderr).toContain('Could not authenticate');
153
+ } else {
154
+ // Check baseline format (first 6 lines only - header + 1 entry)
155
+ testInstance.checkOutputMatchesBaseline(result, 'directory/list.txt', 4);
156
+ }
157
+
158
+ }, 15000);
159
+
160
+ it('should filter by specific app ID', async () => {
161
+ const result = await testInstance.runListCommand(testData.appId);
162
+
163
+ expect(result.exitCode).toBe(0);
164
+ expect(result.stdout).toBeTruthy();
165
+ expect(result.stdout).toContain(testData.appId);
166
+ });
167
+
168
+ it('should include all statuses when flag is set', async () => {
169
+ const result = await testInstance.runListCommand(undefined, { allStatuses: true });
170
+
171
+ // The command might succeed or fail depending on the data, but it should run
172
+ expect([0, 1]).toContain(result.exitCode);
173
+ if (result.exitCode === 0) {
174
+ expect(result.stdout).toBeTruthy();
175
+ }
176
+ });
177
+
178
+ it('should work with availability zone parameter', async () => {
179
+ const result = await testInstance.runListCommand(undefined, { availability: 'us' });
180
+
181
+ expect(result.exitCode).toBe(0);
182
+ expect(result.stdout).toBeTruthy();
183
+ });
184
+
185
+ it('should work with availability zone parameter (short form)', async () => {
186
+ const result = await testInstance.runListCommand(undefined, { availability: 'us', useShortFlags: true });
187
+
188
+ expect(result.exitCode).toBe(0);
189
+ expect(result.stdout).toBeTruthy();
190
+ });
191
+
192
+ it('should work with availability zone parameter (long form)', async () => {
193
+ const result = await testInstance.runListCommand(undefined, { availability: 'us', useShortFlags: false });
194
+
195
+ expect(result.exitCode).toBe(0);
196
+ expect(result.stdout).toBeTruthy();
197
+ });
198
+
199
+ it('should work with multiple flags (allStatuses + availability)', async () => {
200
+ const result = await testInstance.runListCommand(undefined, { allStatuses: true, availability: 'us' });
201
+
202
+ // The command might succeed or fail depending on the data, but it should run
203
+ expect([0, 1]).toContain(result.exitCode);
204
+ if (result.exitCode === 0) {
205
+ expect(result.stdout).toBeTruthy();
206
+ }
207
+ });
208
+
209
+ it('should work with multiple flags using short form for availability', async () => {
210
+ const result = await testInstance.runListCommand(undefined, { allStatuses: true, availability: 'us', useShortFlags: true });
211
+
212
+ // The command might succeed or fail depending on the data, but it should run
213
+ expect([0, 1]).toContain(result.exitCode);
214
+ if (result.exitCode === 0) {
215
+ expect(result.stdout).toBeTruthy();
216
+ }
217
+ });
218
+
219
+ it('should complete within reasonable time', async () => {
220
+ const result = await testInstance.runListCommand(testData.appId);
221
+
222
+ expect(result.executionTime).toBeLessThan(15000); // 15 seconds
223
+ expect(result.timedOut).toBe(false);
224
+ });
225
+ });
226
+
227
+ describe('directory info', () => {
228
+ it('should return app information for valid app ID', async () => {
229
+ const result = await testInstance.runInfoCommand(testData.appId);
230
+
231
+ expect(result.exitCode).toBe(0);
232
+ expect(result.stdout).toBeTruthy();
233
+
234
+ // Check baseline format (first 12 lines only - header + General section + first version)
235
+ testInstance.checkOutputMatchesBaseline(result, 'directory/info.txt', 12);
236
+ }, 15000);
237
+
238
+ it('should work with availability zone parameter', async () => {
239
+ const result = await testInstance.runInfoCommand(testData.appId, 'us');
240
+
241
+ expect(result.exitCode).toBe(0);
242
+ expect(result.stdout).toBeTruthy();
243
+ });
244
+
245
+ it('should work with availability zone parameter (short form)', async () => {
246
+ const result = await testInstance.runInfoCommand(testData.appId, 'us', true);
247
+
248
+ expect(result.exitCode).toBe(0);
249
+ expect(result.stdout).toBeTruthy();
250
+ });
251
+
252
+ it('should work with availability zone parameter (long form)', async () => {
253
+ const result = await testInstance.runInfoCommand(testData.appId, 'us', false);
254
+
255
+ expect(result.exitCode).toBe(0);
256
+ expect(result.stdout).toBeTruthy();
257
+ });
258
+
259
+ it('should handle non-existent app ID gracefully', async () => {
260
+ const result = await testInstance.runInfoCommand('nonexistent-app-id');
261
+
262
+ expect(result.exitCode).not.toBe(0);
263
+ expect(result.stderr).toBeTruthy();
264
+ });
265
+
266
+ it('should fail when app ID parameter is missing', async () => {
267
+ const result = await testInstance.executePublic(['directory', 'info']);
268
+
269
+ expect(result.exitCode).not.toBe(0);
270
+ expect(result.stderr).toBeTruthy();
271
+ });
272
+ });
273
+
274
+ describe('directory status', () => {
275
+ it('should return status for valid app ID and version', async () => {
276
+ const result = await testInstance.runStatusCommand(testData.appVersionString);
277
+
278
+ expect(result.exitCode).toBe(0);
279
+ expect(result.stdout).toBeTruthy();
280
+
281
+ // Check for status information
282
+ expect(result.stdout).toContain('Version state:');
283
+ });
284
+
285
+ it('should work with availability zone parameter', async () => {
286
+ const result = await testInstance.runStatusCommand(testData.appVersionString, 'us');
287
+
288
+ expect(result.exitCode).toBe(0);
289
+ expect(result.stdout).toBeTruthy();
290
+ });
291
+
292
+ it('should work with availability zone parameter (short form)', async () => {
293
+ const result = await testInstance.runStatusCommand(testData.appVersionString, 'us', true);
294
+
295
+ expect(result.exitCode).toBe(0);
296
+ expect(result.stdout).toBeTruthy();
297
+ });
298
+
299
+ it('should work with availability zone parameter (long form)', async () => {
300
+ const result = await testInstance.runStatusCommand(testData.appVersionString, 'us', false);
301
+
302
+ expect(result.exitCode).toBe(0);
303
+ expect(result.stdout).toBeTruthy();
304
+ });
305
+
306
+ it('should fail when app ID and version are missing', async () => {
307
+ const result = await testInstance.runStatusCommand();
308
+
309
+ expect(result.exitCode).not.toBe(0);
310
+ expect(result.stderr).toBeTruthy();
311
+ // The error could be about missing app.yaml or missing parameters
312
+ expect(result.stderr).toMatch(/App ID and version are required|app manifest|app\.yaml/);
313
+ });
314
+
315
+ it('should handle invalid app version format', async () => {
316
+ const result = await testInstance.runStatusCommand('invalid-format');
317
+
318
+ expect(result.exitCode).not.toBe(0);
319
+ expect(result.stderr).toBeTruthy();
320
+ });
321
+ });
322
+
323
+ describe('directory list-functions', () => {
324
+ it('should list functions for valid app and tracker ID', async () => {
325
+ const result = await testInstance.runListFunctionsCommand(testData.appId, testData.trackerId);
326
+
327
+ expect(result.exitCode).toBe(0);
328
+ expect(result.stdout).toBeTruthy();
329
+ });
330
+
331
+ it('should work with availability zone parameter', async () => {
332
+ const result = await testInstance.runListFunctionsCommand(testData.appId, testData.trackerId, 'us');
333
+
334
+ expect(result.exitCode).toBe(0);
335
+ expect(result.stdout).toBeTruthy();
336
+ });
337
+
338
+ it('should work with availability zone parameter (short form)', async () => {
339
+ const result = await testInstance.runListFunctionsCommand(testData.appId, testData.trackerId, 'us', true);
340
+
341
+ expect(result.exitCode).toBe(0);
342
+ expect(result.stdout).toBeTruthy();
343
+ });
344
+
345
+ it('should work with availability zone parameter (long form)', async () => {
346
+ const result = await testInstance.runListFunctionsCommand(testData.appId, testData.trackerId, 'us', false);
347
+
348
+ expect(result.exitCode).toBe(0);
349
+ expect(result.stdout).toBeTruthy();
350
+ });
351
+
352
+ it('should fail when app ID parameter is missing', async () => {
353
+ const result = await testInstance.executePublic(['directory', 'list-functions']);
354
+
355
+ expect(result.exitCode).not.toBe(0);
356
+ expect(result.stderr).toBeTruthy();
357
+ });
358
+
359
+ it('should fail when tracker ID parameter is missing', async () => {
360
+ const result = await testInstance.executePublic(['directory', 'list-functions', testData.appId]);
361
+
362
+ expect(result.exitCode).not.toBe(0);
363
+ expect(result.stderr).toBeTruthy();
364
+ });
365
+
366
+ it('should handle non-existent app installation gracefully', async () => {
367
+ const result = await testInstance.runListFunctionsCommand('nonexistent-app', 'nonexistent-tracker');
368
+
369
+ expect(result.exitCode).not.toBe(0);
370
+ expect(result.stderr).toBeTruthy();
371
+ });
372
+ });
373
+
374
+ describe('directory list-global-functions', () => {
375
+ it('should list global functions for valid app ID', async () => {
376
+ const result = await testInstance.runListGlobalFunctionsCommand(testData.appId);
377
+
378
+ expect(result.exitCode).toBe(0);
379
+ expect(result.stdout).toBeTruthy();
380
+ });
381
+
382
+ it('should work with availability zone parameter', async () => {
383
+ const result = await testInstance.runListGlobalFunctionsCommand(testData.appId, 'us');
384
+
385
+ expect(result.exitCode).toBe(0);
386
+ expect(result.stdout).toBeTruthy();
387
+ });
388
+
389
+ it('should work with availability zone parameter (short form)', async () => {
390
+ const result = await testInstance.runListGlobalFunctionsCommand(testData.appId, 'us', true);
391
+
392
+ expect(result.exitCode).toBe(0);
393
+ expect(result.stdout).toBeTruthy();
394
+ });
395
+
396
+ it('should work with availability zone parameter (long form)', async () => {
397
+ const result = await testInstance.runListGlobalFunctionsCommand(testData.appId, 'us', false);
398
+
399
+ expect(result.exitCode).toBe(0);
400
+ expect(result.stdout).toBeTruthy();
401
+ });
402
+
403
+ it('should fail when app ID parameter is missing', async () => {
404
+ const result = await testInstance.executePublic(['directory', 'list-global-functions']);
405
+
406
+ expect(result.exitCode).not.toBe(0);
407
+ expect(result.stderr).toBeTruthy();
408
+ });
409
+
410
+ it('should handle non-existent app ID gracefully', async () => {
411
+ const result = await testInstance.runListGlobalFunctionsCommand('nonexistent-app-id');
412
+
413
+ // The command may succeed with empty results or fail - both are acceptable
414
+ expect(result.exitCode).toBeDefined();
415
+ expect(result.stdout).toBeDefined();
416
+ });
417
+ });
418
+
419
+ describe('directory list-installs', () => {
420
+ it('should list installations for valid app version', async () => {
421
+ const result = await testInstance.runListInstallsCommand(testData.appVersionString);
422
+
423
+ expect(result.exitCode).toBe(0);
424
+ expect(result.stdout).toBeTruthy();
425
+
426
+ // Check for table headers - use the actual headers from output
427
+ expect(result.stdout).toMatch(/Tracker/);
428
+ expect(result.stdout).toContain('Created At');
429
+ expect(result.stdout).toContain('Updated At');
430
+ });
431
+
432
+ it('should list installations for app without version', async () => {
433
+ const result = await testInstance.runListInstallsCommand(testData.appId);
434
+
435
+ expect(result.exitCode).toBe(0);
436
+ expect(result.stdout).toBeTruthy();
437
+ });
438
+
439
+ it('should work with availability zone parameter', async () => {
440
+ const result = await testInstance.runListInstallsCommand(testData.appVersionString, 'us');
441
+
442
+ expect(result.exitCode).toBe(0);
443
+ expect(result.stdout).toBeTruthy();
444
+ });
445
+
446
+ it('should work with availability zone parameter (short form)', async () => {
447
+ const result = await testInstance.runListInstallsCommand(testData.appVersionString, 'us', true);
448
+
449
+ expect(result.exitCode).toBe(0);
450
+ expect(result.stdout).toBeTruthy();
451
+ });
452
+
453
+ it('should work with availability zone parameter (long form)', async () => {
454
+ const result = await testInstance.runListInstallsCommand(testData.appVersionString, 'us', false);
455
+
456
+ expect(result.exitCode).toBe(0);
457
+ expect(result.stdout).toBeTruthy();
458
+ });
459
+
460
+ it('should fail when app version parameter is missing', async () => {
461
+ const result = await testInstance.executePublic(['directory', 'list-installs']);
462
+
463
+ expect(result.exitCode).not.toBe(0);
464
+ expect(result.stderr).toBeTruthy();
465
+ });
466
+
467
+ it('should handle non-existent app gracefully', async () => {
468
+ const result = await testInstance.runListInstallsCommand('nonexistent-app@1.0.0');
469
+
470
+ expect(result.exitCode).toBe(0);
471
+ expect(result.stdout).toBeTruthy();
472
+ // Should return empty results or appropriate message
473
+ });
474
+ });
475
+
476
+ describe('directory list-source-functions', () => {
477
+ it('should list source functions for valid app and tracker ID', async () => {
478
+ const result = await testInstance.runListSourceFunctionsCommand(testData.appId, testData.trackerId);
479
+
480
+ expect(result.exitCode).toBe(0);
481
+ expect(result.stdout).toBeTruthy();
482
+ });
483
+
484
+ it('should work with availability zone parameter', async () => {
485
+ const result = await testInstance.runListSourceFunctionsCommand(testData.appId, testData.trackerId, 'us');
486
+
487
+ expect(result.exitCode).toBe(0);
488
+ expect(result.stdout).toBeTruthy();
489
+ });
490
+
491
+ it('should work with availability zone parameter (short form)', async () => {
492
+ const result = await testInstance.runListSourceFunctionsCommand(testData.appId, testData.trackerId, 'us', true);
493
+
494
+ expect(result.exitCode).toBe(0);
495
+ expect(result.stdout).toBeTruthy();
496
+ });
497
+
498
+ it('should work with availability zone parameter (long form)', async () => {
499
+ const result = await testInstance.runListSourceFunctionsCommand(testData.appId, testData.trackerId, 'us', false);
500
+
501
+ expect(result.exitCode).toBe(0);
502
+ expect(result.stdout).toBeTruthy();
503
+ });
504
+
505
+ it('should fail when app ID parameter is missing', async () => {
506
+ const result = await testInstance.executePublic(['directory', 'list-source-functions']);
507
+
508
+ expect(result.exitCode).not.toBe(0);
509
+ expect(result.stderr).toBeTruthy();
510
+ });
511
+
512
+ it('should fail when tracker ID parameter is missing', async () => {
513
+ const result = await testInstance.executePublic(['directory', 'list-source-functions', testData.appId]);
514
+
515
+ expect(result.exitCode).not.toBe(0);
516
+ expect(result.stderr).toBeTruthy();
517
+ });
518
+
519
+ it('should handle non-existent app installation gracefully', async () => {
520
+ const result = await testInstance.runListSourceFunctionsCommand('nonexistent-app', 'nonexistent-tracker');
521
+
522
+ expect(result.exitCode).not.toBe(0);
523
+ expect(result.stderr).toBeTruthy();
524
+ });
525
+ });
526
+
527
+ describe('Flag Variations', () => {
528
+ describe('availability flag variations', () => {
529
+ it('should accept availability flag in various formats (short form with =)', async () => {
530
+ const result = await testInstance.executePublic(['directory', 'list', '-a=us']);
531
+
532
+ expect(result.exitCode).toBe(0);
533
+ expect(result.stdout).toBeTruthy();
534
+ });
535
+
536
+ it('should accept availability flag in various formats (long form with =)', async () => {
537
+ const result = await testInstance.executePublic(['directory', 'list', '--availability=us']);
538
+
539
+ expect(result.exitCode).toBe(0);
540
+ expect(result.stdout).toBeTruthy();
541
+ });
542
+ });
543
+
544
+ describe('allStatuses flag variations', () => {
545
+ it('should accept allStatuses flag (long form)', async () => {
546
+ const result = await testInstance.executePublic(['directory', 'list', '--allStatuses']);
547
+
548
+ // The command might succeed or fail depending on the data, but it should run
549
+ expect([0, 1]).toContain(result.exitCode);
550
+ });
551
+
552
+ it('should work with combined flags (allStatuses + availability short form)', async () => {
553
+ const result = await testInstance.executePublic(['directory', 'list', '--allStatuses', '-a=us']);
554
+
555
+ expect([0, 1]).toContain(result.exitCode);
556
+ });
557
+
558
+ it('should work with combined flags (allStatuses + availability long form)', async () => {
559
+ const result = await testInstance.executePublic(['directory', 'list', '--allStatuses', '--availability=us']);
560
+
561
+ expect([0, 1]).toContain(result.exitCode);
562
+ });
563
+
564
+ it('should work with combined flags in different order', async () => {
565
+ const result = await testInstance.executePublic(['directory', 'list', '--availability=us', '--allStatuses']);
566
+
567
+ expect([0, 1]).toContain(result.exitCode);
568
+ });
569
+ });
570
+
571
+ describe('flag validation and error handling', () => {
572
+ it('should handle invalid availability values gracefully', async () => {
573
+ const result = await testInstance.executePublic(['directory', 'list', '--availability=invalid']);
574
+
575
+ // Should either succeed with default behavior or fail gracefully
576
+ expect(result.exitCode).toBeDefined();
577
+ });
578
+
579
+ it('should handle duplicate flags gracefully (last one wins)', async () => {
580
+ const result = await testInstance.executePublic(['directory', 'list', '--availability=eu', '--availability=us']);
581
+
582
+ expect(result.exitCode).toBe(0);
583
+ expect(result.stdout).toBeTruthy();
584
+ });
585
+
586
+ it('should handle mixed short and long forms of same flag', async () => {
587
+ const result = await testInstance.executePublic(['directory', 'list', '-a=eu', '--availability=us']);
588
+
589
+ expect(result.exitCode).toBe(0);
590
+ expect(result.stdout).toBeTruthy();
591
+ });
592
+ });
593
+
594
+ describe('comprehensive flag testing across directory commands', () => {
595
+ it('should test info command with all flag variations', async () => {
596
+ const flagVariations = [
597
+ ['directory', 'info', testData.appId, '-a=us'],
598
+ ['directory', 'info', testData.appId, '--availability=us']
599
+ ];
600
+
601
+ for (const args of flagVariations) {
602
+ const result = await testInstance.executePublic(args);
603
+ expect(result.exitCode).toBe(0);
604
+ expect(result.stdout).toBeTruthy();
605
+ }
606
+ });
607
+
608
+ it('should test status command with all flag variations', async () => {
609
+ const flagVariations = [
610
+ ['directory', 'status', testData.appVersionString, '-a=us'],
611
+ ['directory', 'status', testData.appVersionString, '--availability=us']
612
+ ];
613
+
614
+ for (const args of flagVariations) {
615
+ const result = await testInstance.executePublic(args);
616
+ expect(result.exitCode).toBe(0);
617
+ expect(result.stdout).toBeTruthy();
618
+ }
619
+ });
620
+
621
+ it('should test list-installs command with all flag variations', async () => {
622
+ const flagVariations = [
623
+ ['directory', 'list-installs', testData.appVersionString, '-a=us'],
624
+ ['directory', 'list-installs', testData.appVersionString, '--availability=us']
625
+ ];
626
+
627
+ for (const args of flagVariations) {
628
+ const result = await testInstance.executePublic(args);
629
+ expect(result.exitCode).toBe(0);
630
+ expect(result.stdout).toBeTruthy();
631
+ }
632
+ });
633
+ });
634
+ });
635
+
636
+ describe('Error Scenarios', () => {
637
+ it('should handle malformed availability zone parameter', async () => {
638
+ const result = await testInstance.runListCommand(undefined, { availability: 'invalid-zone' });
639
+
640
+ // The command might still succeed but with default zone behavior
641
+ // Or it might fail - depends on API validation
642
+ expect(result.exitCode).toBeDefined();
643
+ });
644
+ });
645
+
646
+ describe('Performance Tests', () => {
647
+ it('should complete directory list within reasonable time', async () => {
648
+ const result = await testInstance.runListCommand();
649
+
650
+ expect(result.executionTime).toBeLessThan(20000); // 20 seconds
651
+ expect(result.executionTime).toBeGreaterThan(0);
652
+ }, 25000);
653
+
654
+ it('should complete directory info within reasonable time', async () => {
655
+ const result = await testInstance.runInfoCommand(testData.appId);
656
+
657
+ expect(result.executionTime).toBeLessThan(10000); // 10 seconds
658
+ expect(result.timedOut).toBe(false);
659
+ }, 15000);
660
+
661
+ it('should complete function listings within reasonable time', async () => {
662
+ const result = await testInstance.runListGlobalFunctionsCommand(testData.appId);
663
+
664
+ expect(result.executionTime).toBeLessThan(10000); // 10 seconds
665
+ expect(result.timedOut).toBe(false);
666
+ }, 15000);
667
+ });
668
+ });