@optimizely/ocp-cli 1.2.13 → 1.2.14
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,487 @@
|
|
|
1
|
+
import { BaseE2ETest } from '../../lib/base-test';
|
|
2
|
+
import { testData } from '../../config/test-data-helpers';
|
|
3
|
+
|
|
4
|
+
class JobsE2ETest extends BaseE2ETest {
|
|
5
|
+
// Jobs commands
|
|
6
|
+
async runListCommand(
|
|
7
|
+
appId: string,
|
|
8
|
+
options?: {
|
|
9
|
+
version?: string[];
|
|
10
|
+
trackerId?: string[];
|
|
11
|
+
function?: string[];
|
|
12
|
+
status?: string[];
|
|
13
|
+
minDuration?: string;
|
|
14
|
+
sortBy?: string;
|
|
15
|
+
sortDirection?: string;
|
|
16
|
+
limit?: number;
|
|
17
|
+
columns?: string;
|
|
18
|
+
from?: string;
|
|
19
|
+
to?: string;
|
|
20
|
+
availability?: string;
|
|
21
|
+
}
|
|
22
|
+
) {
|
|
23
|
+
const args = ['jobs', 'list', appId];
|
|
24
|
+
|
|
25
|
+
if (options?.version) {
|
|
26
|
+
options.version.forEach(v => args.push(`--version=${v}`));
|
|
27
|
+
}
|
|
28
|
+
if (options?.trackerId) {
|
|
29
|
+
options.trackerId.forEach(t => args.push(`--trackerId=${t}`));
|
|
30
|
+
}
|
|
31
|
+
if (options?.function) {
|
|
32
|
+
options.function.forEach(f => args.push(`--function=${f}`));
|
|
33
|
+
}
|
|
34
|
+
if (options?.status) {
|
|
35
|
+
options.status.forEach(s => args.push(`--status=${s}`));
|
|
36
|
+
}
|
|
37
|
+
if (options?.minDuration) {
|
|
38
|
+
args.push(`--minDuration=${options.minDuration}`);
|
|
39
|
+
}
|
|
40
|
+
if (options?.sortBy) {
|
|
41
|
+
args.push(`--sortBy=${options.sortBy}`);
|
|
42
|
+
}
|
|
43
|
+
if (options?.sortDirection) {
|
|
44
|
+
args.push(`--sortDirection=${options.sortDirection}`);
|
|
45
|
+
}
|
|
46
|
+
if (options?.limit) {
|
|
47
|
+
args.push(`--limit=${options.limit}`);
|
|
48
|
+
}
|
|
49
|
+
if (options?.columns) {
|
|
50
|
+
args.push(`--columns=${options.columns}`);
|
|
51
|
+
}
|
|
52
|
+
if (options?.from) {
|
|
53
|
+
args.push(`--from=${options.from}`);
|
|
54
|
+
}
|
|
55
|
+
if (options?.to) {
|
|
56
|
+
args.push(`--to=${options.to}`);
|
|
57
|
+
}
|
|
58
|
+
if (options?.availability) {
|
|
59
|
+
args.push(`-a=${options.availability}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return this.execute(args);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async runStatusCommand(jobId: string, availability?: string) {
|
|
66
|
+
const args = ['jobs', 'status', jobId];
|
|
67
|
+
if (availability) {
|
|
68
|
+
args.push(`-a=${availability}`);
|
|
69
|
+
}
|
|
70
|
+
return this.execute(args);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async runStatusCommandWithoutJobId() {
|
|
74
|
+
return this.execute(['jobs', 'status']);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Public wrapper methods to access protected assertions
|
|
78
|
+
public checkSuccess(result: any) {
|
|
79
|
+
this.assertSuccess(result);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public checkFailure(result: any) {
|
|
83
|
+
this.assertFailure(result);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public checkOutputContains(result: any, text: string) {
|
|
87
|
+
this.assertOutputContains(result, text);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public checkOutputMatchesBaseline(result: any, baselinePath: string, maxLines?: number) {
|
|
91
|
+
this.assertOutputMatchesBaseline(result, baselinePath, maxLines);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public clearHistory() {
|
|
95
|
+
this.cliExecutor.clearProcessHistory();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public executePublic(args: string[], options?: any) {
|
|
99
|
+
return this.execute(args, options);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
describe('Jobs Commands E2E Tests', () => {
|
|
104
|
+
let testInstance: JobsE2ETest;
|
|
105
|
+
|
|
106
|
+
beforeAll(() => {
|
|
107
|
+
testInstance = new JobsE2ETest();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
afterAll(async () => {
|
|
111
|
+
if (testInstance) {
|
|
112
|
+
await testInstance.cleanup();
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
afterEach(() => {
|
|
117
|
+
// Clean up process history after each test
|
|
118
|
+
if (testInstance) {
|
|
119
|
+
testInstance.clearHistory();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('jobs list', () => {
|
|
124
|
+
it('should list jobs for a valid app ID', async () => {
|
|
125
|
+
const result = await testInstance.runListCommand(testData.appId);
|
|
126
|
+
|
|
127
|
+
expect(result.exitCode).toBe(0);
|
|
128
|
+
expect(result.stdout).toBeTruthy();
|
|
129
|
+
|
|
130
|
+
// Check baseline format Headers + Table header + First job output
|
|
131
|
+
testInstance.checkOutputMatchesBaseline(result, 'jobs/list.txt', 4);
|
|
132
|
+
}, 15000);
|
|
133
|
+
|
|
134
|
+
it('should work with version filtering', async () => {
|
|
135
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
136
|
+
version: [testData.appVersion]
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
expect(result.exitCode).toBe(0);
|
|
140
|
+
expect(result.stdout).toBeTruthy();
|
|
141
|
+
}, 15000);
|
|
142
|
+
|
|
143
|
+
it('should work with tracker ID filtering', async () => {
|
|
144
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
145
|
+
trackerId: [testData.trackerId]
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (result.exitCode === 0) {
|
|
149
|
+
expect(result.stdout).toBeTruthy();
|
|
150
|
+
} else {
|
|
151
|
+
// Should fail gracefully with informative message when no jobs found
|
|
152
|
+
expect(`${result.stdout} - ${result.stderr}`).toMatch(/No jobs found/);
|
|
153
|
+
}
|
|
154
|
+
}, 15000);
|
|
155
|
+
|
|
156
|
+
it('should work with function filtering', async () => {
|
|
157
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
158
|
+
function: ['foo']
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(result.exitCode).toBe(0);
|
|
162
|
+
expect(result.stdout).toBeTruthy();
|
|
163
|
+
}, 15000);
|
|
164
|
+
|
|
165
|
+
it('should work with status filtering', async () => {
|
|
166
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
167
|
+
status: ['COMPLETE', 'RUNNING']
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
expect(result.exitCode).toBe(0);
|
|
171
|
+
expect(result.stdout).toBeTruthy();
|
|
172
|
+
}, 15000);
|
|
173
|
+
|
|
174
|
+
it('should work with multiple filters combined', async () => {
|
|
175
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
176
|
+
version: [testData.appVersion],
|
|
177
|
+
status: ['COMPLETE'],
|
|
178
|
+
limit: 10
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(result.exitCode).toBe(0);
|
|
182
|
+
expect(result.stdout).toBeTruthy();
|
|
183
|
+
}, 15000);
|
|
184
|
+
|
|
185
|
+
it('should work with date range filtering', async () => {
|
|
186
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
187
|
+
from: '30d',
|
|
188
|
+
to: '1h'
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// May return success or failure depending on if jobs exist in range
|
|
192
|
+
expect(result.exitCode).toBeDefined();
|
|
193
|
+
expect(result.stdout).toBeTruthy();
|
|
194
|
+
}, 15000);
|
|
195
|
+
|
|
196
|
+
it('should work with duration filtering', async () => {
|
|
197
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
198
|
+
minDuration: '1s'
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// May return success or failure depending on if jobs exist with that duration
|
|
202
|
+
expect(result.exitCode).toBeDefined();
|
|
203
|
+
expect(result.stdout).toBeTruthy();
|
|
204
|
+
}, 15000);
|
|
205
|
+
|
|
206
|
+
it('should work with column selection', async () => {
|
|
207
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
208
|
+
columns: 'id,status,createdAt'
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
expect(result.exitCode).toBe(0);
|
|
212
|
+
expect(result.stdout).toBeTruthy();
|
|
213
|
+
|
|
214
|
+
// Should only contain specified columns
|
|
215
|
+
expect(result.stdout).toMatch(/Job ID/);
|
|
216
|
+
expect(result.stdout).toMatch(/Status/);
|
|
217
|
+
expect(result.stdout).toMatch(/Created At/);
|
|
218
|
+
}, 15000);
|
|
219
|
+
|
|
220
|
+
it('should work with sorting options', async () => {
|
|
221
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
222
|
+
sortBy: 'createdAt',
|
|
223
|
+
sortDirection: 'asc'
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(result.exitCode).toBe(0);
|
|
227
|
+
expect(result.stdout).toBeTruthy();
|
|
228
|
+
}, 15000);
|
|
229
|
+
|
|
230
|
+
it('should work with limit parameter', async () => {
|
|
231
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
232
|
+
limit: 5
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
expect(result.exitCode).toBe(0);
|
|
236
|
+
expect(result.stdout).toBeTruthy();
|
|
237
|
+
}, 15000);
|
|
238
|
+
|
|
239
|
+
it('should work with availability zone parameter', async () => {
|
|
240
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
241
|
+
availability: 'us'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
expect(result.exitCode).toBe(0);
|
|
245
|
+
expect(result.stdout).toBeTruthy();
|
|
246
|
+
}, 15000);
|
|
247
|
+
|
|
248
|
+
it('should fail when app ID parameter is missing', async () => {
|
|
249
|
+
const result = await testInstance.executePublic(['jobs', 'list']);
|
|
250
|
+
|
|
251
|
+
expect(result.exitCode).not.toBe(0);
|
|
252
|
+
expect(result.stderr).toBeTruthy();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should handle invalid duration format gracefully', async () => {
|
|
256
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
257
|
+
minDuration: 'invalid-duration'
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
expect(result.exitCode).not.toBe(0);
|
|
261
|
+
expect(result.stderr).toBeTruthy();
|
|
262
|
+
expect(result.stderr).toMatch(/Invalid.*minDuration/);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should handle invalid sort column gracefully', async () => {
|
|
266
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
267
|
+
sortBy: 'invalidColumn'
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
expect(result.exitCode).not.toBe(0);
|
|
271
|
+
expect(result.stderr).toBeTruthy();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should handle invalid sort direction gracefully', async () => {
|
|
275
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
276
|
+
sortDirection: 'invalid'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
expect(result.exitCode).not.toBe(0);
|
|
280
|
+
expect(result.stderr).toBeTruthy();
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should handle invalid status values gracefully', async () => {
|
|
284
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
285
|
+
status: ['INVALID_STATUS']
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(result.exitCode).not.toBe(0);
|
|
289
|
+
expect(result.stderr).toBeTruthy();
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should complete within reasonable time', async () => {
|
|
293
|
+
const result = await testInstance.runListCommand(testData.appId);
|
|
294
|
+
|
|
295
|
+
expect(result.executionTime).toBeLessThan(20000); // 20 seconds
|
|
296
|
+
expect(result.timedOut).toBe(false);
|
|
297
|
+
}, 25000);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe('jobs status', () => {
|
|
301
|
+
it('should return status for valid job ID', async () => {
|
|
302
|
+
// First get a job ID from the list
|
|
303
|
+
const listResult = await testInstance.runListCommand(testData.appId, { limit: 1 });
|
|
304
|
+
|
|
305
|
+
if (listResult.exitCode === 0 && listResult.stdout.includes('No jobs found')) {
|
|
306
|
+
// Skip test if no jobs found
|
|
307
|
+
expect(true).toBe(true);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
expect(listResult.exitCode).toBe(0);
|
|
312
|
+
|
|
313
|
+
// Extract a job ID from the output (simplified approach)
|
|
314
|
+
const lines = listResult.stdout.split('\n');
|
|
315
|
+
const dataLine = lines.find(line => line.includes('-') && !line.includes('Job ID'));
|
|
316
|
+
|
|
317
|
+
if (!dataLine) {
|
|
318
|
+
// Skip test if no job data found
|
|
319
|
+
expect(true).toBe(true);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const jobId = dataLine.trim().split(/\s+/)[0];
|
|
324
|
+
|
|
325
|
+
if (jobId && jobId !== '-' && jobId.length > 5) {
|
|
326
|
+
const result = await testInstance.runStatusCommand(jobId);
|
|
327
|
+
|
|
328
|
+
expect(result.exitCode).toBe(0);
|
|
329
|
+
expect(result.stdout).toBeTruthy();
|
|
330
|
+
|
|
331
|
+
// Check for status information
|
|
332
|
+
expect(result.stdout).toMatch(/Id/);
|
|
333
|
+
expect(result.stdout).toMatch(/App Id/);
|
|
334
|
+
expect(result.stdout).toMatch(/Version/);
|
|
335
|
+
expect(result.stdout).toMatch(/Function/);
|
|
336
|
+
expect(result.stdout).toMatch(/Status/);
|
|
337
|
+
} else {
|
|
338
|
+
// Skip test if no valid job ID found
|
|
339
|
+
expect(true).toBe(true);
|
|
340
|
+
}
|
|
341
|
+
}, 25000);
|
|
342
|
+
|
|
343
|
+
it('should work with availability zone parameter', async () => {
|
|
344
|
+
// Get a job ID first
|
|
345
|
+
const listResult = await testInstance.runListCommand(testData.appId, { limit: 1 });
|
|
346
|
+
|
|
347
|
+
if (listResult.exitCode === 0 && listResult.stdout.includes('No jobs found')) {
|
|
348
|
+
expect(true).toBe(true);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const lines = listResult.stdout.split('\n');
|
|
353
|
+
const dataLine = lines.find(line => line.includes('-') && !line.includes('Job ID'));
|
|
354
|
+
|
|
355
|
+
if (!dataLine) {
|
|
356
|
+
expect(true).toBe(true);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const jobId = dataLine.trim().split(/\s+/)[0];
|
|
361
|
+
|
|
362
|
+
if (jobId && jobId !== '-' && jobId.length > 5) {
|
|
363
|
+
const result = await testInstance.runStatusCommand(jobId, 'us');
|
|
364
|
+
|
|
365
|
+
expect(result.exitCode).toBe(0);
|
|
366
|
+
expect(result.stdout).toBeTruthy();
|
|
367
|
+
} else {
|
|
368
|
+
expect(true).toBe(true);
|
|
369
|
+
}
|
|
370
|
+
}, 25000);
|
|
371
|
+
|
|
372
|
+
it('should handle non-existent job ID gracefully', async () => {
|
|
373
|
+
const result = await testInstance.runStatusCommand('nonexistent-job-id');
|
|
374
|
+
|
|
375
|
+
expect(result.exitCode).not.toBe(0);
|
|
376
|
+
expect(result.stderr).toBeTruthy();
|
|
377
|
+
}, 15000);
|
|
378
|
+
|
|
379
|
+
it('should fail when job ID parameter is missing', async () => {
|
|
380
|
+
const result = await testInstance.runStatusCommandWithoutJobId();
|
|
381
|
+
|
|
382
|
+
expect(result.exitCode).not.toBe(0);
|
|
383
|
+
expect(result.stderr).toBeTruthy();
|
|
384
|
+
expect(result.stderr).toMatch(/Job ID is required/);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should complete within reasonable time', async () => {
|
|
388
|
+
// Use a dummy job ID for timing test
|
|
389
|
+
const result = await testInstance.runStatusCommand('dummy-job-id');
|
|
390
|
+
|
|
391
|
+
expect(result.executionTime).toBeLessThan(10000); // 10 seconds
|
|
392
|
+
expect(result.timedOut).toBe(false);
|
|
393
|
+
}, 15000);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
describe('Error Scenarios', () => {
|
|
397
|
+
it('should handle malformed availability zone parameter', async () => {
|
|
398
|
+
const result = await testInstance.runListCommand(testData.appId, { availability: 'invalid-zone' });
|
|
399
|
+
expect(result.exitCode).toBeGreaterThan(0);
|
|
400
|
+
}, 15000);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
describe('Performance Tests', () => {
|
|
404
|
+
it('should complete jobs list within reasonable time', async () => {
|
|
405
|
+
const result = await testInstance.runListCommand(testData.appId);
|
|
406
|
+
|
|
407
|
+
expect(result.executionTime).toBeLessThan(20000); // 20 seconds
|
|
408
|
+
expect(result.executionTime).toBeGreaterThan(0);
|
|
409
|
+
}, 25000);
|
|
410
|
+
|
|
411
|
+
it('should complete jobs status within reasonable time', async () => {
|
|
412
|
+
const result = await testInstance.runStatusCommand('dummy-job-id');
|
|
413
|
+
|
|
414
|
+
expect(result.executionTime).toBeLessThan(10000); // 10 seconds
|
|
415
|
+
expect(result.executionTime).toBeGreaterThan(0);
|
|
416
|
+
}, 15000);
|
|
417
|
+
|
|
418
|
+
it('should handle large result sets efficiently', async () => {
|
|
419
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
420
|
+
limit: 100,
|
|
421
|
+
from: '30d'
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
expect(result.executionTime).toBeLessThan(30000); // 30 seconds
|
|
425
|
+
expect(result.timedOut).toBe(false);
|
|
426
|
+
}, 35000);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
describe('Advanced Filtering and Sorting', () => {
|
|
430
|
+
it('should work with ISO date strings', async () => {
|
|
431
|
+
const now = new Date();
|
|
432
|
+
const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
433
|
+
|
|
434
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
435
|
+
from: oneWeekAgo.toISOString(),
|
|
436
|
+
to: now.toISOString()
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
expect(result.exitCode).toBe(0);
|
|
440
|
+
expect(result.stdout).toBeTruthy();
|
|
441
|
+
}, 15000);
|
|
442
|
+
|
|
443
|
+
it('should work with epoch timestamps', async () => {
|
|
444
|
+
const now = Date.now();
|
|
445
|
+
const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000);
|
|
446
|
+
|
|
447
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
448
|
+
from: oneWeekAgo.toString(),
|
|
449
|
+
to: now.toString()
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// May return success or failure depending on data availability
|
|
453
|
+
expect(result.exitCode).toBeDefined();
|
|
454
|
+
expect(result.stdout).toBeTruthy();
|
|
455
|
+
}, 15000);
|
|
456
|
+
|
|
457
|
+
it('should sort by different columns', async () => {
|
|
458
|
+
const sortColumns = ['id', 'status', 'createdAt', 'updatedAt'];
|
|
459
|
+
|
|
460
|
+
for (const column of sortColumns) {
|
|
461
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
462
|
+
sortBy: column,
|
|
463
|
+
limit: 5
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
expect(result.exitCode).toBe(0);
|
|
467
|
+
expect(result.stdout).toBeTruthy();
|
|
468
|
+
}
|
|
469
|
+
}, 60000);
|
|
470
|
+
|
|
471
|
+
it('should work with complex multi-parameter filtering', async () => {
|
|
472
|
+
const result = await testInstance.runListCommand(testData.appId, {
|
|
473
|
+
version: [testData.appVersion],
|
|
474
|
+
function: ['foo'],
|
|
475
|
+
from: '30d',
|
|
476
|
+
sortBy: 'updatedAt',
|
|
477
|
+
sortDirection: 'desc',
|
|
478
|
+
limit: 20,
|
|
479
|
+
columns: 'id,status,function,createdAt,duration'
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
// May return success or failure depending on data availability
|
|
483
|
+
expect(result.exitCode).toBeDefined();
|
|
484
|
+
expect(result.stdout).toBeTruthy();
|
|
485
|
+
}, 20000);
|
|
486
|
+
});
|
|
487
|
+
});
|