@camunda/e2e-test-suite 0.0.1104 → 0.0.1105
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/AppsPage.js +18 -2
- package/dist/pages/8.9/ClusterPage.js +9 -0
- package/dist/pages/8.9/ModelerCreatePage.js +101 -15
- package/dist/tests/8.9/orchestration-cluster-mcp-server/mcp-cluster-tools.spec.js +5 -0
- package/dist/tests/8.9/orchestration-cluster-mcp-server/mcp-user-task-tools.spec.js +5 -0
- package/package.json +1 -1
|
@@ -29,7 +29,15 @@ class AppsPage {
|
|
|
29
29
|
this.appSwitcherButton = page.getByLabel('App Switcher');
|
|
30
30
|
this.tasklistLink = page.getByRole('link', { name: 'Tasklist', exact: true });
|
|
31
31
|
this.adminLink = page.getByRole('link', { name: /^(Admin|Identity)$/ });
|
|
32
|
-
|
|
32
|
+
// Console renders its OWN "Operate" nav link pointing at
|
|
33
|
+
// /org/<id>/appTeaser/operate — the "Create a cluster to use Operate"
|
|
34
|
+
// teaser page, not a cluster's Operate. It carries the same role and
|
|
35
|
+
// accessible name as the app switcher's cluster-scoped Operate link, so an
|
|
36
|
+
// unfiltered locator silently navigates to the teaser and every downstream
|
|
37
|
+
// Operate assertion then fails on a Console page. Match only the real link.
|
|
38
|
+
this.operateLink = page
|
|
39
|
+
.getByRole('link', { name: 'Operate', exact: true })
|
|
40
|
+
.and(page.locator('a:not([href*="appTeaser"])'));
|
|
33
41
|
this.optimizeLink = page.getByRole('link', { name: 'Optimize', exact: true });
|
|
34
42
|
this.consoleLink = page.getByRole('link', { name: 'Console', exact: true });
|
|
35
43
|
this.camundaComponentsButton = page.getByLabel('Camunda components');
|
|
@@ -84,7 +92,15 @@ class AppsPage {
|
|
|
84
92
|
}
|
|
85
93
|
catch (error) {
|
|
86
94
|
console.warn(`Click attempt ${retries + 1} failed: ${error}`);
|
|
87
|
-
|
|
95
|
+
// The app-switcher panel can open with no entries at all when the
|
|
96
|
+
// request that populates it fails (the nightly trace shows the panel
|
|
97
|
+
// open and empty, with its backing requests erroring out). Re-clicking
|
|
98
|
+
// the switcher only toggles that same empty panel shut, so the retries
|
|
99
|
+
// could never recover. Reload first so the panel is rebuilt from a
|
|
100
|
+
// fresh fetch — the same recovery clickOperate/clickTasklist/clickAdmin
|
|
101
|
+
// already use.
|
|
102
|
+
await this.page.waitForLoadState('domcontentloaded');
|
|
103
|
+
await this.page.reload();
|
|
88
104
|
}
|
|
89
105
|
}
|
|
90
106
|
throw new Error(`Failed to click the modeler link after ${maxRetries} attempts.`);
|
|
@@ -192,8 +192,17 @@ class ClusterPage {
|
|
|
192
192
|
}
|
|
193
193
|
async clickClusterNameInput() {
|
|
194
194
|
await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.clusterNameInput, {
|
|
195
|
+
visibilityTimeout: 30000,
|
|
196
|
+
totalTimeout: 120000,
|
|
195
197
|
postAction: async () => {
|
|
198
|
+
// Going back to the Clusters list is not a recovery on its own: the
|
|
199
|
+
// create-cluster form is a separate route, so the name input can never
|
|
200
|
+
// reappear until "Create new cluster" is pressed again. The nightly
|
|
201
|
+
// trace shows the form's `clusters/parameters` request failing, which
|
|
202
|
+
// left the form empty, and every retry then waited on an input that was
|
|
203
|
+
// no longer reachable. Re-open the form so the request is retried.
|
|
196
204
|
await this.clickClusterBanner();
|
|
205
|
+
await this.clickCreateNewClusterButton();
|
|
197
206
|
},
|
|
198
207
|
});
|
|
199
208
|
}
|
|
@@ -1334,10 +1334,36 @@ class ModelerCreatePage {
|
|
|
1334
1334
|
// 1. Connect cluster → "Configure environment" modal → select cluster → Save
|
|
1335
1335
|
// 2. Deploy process → wait for success banner
|
|
1336
1336
|
// 3. Configure test case
|
|
1337
|
+
// The Deploy button lives in the accordion item's *content* panel, a
|
|
1338
|
+
// sibling of the "Deploy process" heading -- not inside it -- so the
|
|
1339
|
+
// label-scoped locator below resolves to nothing on current builds. The
|
|
1340
|
+
// "Test Studio" rebrand gave the button the stable test id
|
|
1341
|
+
// `test-configuration-deploy-button` (camunda-hub
|
|
1342
|
+
// `frontend/packages/modeler/test-studio/src/test-mode/configuration-overlay/DeployStepContent.tsx`).
|
|
1343
|
+
// Prefer it, and keep the label-scoped locator as a fallback for older
|
|
1344
|
+
// modeler builds that render the button without a test id.
|
|
1337
1345
|
const setupDeployButton = this.page
|
|
1346
|
+
.getByTestId('test-configuration-deploy-button')
|
|
1347
|
+
.or(this.page
|
|
1338
1348
|
.getByText('Deploy process')
|
|
1339
1349
|
.locator('..')
|
|
1340
|
-
.getByRole('button', { name: 'Deploy' })
|
|
1350
|
+
.getByRole('button', { name: 'Deploy' }))
|
|
1351
|
+
.first();
|
|
1352
|
+
// Deploy completion signal. camunda-hub 8b4226983e (#28226, 2026-09-04)
|
|
1353
|
+
// replaced the overlay's "Process has been successfully deployed." status
|
|
1354
|
+
// text with a badge carrying `deploy-success-badge`; keep the old sentence
|
|
1355
|
+
// as a fallback for modeler builds from before that commit.
|
|
1356
|
+
const deploySuccessBadge = this.page
|
|
1357
|
+
.getByTestId('deploy-success-badge')
|
|
1358
|
+
.or(this.page.getByText('Process has been successfully deployed'))
|
|
1359
|
+
.first();
|
|
1360
|
+
// Step 2 is an accordion item too, and its content (the Deploy button)
|
|
1361
|
+
// only renders visibly while that item is expanded. It expands by itself
|
|
1362
|
+
// once the cluster step completes, but a manual heading click is the
|
|
1363
|
+
// recovery path if it did not.
|
|
1364
|
+
const deployStepHeading = this.page.getByRole('button', {
|
|
1365
|
+
name: 'Deploy process',
|
|
1366
|
+
});
|
|
1341
1367
|
// Both attributes on this button have been renamed by camunda-hub, in
|
|
1342
1368
|
// separate commits: a90fd06 changed the label from "Configure scenario" to
|
|
1343
1369
|
// "Configure test case", and b3958a1649 (#27259, 2026-08-07) then changed
|
|
@@ -1437,25 +1463,85 @@ class ModelerCreatePage {
|
|
|
1437
1463
|
// processApplicationId is defined, which it now is, so re-entering
|
|
1438
1464
|
// Play on an already-deployed process application legitimately
|
|
1439
1465
|
// has nothing to deploy and renders no Deploy button at all.
|
|
1466
|
+
// The "Configure test case" accordion header is always rendered once the
|
|
1467
|
+
// overlay is up -- TestConfigurationPanel renders it whenever
|
|
1468
|
+
// canShowConfigureSection and only sets `disabled={!isConfigureReady}` --
|
|
1469
|
+
// so isVisible() alone is always true here. Gating on it skipped Step 2
|
|
1470
|
+
// even while deploy was still pending, and Step 3 then burned its whole
|
|
1471
|
+
// budget clicking a permanently disabled button. Gate on isEnabled().
|
|
1440
1472
|
const alreadyDeployed = await configureScenarioButton
|
|
1441
|
-
.
|
|
1473
|
+
.isEnabled({ timeout: 3000 })
|
|
1442
1474
|
.catch(() => false);
|
|
1443
|
-
|
|
1444
|
-
|
|
1475
|
+
// `deploy-success-badge` on its own is NOT a usable "is the deploy done"
|
|
1476
|
+
// probe. DeployStepContent renders it inside the "Deploy process"
|
|
1477
|
+
// accordion item, and TestConfigurationPanel collapses that item the
|
|
1478
|
+
// instant the deploy finishes (`isDeployStepComplete` ->
|
|
1479
|
+
// `hideConfigurationOverlay()` -> `isDeployOpen` false). Carbon keeps a
|
|
1480
|
+
// collapsed accordion's content mounted, so the badge stays in the DOM
|
|
1481
|
+
// but never becomes visible again -- confirmed in a failing nightly
|
|
1482
|
+
// trace, whose call log shows the badge resolving 89 times in a row and
|
|
1483
|
+
// reading "hidden" every time. DeployStepIcon carries the same state in
|
|
1484
|
+
// the accordion *heading*, which stays on screen while the item is
|
|
1485
|
+
// collapsed, and the configure panel only opens once the deploy step
|
|
1486
|
+
// completes, so treat any of the three as proof.
|
|
1487
|
+
const deployCompleteIcon = this.page.locator('[aria-label="Deployment complete"]');
|
|
1488
|
+
const isDeployComplete = async () => (await deployCompleteIcon.isVisible().catch(() => false)) ||
|
|
1489
|
+
(await deploySuccessBadge.isVisible().catch(() => false)) ||
|
|
1490
|
+
(await configureTestPanel.isVisible().catch(() => false));
|
|
1491
|
+
if (!alreadyDeployed && !(await isDeployComplete())) {
|
|
1492
|
+
// The Deploy button lives inside the "Deploy process" accordion item,
|
|
1493
|
+
// which expands itself once the cluster step completes. Nudge the
|
|
1494
|
+
// heading if it is still collapsed, otherwise the button is present
|
|
1495
|
+
// but hidden and the click below would time out.
|
|
1496
|
+
const deployButtonShown = await setupDeployButton
|
|
1497
|
+
.isVisible({ timeout: 30000 })
|
|
1498
|
+
.catch(() => false);
|
|
1499
|
+
if (!deployButtonShown) {
|
|
1500
|
+
const canExpandDeployStep = await deployStepHeading
|
|
1501
|
+
.isEnabled({ timeout: 5000 })
|
|
1502
|
+
.catch(() => false);
|
|
1503
|
+
if (canExpandDeployStep) {
|
|
1504
|
+
await deployStepHeading.click({ timeout });
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
// Wait for enabled; the button stays disabled until the cluster
|
|
1445
1508
|
// connection is confirmed by the backend after the Save in step 1.
|
|
1446
|
-
await (0, test_1.expect)(setupDeployButton).toBeEnabled({ timeout:
|
|
1447
|
-
|
|
1448
|
-
|
|
1509
|
+
await (0, test_1.expect)(setupDeployButton).toBeEnabled({ timeout: 60000 });
|
|
1510
|
+
// The click is retried against the completion probe rather than fired
|
|
1511
|
+
// once, because the same collapse re-renders the accordion around the
|
|
1512
|
+
// button: it can detach mid-click, which is the second nightly
|
|
1513
|
+
// symptom (a stuck-hidden badge, or the later Start button never
|
|
1514
|
+
// rendering because deploy silently never landed). A re-click can
|
|
1515
|
+
// only happen while the deploy is provably still incomplete AND the
|
|
1516
|
+
// button is enabled -- a deploy in flight disables it and a finished
|
|
1517
|
+
// deploy replaces it with the badge, so this cannot double-deploy. If
|
|
1518
|
+
// the deploy never completes the loop still fails.
|
|
1519
|
+
await (0, test_1.expect)(async () => {
|
|
1520
|
+
if (await isDeployComplete()) {
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
const canClick = (await setupDeployButton.isVisible().catch(() => false)) &&
|
|
1524
|
+
(await setupDeployButton.isEnabled().catch(() => false));
|
|
1525
|
+
if (canClick) {
|
|
1526
|
+
await setupDeployButton.click({ timeout });
|
|
1527
|
+
}
|
|
1528
|
+
(0, test_1.expect)(await isDeployComplete()).toBe(true);
|
|
1529
|
+
}).toPass({ timeout: 120000, intervals: [1000, 2000, 5000] });
|
|
1449
1530
|
}
|
|
1450
|
-
// Step 3:
|
|
1451
|
-
//
|
|
1452
|
-
//
|
|
1453
|
-
//
|
|
1454
|
-
//
|
|
1455
|
-
//
|
|
1531
|
+
// Step 3: the configure-test-case step opens on its own once the deploy
|
|
1532
|
+
// step completes (TestConfigurationPanel hides the setup overlay in an
|
|
1533
|
+
// effect keyed on isDeployStepComplete). Wait for the panel that step
|
|
1534
|
+
// renders; only if it stays closed -- e.g. the panel's own
|
|
1535
|
+
// cluster-change effect fired resetDeployment and reopened setup -- fall
|
|
1536
|
+
// back to clicking the step heading, which by then is enabled.
|
|
1456
1537
|
await (0, test_1.expect)(async () => {
|
|
1457
|
-
if (await
|
|
1458
|
-
await configureScenarioButton
|
|
1538
|
+
if (!(await configureTestPanel.isVisible())) {
|
|
1539
|
+
const canOpenConfigureStep = await configureScenarioButton
|
|
1540
|
+
.isEnabled({ timeout: 5000 })
|
|
1541
|
+
.catch(() => false);
|
|
1542
|
+
if (canOpenConfigureStep) {
|
|
1543
|
+
await configureScenarioButton.click({ timeout: 15000 });
|
|
1544
|
+
}
|
|
1459
1545
|
}
|
|
1460
1546
|
await (0, test_1.expect)(configureTestPanel).toBeVisible({ timeout: 15000 });
|
|
1461
1547
|
}).toPass({ timeout: 90000 });
|
|
@@ -55,6 +55,11 @@ _8_9_1.test.describe('Orchestration Cluster MCP Server - Cluster Tools @tasklist
|
|
|
55
55
|
_8_9_1.test.slow();
|
|
56
56
|
await _8_9_1.test.step('Navigate to completed process in Operate', async () => {
|
|
57
57
|
await homePage.clickClusters();
|
|
58
|
+
// clickOperate expects the app switcher to already be open: its
|
|
59
|
+
// first attempt looks for the switcher's Operate entry, which does
|
|
60
|
+
// not exist on the Clusters page, so it always burned an attempt
|
|
61
|
+
// before recovering. Open it first, as every other spec does.
|
|
62
|
+
await appsPage.clickCamundaApps();
|
|
58
63
|
await appsPage.clickOperate(clusterName);
|
|
59
64
|
await (0, test_1.expect)(operateHomePage.operateBanner).toBeVisible({
|
|
60
65
|
timeout: 60000,
|
|
@@ -108,6 +108,11 @@ _8_9_1.test.describe('Orchestration Cluster MCP Server - User Task Tools @taskli
|
|
|
108
108
|
await _8_9_1.test.step('Navigate to completed process in Operate', async () => {
|
|
109
109
|
await page.goto('/');
|
|
110
110
|
await homePage.clickClusters();
|
|
111
|
+
// clickOperate expects the app switcher to already be open: its
|
|
112
|
+
// first attempt looks for the switcher's Operate entry, which does
|
|
113
|
+
// not exist on the Clusters page, so it always burned an attempt
|
|
114
|
+
// before recovering. Open it first, as every other spec does.
|
|
115
|
+
await appsPage.clickCamundaApps();
|
|
111
116
|
await appsPage.clickOperate(clusterName);
|
|
112
117
|
await (0, test_1.expect)(operateHomePage.operateBanner).toBeVisible({
|
|
113
118
|
timeout: 60000,
|