@camunda/e2e-test-suite 0.0.608 → 0.0.610
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.
|
@@ -74,7 +74,6 @@ _8_10_1.test.describe('Cluster Setup Tests', () => {
|
|
|
74
74
|
await clusterSecretsPage.createSetOfSecrets(clusterName, (0, mcpSecrets_1.mcpSecretsValues)(mcpCredentials));
|
|
75
75
|
});
|
|
76
76
|
(0, _8_10_1.test)('Create AWS Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }, testInfo) => {
|
|
77
|
-
_8_10_1.test.skip(process.env.IS_AG === 'true', 'Skipping AWS cluster creation when IS_AG is true - will be investigated');
|
|
78
77
|
_8_10_1.test.slow();
|
|
79
78
|
const clusterName = 'AWS Cluster';
|
|
80
79
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
@@ -31,7 +31,6 @@ _8_7_1.test.describe('Cluster Setup Tests', () => {
|
|
|
31
31
|
});
|
|
32
32
|
(0, _8_7_1.test)('Create AWS Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, }, testInfo) => {
|
|
33
33
|
_8_7_1.test.skip(process.env.IS_MIGRATION === 'true', 'Skipping AWS Cluster creation during upgrade testing');
|
|
34
|
-
_8_7_1.test.skip(process.env.IS_AG === 'true', 'Skipping AWS cluster creation when IS_AG is true - will be investigated');
|
|
35
34
|
_8_7_1.test.slow();
|
|
36
35
|
const clusterName = 'AWS Cluster';
|
|
37
36
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
@@ -50,7 +50,6 @@ _8_8_1.test.describe('Cluster Setup Tests', () => {
|
|
|
50
50
|
});
|
|
51
51
|
(0, _8_8_1.test)('Create AWS Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }, testInfo) => {
|
|
52
52
|
_8_8_1.test.skip(process.env.IS_MIGRATION === 'true', 'Skipping AWS Cluster creation during upgrade testing');
|
|
53
|
-
_8_8_1.test.skip(process.env.IS_AG === 'true', 'Skipping AWS cluster creation when IS_AG is true - will be investigated');
|
|
54
53
|
_8_8_1.test.slow();
|
|
55
54
|
const clusterName = 'AWS Cluster';
|
|
56
55
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
@@ -72,7 +72,6 @@ _8_9_1.test.describe('Cluster Setup Tests', () => {
|
|
|
72
72
|
await clusterSecretsPage.assertSecretsOrCreate(clusterName, (0, mcpSecrets_1.mcpSecretsValues)(mcpCredentials));
|
|
73
73
|
});
|
|
74
74
|
(0, _8_9_1.test)('Create AWS Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }, testInfo) => {
|
|
75
|
-
_8_9_1.test.skip(process.env.IS_AG === 'true', 'Skipping AWS cluster creation when IS_AG is true - will be investigated');
|
|
76
75
|
_8_9_1.test.slow();
|
|
77
76
|
const clusterName = 'AWS Cluster';
|
|
78
77
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
package/dist/utils/apiHelpers.js
CHANGED
|
@@ -57,6 +57,34 @@ async function retryOn500(fn, maxAttempts = 3, delayMs = 3000) {
|
|
|
57
57
|
throw new Error('unreachable');
|
|
58
58
|
}
|
|
59
59
|
exports.retryOn500 = retryOn500;
|
|
60
|
+
// Retries an arbitrary async operation when it fails with a transient
|
|
61
|
+
// backend error: a 5xx response asserted via assertResponseStatus, a
|
|
62
|
+
// Playwright apiRequestContext timeout, or a socket-level network reset.
|
|
63
|
+
// Surfaces in Optimize SM upgrade nightlies where rolling restarts cause
|
|
64
|
+
// brief 5xx windows on /optimize and /optimize/api/*.
|
|
65
|
+
async function retryOnTransientApiError(fn, label, maxAttempts = 3, delayMs = 3000) {
|
|
66
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
67
|
+
try {
|
|
68
|
+
return await fn();
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
const isTransient = /Request timed out/i.test(message) ||
|
|
73
|
+
/Received:\s*5\d{2}/.test(message) ||
|
|
74
|
+
/socket hang up/i.test(message) ||
|
|
75
|
+
/ECONNRESET/.test(message) ||
|
|
76
|
+
/ECONNREFUSED/.test(message);
|
|
77
|
+
if (!isTransient || attempt === maxAttempts) {
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
console.warn(`${label}: attempt ${attempt}/${maxAttempts} failed transiently, retrying in ${delayMs}ms: ${message
|
|
81
|
+
.split('\n')[0]
|
|
82
|
+
.slice(0, 200)}`);
|
|
83
|
+
await (0, sleep_1.sleep)(delayMs);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
throw new Error('unreachable');
|
|
87
|
+
}
|
|
60
88
|
// ---- Cluster Credentials Helper ----
|
|
61
89
|
function getClusterCredentials(clusterType) {
|
|
62
90
|
if (!clusterType) {
|
|
@@ -462,14 +490,33 @@ async function getOptimizeCookieSm(page) {
|
|
|
462
490
|
const optimizeUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
463
491
|
const username = 'demo';
|
|
464
492
|
const password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD;
|
|
465
|
-
|
|
466
|
-
//
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
493
|
+
const maxLoginAttempts = 3;
|
|
494
|
+
// Upgrade scenarios trigger rolling restarts of Optimize; page.goto can
|
|
495
|
+
// briefly receive a 5xx and the Keycloak login form never renders, causing
|
|
496
|
+
// the #username selector to time out. Retry the whole login flow.
|
|
497
|
+
let lastLoginError;
|
|
498
|
+
for (let attempt = 1; attempt <= maxLoginAttempts; attempt++) {
|
|
499
|
+
try {
|
|
500
|
+
await page.goto(optimizeUrl, { timeout: 30000 });
|
|
501
|
+
await page.waitForSelector('#username', { timeout: 30000 });
|
|
502
|
+
await page.fill('#username', username);
|
|
503
|
+
await page.fill('#password', password);
|
|
504
|
+
await page.click('button[type="submit"]');
|
|
505
|
+
await page.waitForURL(`${optimizeUrl}/**`, { timeout: 30000 });
|
|
506
|
+
lastLoginError = undefined;
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
catch (error) {
|
|
510
|
+
lastLoginError = error;
|
|
511
|
+
if (attempt < maxLoginAttempts) {
|
|
512
|
+
console.warn(`getOptimizeCookieSm: login attempt ${attempt}/${maxLoginAttempts} failed (likely transient Optimize 5xx during upgrade), retrying after backoff...`, error);
|
|
513
|
+
await page.context().clearCookies();
|
|
514
|
+
await page.waitForTimeout(5000 * attempt);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (lastLoginError)
|
|
519
|
+
throw lastLoginError;
|
|
473
520
|
const context = page.context();
|
|
474
521
|
await context.storageState({ path: path_1.default.join(__dirname, '.auth_optimize_sm') });
|
|
475
522
|
const authData = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '.auth_optimize_sm'), 'utf8'));
|
|
@@ -482,39 +529,43 @@ async function getOptimizeCookieSm(page) {
|
|
|
482
529
|
}
|
|
483
530
|
exports.getOptimizeCookieSm = getOptimizeCookieSm;
|
|
484
531
|
async function createCollection(request, options) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
532
|
+
return retryOnTransientApiError(async () => {
|
|
533
|
+
const optimizeResponse = await request.post(`${process.env.CAMUNDA_OPTIMIZE_BASE_URL}/api/collection`, {
|
|
534
|
+
headers: {
|
|
535
|
+
Cookie: options.optimizeCookie,
|
|
536
|
+
},
|
|
537
|
+
data: {
|
|
538
|
+
name: options.name,
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
await assertResponseStatus(optimizeResponse, 200);
|
|
542
|
+
const optimizeResponseBody = await optimizeResponse.json();
|
|
543
|
+
return optimizeResponseBody.id;
|
|
544
|
+
}, 'createCollection');
|
|
496
545
|
}
|
|
497
546
|
exports.createCollection = createCollection;
|
|
498
547
|
async function createDashboard(request, options) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
548
|
+
return retryOnTransientApiError(async () => {
|
|
549
|
+
const optimizeResponse = await request.post(`${process.env.CAMUNDA_OPTIMIZE_BASE_URL}/api/dashboard`, {
|
|
550
|
+
headers: {
|
|
551
|
+
Cookie: options.optimizeCookie,
|
|
552
|
+
},
|
|
553
|
+
data: {
|
|
554
|
+
collectionId: options.collectionId,
|
|
555
|
+
name: options.name,
|
|
556
|
+
description: null,
|
|
557
|
+
tiles: [],
|
|
558
|
+
availableFilters: [],
|
|
559
|
+
refreshRateSeconds: null,
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
await assertResponseStatus(optimizeResponse, 200);
|
|
563
|
+
const responseBody = await optimizeResponse.json();
|
|
564
|
+
if (!responseBody?.id) {
|
|
565
|
+
throw new Error(`Expected dashboard ID in response, but got: ${JSON.stringify(responseBody, null, 2)}`);
|
|
566
|
+
}
|
|
567
|
+
return responseBody.id;
|
|
568
|
+
}, 'createDashboard');
|
|
518
569
|
}
|
|
519
570
|
exports.createDashboard = createDashboard;
|
|
520
571
|
async function createSingleProcessReport(request, options) {
|
|
@@ -575,38 +626,42 @@ async function createSingleProcessReport(request, options) {
|
|
|
575
626
|
data: {},
|
|
576
627
|
configuration: options.configuration || defaultConfiguration,
|
|
577
628
|
};
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
629
|
+
return retryOnTransientApiError(async () => {
|
|
630
|
+
const response = await request.post(`${process.env.CAMUNDA_OPTIMIZE_BASE_URL}/api/report/process/single`, {
|
|
631
|
+
headers: {
|
|
632
|
+
Cookie: options.optimizeCookie,
|
|
633
|
+
'Content-Type': 'application/json',
|
|
634
|
+
},
|
|
635
|
+
data: payload,
|
|
636
|
+
});
|
|
637
|
+
await assertResponseStatus(response, 200);
|
|
638
|
+
const responseBody = await response.json();
|
|
639
|
+
if (!responseBody?.id) {
|
|
640
|
+
throw new Error(`Expected report ID in response, but got: ${JSON.stringify(responseBody, null, 2)}`);
|
|
641
|
+
}
|
|
642
|
+
return responseBody.id;
|
|
643
|
+
}, 'createSingleProcessReport');
|
|
591
644
|
}
|
|
592
645
|
exports.createSingleProcessReport = createSingleProcessReport;
|
|
593
646
|
async function updateCollectionScope(request, options) {
|
|
594
647
|
const url = `${process.env.CAMUNDA_OPTIMIZE_BASE_URL}/api/collection/${options.collectionId}/scope`;
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
648
|
+
return retryOnTransientApiError(async () => {
|
|
649
|
+
const response = await request.put(url, {
|
|
650
|
+
headers: {
|
|
651
|
+
Cookie: options.optimizeCookie,
|
|
652
|
+
'Content-Type': 'application/json',
|
|
653
|
+
},
|
|
654
|
+
data: options.data,
|
|
655
|
+
});
|
|
656
|
+
await assertResponseStatus(response, 200);
|
|
657
|
+
let responseBody = null;
|
|
658
|
+
try {
|
|
659
|
+
responseBody = await response.json();
|
|
660
|
+
}
|
|
661
|
+
catch (err) {
|
|
662
|
+
responseBody = null;
|
|
663
|
+
}
|
|
664
|
+
return responseBody;
|
|
665
|
+
}, 'updateCollectionScope');
|
|
611
666
|
}
|
|
612
667
|
exports.updateCollectionScope = updateCollectionScope;
|