@camunda/e2e-test-suite 0.0.1105 → 0.0.1107

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.
@@ -22,6 +22,7 @@ declare class ClusterDetailsPage {
22
22
  readonly clientCredentialsDialog: Locator;
23
23
  readonly clustersLink: Locator;
24
24
  readonly alertsTab: Locator;
25
+ readonly activeTabPanel: Locator;
25
26
  readonly alertsList: Locator;
26
27
  readonly createFirstAlertButton: Locator;
27
28
  readonly createNewAlertButton: Locator;
@@ -28,6 +28,7 @@ class ClusterDetailsPage {
28
28
  clientCredentialsDialog;
29
29
  clustersLink;
30
30
  alertsTab;
31
+ activeTabPanel;
31
32
  alertsList;
32
33
  createFirstAlertButton;
33
34
  createNewAlertButton;
@@ -105,7 +106,14 @@ class ClusterDetailsPage {
105
106
  .getByRole('banner')
106
107
  .getByRole('link', { name: 'Clusters' });
107
108
  this.alertsTab = page.getByRole('tab', { name: 'Alerts' });
108
- this.alertsList = page
109
+ // Only the selected tab's panel is rendered without `hidden`, so this always
110
+ // resolves to the tab currently on screen. Scoping the alert rows to it is
111
+ // what stops `alertsList` from silently counting a different tab's table:
112
+ // unscoped, `getByRole('row')` matched the Overview tab's 15-row "Cluster
113
+ // Details" list whenever the Alerts tab was not the active one, so the
114
+ // "alerts are gone" assertion was reporting rows that were never alerts.
115
+ this.activeTabPanel = page.locator('[role="tabpanel"]:not([hidden])');
116
+ this.alertsList = this.activeTabPanel
109
117
  .getByRole('row')
110
118
  .filter({ hasNotText: 'Delivery method' }); //Filter out header row
111
119
  this.createFirstAlertButton = page.getByRole('button', {
@@ -362,7 +370,26 @@ class ClusterDetailsPage {
362
370
  }
363
371
  async clickAlertsTab() {
364
372
  await (0, test_1.expect)(this.alertsTab).toBeVisible({ timeout: 40000 });
365
- await this.alertsTab.click();
373
+ // The cluster details page re-mounts while its data finishes loading: the
374
+ // nightly trace shows the DOM emptied out at the exact moment of this click,
375
+ // and once the app re-rendered the tab strip was back on its default
376
+ // "Overview" tab with the click discarded. Nothing downstream noticed, so
377
+ // the alert steps ran against the Overview tab. Re-drive the click until the
378
+ // tab reports itself selected.
379
+ await (0, test_1.expect)(async () => {
380
+ const selected = await this.alertsTab.getAttribute('aria-selected');
381
+ if (selected !== 'true') {
382
+ await this.alertsTab.click({ timeout: 30000 });
383
+ }
384
+ await (0, test_1.expect)(this.alertsTab).toHaveAttribute('aria-selected', 'true', {
385
+ timeout: 10000,
386
+ });
387
+ }).toPass({ timeout: 90000 });
388
+ // Wait for the panel to finish loading before the caller reads the list.
389
+ // Exactly one of these renders: "Create an alert" is the empty state,
390
+ // "Create new alert" sits above a populated table. Without this the callers
391
+ // can observe an empty, still-loading panel and mistake it for "no alerts".
392
+ await (0, test_1.expect)(this.createFirstAlertButton.or(this.createNewAlertButton).first()).toBeVisible({ timeout: 60000 });
366
393
  }
367
394
  async clickExpandButton() {
368
395
  await this.expandButton.click({ timeout: 60000 });
@@ -1393,24 +1393,42 @@ class ModelerCreatePage {
1393
1393
  // 1. Connect cluster → "Configure environment" modal → select cluster → Save
1394
1394
  // 2. Deploy process → wait for success banner
1395
1395
  // 3. Configure test case
1396
+ // camunda-hub 8b4226983e (#28226, 2026-09-04) turned the three setup steps
1397
+ // into a Carbon Accordion, so the Deploy button now lives in the "Deploy
1398
+ // process" item's *content*, a sibling of the heading -- scoping by the
1399
+ // heading text's parent can no longer reach it. Anchor on the test id the
1400
+ // hub's own e2e suite uses (test-studio/e2e/pages/Definition.ts), keeping
1401
+ // the text-scoped locator as a fallback for pre-accordion builds.
1396
1402
  const setupDeployButton = this.page
1403
+ .getByTestId('test-configuration-deploy-button')
1404
+ .or(this.page
1397
1405
  .getByText('Deploy process')
1398
1406
  .locator('..')
1399
- .getByRole('button', { name: 'Deploy' });
1407
+ .getByRole('button', { name: 'Deploy' }))
1408
+ .first();
1400
1409
  // Both attributes on this button have been renamed by camunda-hub, in
1401
1410
  // separate commits: a90fd06 changed the label from "Configure scenario" to
1402
1411
  // "Configure test case", and b3958a1649 (#27259, 2026-08-07) then changed
1403
1412
  // the test id from `play-configuration-configure-scenario-button` to
1404
1413
  // `configure-test-case-button`. Match current test id, then pre-rename test
1405
- // id, then either label, so a further rename of any single attribute cannot
1406
- // break the step.
1414
+ // id. The label-based fallback that used to follow them had to go: the
1415
+ // accordion's third heading is itself a <button> labelled "Configure test
1416
+ // case", rendered `disabled={!isConfigureReady}` (camunda-hub
1417
+ // test-studio/src/test-mode/test-configuration-panel/TestConfigurationPanel.tsx).
1418
+ // The regex matched that heading, so the "already deployed?" probe below saw
1419
+ // it, skipped the deploy step outright, and then clicked a permanently
1420
+ // disabled button until the step timed out.
1407
1421
  const configureScenarioButton = this.page
1408
1422
  .getByTestId('configure-test-case-button')
1409
1423
  .or(this.page.getByTestId('play-configuration-configure-scenario-button'))
1410
- .or(this.page.getByRole('button', {
1411
- name: /^Configure (test case|scenario)$/,
1412
- }))
1413
1424
  .first();
1425
+ // Step 2 is an accordion item too, and its content (the Deploy button)
1426
+ // only renders visibly while that item is expanded. It expands by itself
1427
+ // once the cluster step completes, but a manual heading click is the
1428
+ // recovery path if it did not.
1429
+ const deployStepHeading = this.page.getByRole('button', {
1430
+ name: 'Deploy process',
1431
+ });
1414
1432
  // Play settles into exactly ONE of three states, and which one is not
1415
1433
  // knowable up front, so race them instead of timing out on each in turn:
1416
1434
  // the setup overlay, the legacy Continue button, or the configure-test
@@ -1496,25 +1514,91 @@ class ModelerCreatePage {
1496
1514
  // processApplicationId is defined, which it now is, so re-entering
1497
1515
  // Play on an already-deployed process application legitimately
1498
1516
  // has nothing to deploy and renders no Deploy button at all.
1517
+ //
1518
+ // Deploy is done when the step swaps its button for the success badge --
1519
+ // camunda-hub DeployStepContent.tsx renders
1520
+ // `data-testid="deploy-success-badge"` reading "Successfully deployed";
1521
+ // the old "Process has been successfully deployed" banner is gone, so keep
1522
+ // it only as a fallback for older builds. Probing for a Configure control
1523
+ // alone is not enough: current builds render none at all until the deploy
1524
+ // step completes.
1525
+ const deploySuccessBadge = this.page
1526
+ .getByTestId('deploy-success-badge')
1527
+ .or(this.page.getByText('Process has been successfully deployed'))
1528
+ .first();
1529
+ // `deploy-success-badge` on its own is NOT a usable "is the deploy done"
1530
+ // probe. DeployStepContent renders it inside the "Deploy process"
1531
+ // accordion item, and TestConfigurationPanel collapses that item the
1532
+ // instant the deploy finishes (`isDeployStepComplete` ->
1533
+ // `hideConfigurationOverlay()` -> `isDeployOpen` false). Carbon keeps a
1534
+ // collapsed accordion's content mounted, so the badge stays in the DOM
1535
+ // but never becomes visible again -- confirmed in a failing nightly
1536
+ // trace (PR #3339, 8.9), whose call log shows the badge resolving 89
1537
+ // times in a row and reading "hidden" every time. DeployStepIcon
1538
+ // carries the same state in the accordion *heading*, which stays on
1539
+ // screen while the item is collapsed, and the configure panel only
1540
+ // opens once the deploy step completes, so treat any of the three as
1541
+ // proof.
1542
+ const deployCompleteIcon = this.page.locator('[aria-label="Deployment complete"]');
1543
+ const isDeployComplete = async () => (await deployCompleteIcon.isVisible().catch(() => false)) ||
1544
+ (await deploySuccessBadge.isVisible().catch(() => false)) ||
1545
+ (await configureTestPanel.isVisible().catch(() => false));
1499
1546
  const alreadyDeployed = await configureScenarioButton
1500
- .isVisible({ timeout: 3000 })
1547
+ .isEnabled({ timeout: 3000 })
1501
1548
  .catch(() => false);
1502
- if (!alreadyDeployed) {
1503
- // Step 2: deploy wait for enabled; button stays disabled until the cluster
1549
+ if (!alreadyDeployed && !(await isDeployComplete())) {
1550
+ // The Deploy button lives inside the "Deploy process" accordion item,
1551
+ // which expands itself once the cluster step completes. Nudge the
1552
+ // heading if it is still collapsed, otherwise the button is present
1553
+ // but hidden and the click below would time out.
1554
+ const deployButtonShown = await setupDeployButton
1555
+ .isVisible({ timeout: 30000 })
1556
+ .catch(() => false);
1557
+ if (!deployButtonShown) {
1558
+ const canExpandDeployStep = await deployStepHeading
1559
+ .isEnabled({ timeout: 5000 })
1560
+ .catch(() => false);
1561
+ if (canExpandDeployStep) {
1562
+ await deployStepHeading.click({ timeout });
1563
+ }
1564
+ }
1565
+ // Wait for enabled; the button stays disabled until the cluster
1504
1566
  // connection is confirmed by the backend after the Save in step 1.
1505
- await (0, test_1.expect)(setupDeployButton).toBeEnabled({ timeout: 30000 });
1506
- await setupDeployButton.click({ timeout });
1507
- await (0, test_1.expect)(this.page.getByText('Process has been successfully deployed')).toBeVisible({ timeout: 90000 });
1567
+ await (0, test_1.expect)(setupDeployButton).toBeEnabled({ timeout: 60000 });
1568
+ // The click is retried against the completion probe rather than fired
1569
+ // once, because the same collapse re-renders the accordion around the
1570
+ // button: it can detach mid-click, which is the second nightly
1571
+ // symptom. A re-click can only happen while the deploy is provably
1572
+ // still incomplete AND the button is enabled -- a deploy in flight
1573
+ // disables it and a finished deploy replaces it with the badge, so
1574
+ // this cannot double-deploy. If the deploy never completes the loop
1575
+ // still fails.
1576
+ await (0, test_1.expect)(async () => {
1577
+ if (await isDeployComplete()) {
1578
+ return;
1579
+ }
1580
+ const canClick = (await setupDeployButton.isVisible().catch(() => false)) &&
1581
+ (await setupDeployButton.isEnabled().catch(() => false));
1582
+ if (canClick) {
1583
+ await setupDeployButton.click({ timeout });
1584
+ }
1585
+ (0, test_1.expect)(await isDeployComplete()).toBe(true);
1586
+ }).toPass({ timeout: 120000, intervals: [1000, 2000, 5000] });
1508
1587
  }
1509
- // Step 3: leave the overlay, and confirm we actually left it. The
1510
- // button only calls hideConfigurationOverlay(); the overlay's own
1511
- // cluster-change effect can then fire resetDeployment and bring it
1512
- // straight back, and ConfigureTestPanel stays null while it is up.
1513
- // Assert the panel really rendered, and re-drive the click if the
1514
- // overlay returned.
1588
+ // Step 3: the configure-test-case step opens on its own once the deploy
1589
+ // step completes (TestConfigurationPanel hides the setup overlay in an
1590
+ // effect keyed on isDeployStepComplete). Wait for the panel that step
1591
+ // renders; only if it stays closed -- e.g. the panel's own
1592
+ // cluster-change effect fired resetDeployment and reopened setup -- fall
1593
+ // back to clicking the step heading, which by then is enabled.
1515
1594
  await (0, test_1.expect)(async () => {
1516
- if (await configurationOverlay.isVisible()) {
1517
- await configureScenarioButton.click({ timeout });
1595
+ if (!(await configureTestPanel.isVisible())) {
1596
+ const canOpenConfigureStep = await configureScenarioButton
1597
+ .isEnabled({ timeout: 5000 })
1598
+ .catch(() => false);
1599
+ if (canOpenConfigureStep) {
1600
+ await configureScenarioButton.click({ timeout: 15000 });
1601
+ }
1518
1602
  }
1519
1603
  await (0, test_1.expect)(configureTestPanel).toBeVisible({ timeout: 15000 });
1520
1604
  }).toPass({ timeout: 90000 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1105",
3
+ "version": "0.0.1107",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",