@camunda/e2e-test-suite 0.0.837 → 0.0.839
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/pages/8.9/ClusterDetailsPage.js +88 -16
- package/dist/pages/8.9/ClusterPage.js +6 -1
- package/dist/pages/8.9/FormJsPage.js +1 -1
- package/dist/pages/8.9/HomePage.js +5 -1
- package/dist/pages/8.9/ModelerCreatePage.js +8 -7
- package/dist/pages/8.9/ModelerHomePage.js +64 -13
- package/dist/pages/8.9/TaskPanelPage.js +12 -1
- package/dist/tests/8.9/console-user-flows.spec.js +11 -0
- package/dist/tests/8.9/test-setup.spec.js +22 -9
- package/dist/utils/consoleApiHelpers.js +7 -0
- package/package.json +1 -1
|
@@ -476,22 +476,94 @@ class ClusterDetailsPage {
|
|
|
476
476
|
return variables;
|
|
477
477
|
}
|
|
478
478
|
async createAPIClient(name) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
479
|
+
const maxRetries = 3;
|
|
480
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
481
|
+
// Use a suffixed name on retries so duplicate-name validation never
|
|
482
|
+
// leaves the Create button permanently disabled. A prior attempt may
|
|
483
|
+
// have created the client before we could detect the credentials dialog.
|
|
484
|
+
const attemptName = attempt === 0 ? name : `${name}-r${attempt}`;
|
|
485
|
+
try {
|
|
486
|
+
await this.clickCreateClientButton();
|
|
487
|
+
await (0, test_1.expect)(this.createClientCredentialsDialog).toBeVisible({
|
|
488
|
+
timeout: 30000,
|
|
489
|
+
});
|
|
490
|
+
await this.fillAPIClientName(attemptName);
|
|
491
|
+
await this.checkOrchestrationClusterCheckbox();
|
|
492
|
+
await this.checkOptimizeCheckbox();
|
|
493
|
+
await this.checkSecretsCheckbox();
|
|
494
|
+
await this.clickCreateButton();
|
|
495
|
+
// The POST behind Create occasionally returns "fetch error" — the
|
|
496
|
+
// create dialog stays open with an in-modal "Error fetch error"
|
|
497
|
+
// banner and the success ("Client credentials" / "The Client
|
|
498
|
+
// Secret will not be shown again.") dialog never appears. Detect
|
|
499
|
+
// that state and retry instead of burning 60s on a visibility
|
|
500
|
+
// assertion that will never resolve.
|
|
501
|
+
const credentialsShown = await this.clientCredentialsDialog
|
|
502
|
+
.isVisible({ timeout: 30000 })
|
|
503
|
+
.catch(() => false);
|
|
504
|
+
if (!credentialsShown) {
|
|
505
|
+
const stuckCreateDialog = await this.createClientCredentialsDialog
|
|
506
|
+
.isVisible({ timeout: 500 })
|
|
507
|
+
.catch(() => false);
|
|
508
|
+
const fetchError = stuckCreateDialog
|
|
509
|
+
? await this.createClientCredentialsDialog
|
|
510
|
+
.getByText(/fetch error/i)
|
|
511
|
+
.isVisible({ timeout: 500 })
|
|
512
|
+
.catch(() => false)
|
|
513
|
+
: false;
|
|
514
|
+
if (stuckCreateDialog && fetchError) {
|
|
515
|
+
throw new Error('createAPIClient: create dialog stuck with "fetch error"');
|
|
516
|
+
}
|
|
517
|
+
// Not the fetch-error path — fall through to the original
|
|
518
|
+
// visibility expectation so the failure surface stays informative.
|
|
519
|
+
await (0, test_1.expect)(this.clientCredentialsDialog).toBeVisible({
|
|
520
|
+
timeout: 30000,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
await (0, test_1.expect)(this.clientCredentialsDialog
|
|
524
|
+
.getByText('The Client Secret will not be shown again.')
|
|
525
|
+
.first()).toBeVisible();
|
|
526
|
+
try {
|
|
527
|
+
await (0, test_1.expect)(this.clientsList.filter({ hasText: attemptName })).toContainText(/(?=.*Orchestration)(?=.*Optimize)(?=.*Secrets)/, {
|
|
528
|
+
timeout: 10000,
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
catch (err) {
|
|
532
|
+
// The clients list panel can land in "Oops ... something went wrong."
|
|
533
|
+
// while the post-create modal is still open. The modal blocks pointer
|
|
534
|
+
// events so we can't click Reload here; the modal's "Client Secret will
|
|
535
|
+
// not be shown again" message above already proves the client exists.
|
|
536
|
+
const oopsVisible = await this.page
|
|
537
|
+
.getByRole('heading', { name: /Oops/i })
|
|
538
|
+
.isVisible({ timeout: 1000 })
|
|
539
|
+
.catch(() => false);
|
|
540
|
+
if (!oopsVisible)
|
|
541
|
+
throw err;
|
|
542
|
+
console.warn(`createAPIClient: clients list panel is in Oops state; skipping row scope assertion for "${attemptName}".`);
|
|
543
|
+
}
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
if (attempt < maxRetries - 1) {
|
|
548
|
+
console.warn(`createAPIClient attempt ${attempt + 1} for "${name}" failed: ${error}; cancelling any stuck dialog and reloading.`);
|
|
549
|
+
// Cancel the stuck create dialog if it's still open, then reload
|
|
550
|
+
// the API tab so the next attempt starts from a clean state.
|
|
551
|
+
const cancel = this.createClientCredentialsDialog.getByRole('button', { name: 'Cancel' });
|
|
552
|
+
if (await cancel.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
553
|
+
await cancel.click({ timeout: 5000 }).catch(() => { });
|
|
554
|
+
}
|
|
555
|
+
await this.page.keyboard.press('Escape').catch(() => { });
|
|
556
|
+
await this.page
|
|
557
|
+
.reload({ waitUntil: 'domcontentloaded' })
|
|
558
|
+
.catch(() => { });
|
|
559
|
+
// The API tab needs to be re-selected after reload.
|
|
560
|
+
await this.clickAPITab().catch(() => { });
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
throw new Error(`Creating API client "${name}" failed after ${maxRetries} attempts: ${error}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
495
567
|
}
|
|
496
568
|
async clickEnvVarsButton() {
|
|
497
569
|
await (0, test_1.expect)(this.envVarsTab).toBeVisible({ timeout: 40000 });
|
|
@@ -104,12 +104,17 @@ class ClusterPage {
|
|
|
104
104
|
.filter({ hasNotText: 'Generation' }); //Filter out header row
|
|
105
105
|
this.tasklistV1Api = page.getByText('Tasklist API v1 (legacy)');
|
|
106
106
|
this.tasklistV2Api = page.getByText('Tasklist API v2');
|
|
107
|
-
this.cluster = (clusterName) => this.clustersList
|
|
107
|
+
this.cluster = (clusterName) => this.clustersList
|
|
108
|
+
.filter({
|
|
109
|
+
has: page.getByRole('link', { name: clusterName, exact: true }),
|
|
110
|
+
})
|
|
111
|
+
.first();
|
|
108
112
|
this.clusterHealthiness = (clusterName) => this.cluster(clusterName).getByText(`Healthy`, {
|
|
109
113
|
exact: true,
|
|
110
114
|
});
|
|
111
115
|
this.clusterLink = (clusterName) => this.cluster(clusterName).getByRole('link', {
|
|
112
116
|
name: clusterName,
|
|
117
|
+
exact: true,
|
|
113
118
|
});
|
|
114
119
|
this.clusterVersion = (clusterName, versionText) => this.cluster(clusterName).getByText(versionText);
|
|
115
120
|
}
|
|
@@ -130,7 +130,7 @@ class FormJsPage {
|
|
|
130
130
|
await cluster.click();
|
|
131
131
|
await (0, test_1.expect)(this.dialog
|
|
132
132
|
.locator('label')
|
|
133
|
-
.filter({ hasText: clusterName })
|
|
133
|
+
.filter({ hasText: new RegExp(`^${clusterName}`) })
|
|
134
134
|
.getByRole('switch')).toBeChecked({ timeout: 30000 });
|
|
135
135
|
await (0, test_1.expect)(this.dialog).toHaveText(healthyRegex, {
|
|
136
136
|
timeout: healthCheckTimeout,
|
|
@@ -94,7 +94,11 @@ class HomePage {
|
|
|
94
94
|
state: 'visible',
|
|
95
95
|
timeout: 30000,
|
|
96
96
|
});
|
|
97
|
-
|
|
97
|
+
// Best-effort: dismiss any Carbon modal that has a named close button.
|
|
98
|
+
await this.closeInformationDialog();
|
|
99
|
+
// force: true bypasses the "pointer events intercepted by modal backdrop"
|
|
100
|
+
// check — the same pattern used by closeInformationDialog itself.
|
|
101
|
+
await this.buttonSkipCustomization.click({ timeout: 60000, force: true });
|
|
98
102
|
await this.closeInformationDialog();
|
|
99
103
|
}
|
|
100
104
|
catch {
|
|
@@ -604,13 +604,14 @@ class ModelerCreatePage {
|
|
|
604
604
|
await (0, test_1.expect)(this.dialog).toBeVisible({ timeout: 30000 });
|
|
605
605
|
const healthCheckTimeout = 30000;
|
|
606
606
|
const healthyRegex = new RegExp(`${clusterName}.*?HealthydevManage`);
|
|
607
|
-
const
|
|
608
|
-
await (0, test_1.expect)(cluster).toBeVisible({ timeout: 30000 });
|
|
609
|
-
await cluster.click();
|
|
610
|
-
await (0, test_1.expect)(this.dialog
|
|
607
|
+
const clusterLabel = this.dialog
|
|
611
608
|
.locator('label')
|
|
612
|
-
.filter({ hasText: clusterName })
|
|
613
|
-
|
|
609
|
+
.filter({ hasText: new RegExp(`^${clusterName}`) });
|
|
610
|
+
await (0, test_1.expect)(clusterLabel).toBeVisible({ timeout: 30000 });
|
|
611
|
+
await clusterLabel.click();
|
|
612
|
+
await (0, test_1.expect)(clusterLabel.getByRole('switch')).toBeChecked({
|
|
613
|
+
timeout: 30000,
|
|
614
|
+
});
|
|
614
615
|
await (0, test_1.expect)(this.dialog).toHaveText(healthyRegex, {
|
|
615
616
|
timeout: healthCheckTimeout,
|
|
616
617
|
});
|
|
@@ -1102,7 +1103,7 @@ class ModelerCreatePage {
|
|
|
1102
1103
|
// before saving. This handles environments with multiple clusters.
|
|
1103
1104
|
const clusterLabel = configureEnvDialog
|
|
1104
1105
|
.locator('label')
|
|
1105
|
-
.filter({ hasText: clusterName });
|
|
1106
|
+
.filter({ hasText: new RegExp(`^${clusterName}`) });
|
|
1106
1107
|
const clusterSwitch = clusterLabel.getByRole('switch');
|
|
1107
1108
|
await (0, test_1.expect)(clusterLabel).toBeVisible({ timeout });
|
|
1108
1109
|
const alreadyChecked = (await clusterSwitch.getAttribute('aria-checked')) === 'true';
|
|
@@ -97,9 +97,24 @@ class ModelerHomePage {
|
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
async enterNewProjectName(name) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
// The inline rename silently drops the value when the editable title field
|
|
101
|
+
// is not yet in edit mode as fill() runs, leaving the project named
|
|
102
|
+
// "New project". Re-enter until the field reflects the requested name.
|
|
103
|
+
//
|
|
104
|
+
// Once the rename commits, the editable input unmounts and the title
|
|
105
|
+
// renders as a static heading (`[title="<name>"]`) instead. A retry that
|
|
106
|
+
// still assumes `[data-test="editable-input"]` is clickable then hangs on
|
|
107
|
+
// an element that will never reappear, even though the rename already
|
|
108
|
+
// succeeded. Treat the static title becoming visible as success.
|
|
109
|
+
await (0, test_1.expect)(async () => {
|
|
110
|
+
if (await this.page.getByTitle(name, { exact: true }).isVisible()) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
await this.projectNameInput.click({ timeout: 60000 });
|
|
114
|
+
await this.projectNameInput.fill(name);
|
|
115
|
+
await this.projectNameInput.press('Enter');
|
|
116
|
+
await (0, test_1.expect)(this.projectNameInput).toHaveValue(name, { timeout: 5000 });
|
|
117
|
+
}).toPass({ timeout: 120000 });
|
|
103
118
|
}
|
|
104
119
|
async enterIdpApplicationName(name) {
|
|
105
120
|
await this.idpApplicationNameInput.click({ timeout: 60000 });
|
|
@@ -201,15 +216,51 @@ class ModelerHomePage {
|
|
|
201
216
|
});
|
|
202
217
|
}
|
|
203
218
|
async createCrossComponentProjectFolder() {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
219
|
+
// Retry the whole create+rename sequence, not just the inline rename.
|
|
220
|
+
// enterNewProjectName only retries typing the name; if the "New project"
|
|
221
|
+
// click never puts the new project into inline-edit mode (the editable
|
|
222
|
+
// input never renders, common when the modeler backend is slow), that
|
|
223
|
+
// retry can never recover. Re-clicking "New project" on the next attempt
|
|
224
|
+
// gives the edit field a fresh chance to appear. Mirrors the SM
|
|
225
|
+
// createCrossComponentProjectFolder retry.
|
|
226
|
+
const maxAttempts = 3;
|
|
227
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
228
|
+
await (0, sleep_1.sleep)(attempt === 0 ? 15000 : 5000);
|
|
229
|
+
await this.dismissOverlays();
|
|
230
|
+
// The project may already exist (a sibling user's setup, or a previous
|
|
231
|
+
// attempt that created it but tripped on the rename check). Detect it in
|
|
232
|
+
// BOTH view states before trying to create, otherwise we click "New
|
|
233
|
+
// project" — which does not exist inside an open project — and fail:
|
|
234
|
+
// - on Home it shows as a folder tile (crossComponentProjectFolder);
|
|
235
|
+
// - if a previous step already opened it, the page is INSIDE the project
|
|
236
|
+
// (project breadcrumb visible), where the tile is not rendered, so it
|
|
237
|
+
// already exists and we are done.
|
|
238
|
+
if (await this.crossComponentProjectFolder.isVisible()) {
|
|
239
|
+
console.log('Cross Component Project folder already exists. Clicking into it');
|
|
240
|
+
await this.clickCrossComponentProjectFolder();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (await this.projectBreadcrumb.isVisible().catch(() => false)) {
|
|
244
|
+
console.log('Already inside the Cross Component Project folder; it exists');
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
await this.clickCreateNewProjectButton();
|
|
249
|
+
await this.enterNewProjectName(this.defaultFolderName);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
if (attempt >= maxAttempts - 1) {
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
// A prior attempt may have created and opened the project but failed
|
|
257
|
+
// the rename check. Return Home so the next attempt's existence check
|
|
258
|
+
// sees the folder tile instead of trying to create it again from
|
|
259
|
+
// inside the project (where there is no "New project" button).
|
|
260
|
+
await this.clickHomeBreadcrumb().catch(() => { });
|
|
261
|
+
console.log(`createCrossComponentProjectFolder attempt ${attempt + 1} failed; retrying...`);
|
|
262
|
+
}
|
|
210
263
|
}
|
|
211
|
-
await this.clickCreateNewProjectButton();
|
|
212
|
-
await this.enterNewProjectName(this.defaultFolderName);
|
|
213
264
|
}
|
|
214
265
|
async clickManageButton(retries = 3) {
|
|
215
266
|
await this.optionsButton.click({ timeout: 30000 });
|
|
@@ -249,7 +300,7 @@ class ModelerHomePage {
|
|
|
249
300
|
async selectCluster(clusterName) {
|
|
250
301
|
//Select the correct cluster if multiple exist
|
|
251
302
|
const baseClusterName = clusterName.split('(')[0].trim();
|
|
252
|
-
const cluster = this.dialog.getByText(
|
|
303
|
+
const cluster = this.dialog.getByText(new RegExp(`^${baseClusterName}`));
|
|
253
304
|
await (0, test_1.expect)(cluster).toBeVisible({
|
|
254
305
|
timeout: 30000,
|
|
255
306
|
});
|
|
@@ -257,7 +308,7 @@ class ModelerHomePage {
|
|
|
257
308
|
await (0, test_1.expect)(this.dialog
|
|
258
309
|
.locator('label')
|
|
259
310
|
.filter({
|
|
260
|
-
hasText: clusterName,
|
|
311
|
+
hasText: new RegExp(`^${clusterName}`),
|
|
261
312
|
})
|
|
262
313
|
.getByRole('switch')).toBeChecked({ timeout: 30000 });
|
|
263
314
|
}
|
|
@@ -32,7 +32,12 @@ class TaskPanelPage {
|
|
|
32
32
|
}
|
|
33
33
|
async openTask(name) {
|
|
34
34
|
let attempts = 0;
|
|
35
|
-
|
|
35
|
+
// Tasklist's importer can lag well behind Zeebe under heavy concurrent
|
|
36
|
+
// load from the sibling chromium-v1/chromium-v2 projects sharing one
|
|
37
|
+
// cluster -- trace evidence from failing runs showed other tests' tasks
|
|
38
|
+
// only appearing 15-17 minutes after creation. 10 x 120s gives 20 minutes
|
|
39
|
+
// of budget, comfortably covering that observed lag.
|
|
40
|
+
const maxAttempts = 10;
|
|
36
41
|
while (attempts < maxAttempts) {
|
|
37
42
|
try {
|
|
38
43
|
const task = this.availableTasks.getByText(name, { exact: true }).first();
|
|
@@ -46,6 +51,12 @@ class TaskPanelPage {
|
|
|
46
51
|
throw error;
|
|
47
52
|
}
|
|
48
53
|
await this.page.reload();
|
|
54
|
+
// Tasklist polls continuously for new tasks, so `networkidle` never
|
|
55
|
+
// fires and the wait times out at 60s -- burning the retry budget
|
|
56
|
+
// without ever re-attempting the task click. `domcontentloaded`
|
|
57
|
+
// resolves once the reloaded HTML has parsed, which is the actual
|
|
58
|
+
// signal we need before trying to find the task again.
|
|
59
|
+
await this.page.waitForLoadState('domcontentloaded', { timeout: 60000 });
|
|
49
60
|
}
|
|
50
61
|
}
|
|
51
62
|
}
|
|
@@ -71,6 +71,17 @@ _8_9_1.test.describe('Console User Flow Tests @tasklistV2', () => {
|
|
|
71
71
|
await (0, UtilitiesPage_1.assertLocatorVisibleWithRetry)(operateTabProcessInstancePage, operateTabProcessInstancePage.completedIcon, 'completed icon in Operate', 60000);
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
|
+
(0, _8_9_1.test)('Create Cluster', async ({ homePage, clusterPage }) => {
|
|
75
|
+
_8_9_1.test.slow();
|
|
76
|
+
const newClusterName = 'UI Test Cluster';
|
|
77
|
+
await _8_9_1.test.step('Navigate to clusters and create cluster', async () => {
|
|
78
|
+
await homePage.clickClusters();
|
|
79
|
+
await clusterPage.createCluster(newClusterName);
|
|
80
|
+
});
|
|
81
|
+
await _8_9_1.test.step('Assert cluster is healthy', async () => {
|
|
82
|
+
await clusterPage.assertClusterHealthyStatusWithRetry(newClusterName, 300000, 1500000);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
74
85
|
(0, _8_9_1.test)('Alert Trigger Flow - Email Notification', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, clusterPage, clusterDetailsPage, connectorSettingsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
75
86
|
_8_9_1.test.slow();
|
|
76
87
|
const processName = 'Email_Alert_Process' + (await (0, _setup_1.generateRandomStringAsync)(3));
|
|
@@ -7,6 +7,7 @@ const connectorSecrets_1 = require("../../utils/connectorSecrets");
|
|
|
7
7
|
const mcpSecrets_1 = require("../../utils/mcpSecrets");
|
|
8
8
|
const UtilitiesPage_1 = require("../../pages/8.9/UtilitiesPage");
|
|
9
9
|
const users_1 = require("../../utils/users");
|
|
10
|
+
const consoleApiHelpers_1 = require("../../utils/consoleApiHelpers");
|
|
10
11
|
_8_9_1.test.describe.configure({ mode: 'parallel' });
|
|
11
12
|
_8_9_1.test.describe('Cluster Setup Tests', () => {
|
|
12
13
|
_8_9_1.test.afterEach(async ({ page }, testInfo) => {
|
|
@@ -26,9 +27,15 @@ _8_9_1.test.describe('Cluster Setup Tests', () => {
|
|
|
26
27
|
const clusterName = 'Test Cluster';
|
|
27
28
|
const apiClientName = 'Test_API_Client' + (await (0, _setup_1.generateRandomStringAsync)(3));
|
|
28
29
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (process.env.IS_PROD === 'true') {
|
|
31
|
+
await clusterPage.createCluster(clusterName);
|
|
32
|
+
await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const clusterUuid = await (0, consoleApiHelpers_1.ensureClusterViaApi)(page, clusterName);
|
|
36
|
+
await (0, consoleApiHelpers_1.waitForClusterHealthyViaApi)(page, clusterUuid);
|
|
37
|
+
await homePage.clickClusters();
|
|
38
|
+
}
|
|
32
39
|
await clusterPage.clickClusterLink(clusterName);
|
|
33
40
|
await clusterDetailsPage.assertComponentsHealth();
|
|
34
41
|
if (process.env.IS_AG !== 'true') {
|
|
@@ -51,9 +58,9 @@ _8_9_1.test.describe('Cluster Setup Tests', () => {
|
|
|
51
58
|
const apiClientName = 'Test_API_Client' + (await (0, _setup_1.generateRandomStringAsync)(3));
|
|
52
59
|
const mcpClientName = 'MCP_Test_API_Client' + (await (0, _setup_1.generateRandomStringAsync)(3));
|
|
53
60
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
61
|
+
const clusterUuid = await (0, consoleApiHelpers_1.ensureClusterViaApi)(page, clusterName);
|
|
62
|
+
await (0, consoleApiHelpers_1.waitForClusterHealthyViaApi)(page, clusterUuid, 1500000);
|
|
54
63
|
await homePage.clickClusters();
|
|
55
|
-
await clusterPage.createCluster(clusterName);
|
|
56
|
-
await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
|
|
57
64
|
await clusterPage.clickClusterLink(clusterName);
|
|
58
65
|
await clusterDetailsPage.assertComponentsHealth();
|
|
59
66
|
await clusterDetailsPage.clickSettingsTab();
|
|
@@ -75,10 +82,16 @@ _8_9_1.test.describe('Cluster Setup Tests', () => {
|
|
|
75
82
|
_8_9_1.test.slow();
|
|
76
83
|
const clusterName = 'AWS Cluster';
|
|
77
84
|
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
if (process.env.IS_PROD === 'true') {
|
|
86
|
+
await clusterPage.createCluster(clusterName, 'AWS');
|
|
87
|
+
// AWS clusters on SaaS INT routinely need 10+ min to reach Healthy.
|
|
88
|
+
await clusterPage.assertClusterHealthyStatusWithRetry(clusterName, 300000, 1500000);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const clusterUuid = await (0, consoleApiHelpers_1.ensureClusterViaApi)(page, clusterName, 'AWS');
|
|
92
|
+
await (0, consoleApiHelpers_1.waitForClusterHealthyViaApi)(page, clusterUuid, 1500000);
|
|
93
|
+
await homePage.clickClusters();
|
|
94
|
+
}
|
|
82
95
|
await clusterPage.clickClusterLink(clusterName);
|
|
83
96
|
await clusterDetailsPage.assertComponentsHealth();
|
|
84
97
|
if (process.env.IS_AG !== 'true') {
|
|
@@ -123,6 +123,13 @@ async function createClusterViaApi(page, clusterName, region = 'GCP') {
|
|
|
123
123
|
k8sContextId,
|
|
124
124
|
autoUpdate: true,
|
|
125
125
|
stageLabel: 'dev',
|
|
126
|
+
// Upgrading a cluster to Tasklist v2 is a one-way, irreversible switch,
|
|
127
|
+
// and v2 cannot run job-worker-based user tasks, draft variables, or
|
|
128
|
+
// public start forms -- all of which the @tasklistV1-tagged suites
|
|
129
|
+
// exercise. Explicitly request v1 rather than relying on whatever the
|
|
130
|
+
// Console API defaults new clusters to, since a cluster that ends up
|
|
131
|
+
// v2-enabled can never be brought back to v1 for the rest of its life.
|
|
132
|
+
tasklistV2Enabled: false,
|
|
126
133
|
},
|
|
127
134
|
});
|
|
128
135
|
if (createResponse.status() !== 200 && createResponse.status() !== 201) {
|