@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.
- package/dist/commands/app/Init.js +1 -1
- package/dist/commands/app/Init.js.map +1 -1
- package/dist/oo-cli.manifest.json +1 -1
- package/package.json +10 -6
- package/src/commands/app/Init.ts +1 -1
- package/src/test/e2e/__tests__/accounts/accounts.test.ts +120 -0
- package/src/test/e2e/__tests__/availability/availability.test.ts +156 -0
- package/src/test/e2e/__tests__/directory/directory.test.ts +668 -0
- package/src/test/e2e/__tests__/jobs/jobs.test.ts +487 -0
- package/src/test/e2e/__tests__/review/review.test.ts +355 -0
- package/src/test/e2e/config/fixture-loader.ts +130 -0
- package/src/test/e2e/config/setup.ts +29 -0
- package/src/test/e2e/config/test-data-config.ts +27 -0
- package/src/test/e2e/config/test-data-helpers.ts +23 -0
- package/src/test/e2e/fixtures/baselines/accounts/whoami.txt +11 -0
- package/src/test/e2e/fixtures/baselines/accounts/whois.txt +4 -0
- package/src/test/e2e/fixtures/baselines/directory/info.txt +7 -0
- package/src/test/e2e/fixtures/baselines/directory/list.txt +4 -0
- package/src/test/e2e/fixtures/baselines/jobs/list.txt +4 -0
- package/src/test/e2e/fixtures/baselines/review/list.txt +4 -0
- package/src/test/e2e/lib/base-test.ts +150 -0
- package/src/test/e2e/lib/command-discovery.ts +324 -0
- package/src/test/e2e/utils/baseline-normalizer.ts +79 -0
- package/src/test/e2e/utils/cli-executor.ts +349 -0
- package/src/test/e2e/utils/command-registry.ts +99 -0
- package/src/test/e2e/utils/output-validator.ts +661 -0
- package/src/test/setup.ts +3 -1
- package/src/test/tsconfig.json +17 -0
- package/dist/test/setup.d.ts +0 -0
- package/dist/test/setup.js +0 -4
- 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
|
+
});
|