@camunda/e2e-test-suite 0.0.937 → 0.0.939

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,6 +74,8 @@ declare class ClusterDetailsPage {
74
74
  selectEmailRadioButton(): Promise<void>;
75
75
  clickCreateAlertButton(): Promise<void>;
76
76
  deleteAlerts(): Promise<void>;
77
+ private confirmDelete;
78
+ private dismissDeleteDialog;
77
79
  private doDelete;
78
80
  assertComponentsHealth(components?: string[]): Promise<void>;
79
81
  createAPIClientAndReturnVariables(name: string, setEnvVariables?: boolean): Promise<{
@@ -404,6 +404,45 @@ class ClusterDetailsPage {
404
404
  async deleteAlerts() {
405
405
  await this.doDelete(this.dialog, 'Alerts');
406
406
  }
407
+ // The confirmation modal only closes once the DELETE request resolves. When
408
+ // that call fails the modal stays open on an inline "We're having trouble
409
+ // deleting the alert / fetch error" banner, and Carbon's modal overlay then
410
+ // intercepts pointer events for the whole page — so the next row's Delete
411
+ // click can never land (the nightly trace shows
412
+ // `DELETE /api/orgs/<org>/clusters/<id>/alerts/<uuid>` ending in
413
+ // net::ERR_FAILED, followed by a 60s click timeout on the row button). Retry
414
+ // the confirmation while the modal is up, and guarantee it is gone before the
415
+ // caller touches the list again.
416
+ async confirmDelete(dialog) {
417
+ const maxAttempts = 3;
418
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
419
+ await this.deleteSubButton.click({ timeout: 60000 });
420
+ await (0, test_1.expect)(this.page.getByText('Deleting...')).not.toBeVisible({
421
+ timeout: 60000,
422
+ });
423
+ const closed = await dialog
424
+ .waitFor({ state: 'hidden', timeout: 30000 })
425
+ .then(() => true)
426
+ .catch(() => false);
427
+ if (closed) {
428
+ return true;
429
+ }
430
+ console.warn(`Confirmation dialog still open after delete attempt ${attempt} of ${maxAttempts}`);
431
+ }
432
+ await this.dismissDeleteDialog(dialog);
433
+ return false;
434
+ }
435
+ async dismissDeleteDialog(dialog) {
436
+ const cancelButton = dialog.getByRole('button', { name: 'Cancel' });
437
+ const hasCancel = await cancelButton.isVisible().catch(() => false);
438
+ if (hasCancel) {
439
+ await cancelButton.click({ timeout: 30000 });
440
+ }
441
+ else {
442
+ await this.page.keyboard.press('Escape');
443
+ }
444
+ await dialog.waitFor({ state: 'hidden', timeout: 30000 });
445
+ }
407
446
  async doDelete(dialog, text) {
408
447
  try {
409
448
  await (0, test_1.expect)(this.deleteButton.first()).toBeVisible({
@@ -414,9 +453,12 @@ class ClusterDetailsPage {
414
453
  return; //No items found in the list
415
454
  }
416
455
  try {
417
- let deletes = await this.deleteButton.all();
418
- while (deletes.length > 0) {
419
- const deleteButton = deletes[0];
456
+ let remaining = await this.deleteButton.count();
457
+ // A failed DELETE leaves the row in place; retry it from a clean state
458
+ // instead of giving up on the first stalled round.
459
+ let stalledRounds = 0;
460
+ while (remaining > 0 && stalledRounds < 3) {
461
+ const deleteButton = this.deleteButton.first();
420
462
  if (await deleteButton.isVisible()) {
421
463
  await deleteButton.click({ timeout: 60000 });
422
464
  // Handle confirmation dialog if it appears; some UI states delete without one
@@ -424,17 +466,18 @@ class ClusterDetailsPage {
424
466
  .isVisible({ timeout: 5000 })
425
467
  .catch(() => false);
426
468
  if (dialogVisible) {
427
- await this.deleteSubButton.click();
428
- await (0, test_1.expect)(this.page.getByText('Deleting...')).not.toBeVisible({
429
- timeout: 60000,
430
- });
469
+ if (!(await this.confirmDelete(dialog))) {
470
+ console.warn(`Retrying ${text} deletion after a failed request`);
471
+ }
431
472
  }
432
473
  else {
433
474
  await (0, sleep_1.sleep)(2000);
434
475
  }
435
476
  }
436
477
  await (0, sleep_1.sleep)(3000);
437
- deletes = await this.deleteButton.all();
478
+ const left = await this.deleteButton.count();
479
+ stalledRounds = left < remaining ? 0 : stalledRounds + 1;
480
+ remaining = left;
438
481
  }
439
482
  await (0, test_1.expect)(this.deleteButton).not.toBeVisible({
440
483
  timeout: 30000,
@@ -152,17 +152,23 @@ _8_8_1.test.describe('Console User Flow Tests @tasklistV2', () => {
152
152
  await homePage.clickClusters();
153
153
  await clusterPage.clickClusterLink(alertFlowClusterName);
154
154
  });
155
+ // Console's alerts panel renders its "Alerts keep you informed" empty state
156
+ // whenever the cluster-detail fetch fails (the nightly trace shows
157
+ // `/api/orgs/<org>/clusters/<id>*` calls ending in net::ERR_FAILED), so the
158
+ // alert rows can be missing for a while even though the alert exists and has
159
+ // already triggered. A reload re-issues those fetches, so give the recovery
160
+ // enough reload cycles instead of only three.
155
161
  await _8_8_1.test.step('Verify Alert Count Increases to 1 After Trigger', async () => {
156
162
  await clusterDetailsPage.clickAlertsTab();
157
163
  await (0, test_1.expect)(async () => {
158
164
  await page.reload();
159
165
  await (0, test_1.expect)(clusterDetailsPage.alertsList.first()).toBeVisible({
160
- timeout: 30000,
166
+ timeout: 20000,
161
167
  });
162
168
  (0, test_1.expect)(await clusterDetailsPage.alertsList.count()).toBeGreaterThan(1);
163
169
  await (0, test_1.expect)(clusterDetailsPage.alertsList.nth(0)).toContainText(`Email`);
164
170
  await clusterDetailsPage.assertAlertText('Amount triggered1');
165
- }).toPass({ timeout: 90000 });
171
+ }).toPass({ timeout: 240000 });
166
172
  });
167
173
  await _8_8_1.test.step('Verify Alerts Received via Email for Incident', async () => {
168
174
  await (0, sleep_1.sleep)(60000);
@@ -191,16 +197,17 @@ _8_8_1.test.describe('Console User Flow Tests @tasklistV2', () => {
191
197
  await homePage.clickClusters();
192
198
  await clusterPage.clickClusterLink(alertFlowClusterName);
193
199
  });
200
+ // Same empty-state recovery as the first count assertion above.
194
201
  await _8_8_1.test.step('Verify Alert Count Increases to 3 After Trigger', async () => {
195
202
  await clusterDetailsPage.clickAlertsTab();
196
203
  await (0, test_1.expect)(async () => {
197
204
  await page.reload();
198
205
  await (0, test_1.expect)(clusterDetailsPage.alertsList.first()).toBeVisible({
199
- timeout: 30000,
206
+ timeout: 20000,
200
207
  });
201
208
  (0, test_1.expect)(await clusterDetailsPage.alertsList.count()).toBeGreaterThan(1);
202
209
  await clusterDetailsPage.assertAlertText('Amount triggered3');
203
- }).toPass({ timeout: 90000 });
210
+ }).toPass({ timeout: 240000 });
204
211
  });
205
212
  await _8_8_1.test.step('Verify Alerts Received via Email for Incident', async () => {
206
213
  await (0, sleep_1.sleep)(60000);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.937",
3
+ "version": "0.0.939",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",