@camunda/e2e-test-suite 0.0.484 → 0.0.485

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.
@@ -1,4 +1,5 @@
1
1
  import { Page, Locator } from '@playwright/test';
2
+ import { McpCredentials } from '../../utils/mcpSecrets';
2
3
  import { ClientCredentialsDetailsPage } from './ClientCredentialsDetailsPage';
3
4
  declare class ClusterDetailsPage {
4
5
  private page;
@@ -41,6 +42,9 @@ declare class ClusterDetailsPage {
41
42
  readonly reviewUpdateButton: Locator;
42
43
  readonly updateAvailableDialog: Locator;
43
44
  readonly updateButton: Locator;
45
+ readonly mcpSupportToggle: Locator;
46
+ readonly mcpTab: Locator;
47
+ readonly mcpTextarea: Locator;
44
48
  constructor(page: Page);
45
49
  clickAPITab(): Promise<void>;
46
50
  clickCreateClientButton(): Promise<void>;
@@ -67,7 +71,7 @@ declare class ClusterDetailsPage {
67
71
  deleteAlerts(): Promise<void>;
68
72
  private doDelete;
69
73
  assertComponentsHealth(components?: string[]): Promise<void>;
70
- createAPIClientAndReturnVariables(name: string, setEnvVariables?: boolean): Promise<{
74
+ createAPIClientAndReturnVariables(name: string, setEnvVariables?: boolean, clusterType?: string): Promise<{
71
75
  [key: string]: string;
72
76
  }>;
73
77
  createAPIClient(name: string): Promise<void>;
@@ -82,5 +86,9 @@ declare class ClusterDetailsPage {
82
86
  checkOrchestrationClusterCheckbox(): Promise<void>;
83
87
  clickReviewUpdateButton(): Promise<void>;
84
88
  performClusterUpdate(): Promise<void>;
89
+ checkMcpSupportToggle(): Promise<void>;
90
+ clickMCPTab(): Promise<void>;
91
+ getMcpConfigurationText(): Promise<string>;
92
+ createMCPClientAndReturnVariables(name: string, setEnvVariables?: boolean): Promise<McpCredentials>;
85
93
  }
86
94
  export { ClusterDetailsPage };
@@ -47,6 +47,9 @@ class ClusterDetailsPage {
47
47
  reviewUpdateButton;
48
48
  updateAvailableDialog;
49
49
  updateButton;
50
+ mcpSupportToggle;
51
+ mcpTab;
52
+ mcpTextarea;
50
53
  constructor(page) {
51
54
  this.page = page;
52
55
  this.apiTab = page.getByRole('tab', { name: 'API' });
@@ -145,6 +148,11 @@ class ClusterDetailsPage {
145
148
  this.updateButton = this.updateAvailableDialog.getByRole('button', {
146
149
  name: 'Update',
147
150
  });
151
+ this.mcpSupportToggle = page.getByRole('switch', {
152
+ name: /Enable MCP Support/i,
153
+ });
154
+ this.mcpTab = page.getByRole('tab', { name: 'MCP' });
155
+ this.mcpTextarea = page.getByRole('textbox', { name: 'Copy to clipboard' });
148
156
  }
149
157
  async clickAPITab() {
150
158
  await (0, test_1.expect)(this.apiTab).toBeVisible({ timeout: 60000 });
@@ -372,7 +380,7 @@ class ClusterDetailsPage {
372
380
  });
373
381
  }
374
382
  }
375
- async createAPIClientAndReturnVariables(name, setEnvVariables = true) {
383
+ async createAPIClientAndReturnVariables(name, setEnvVariables = true, clusterType) {
376
384
  await this.createAPIClient(name);
377
385
  await this.clickEnvVarsButton();
378
386
  const variables = {
@@ -384,13 +392,29 @@ class ClusterDetailsPage {
384
392
  optimizeBaseUrl: await this.clientCredentialsText(/export CAMUNDA_OPTIMIZE_BASE_URL='([^']+)'/),
385
393
  };
386
394
  if (setEnvVariables) {
387
- process.env.ZEEBE_API_CLIENT_ID = variables.zeebeClientId;
388
- process.env.ZEEBE_API_CLIENT_SECRET = variables.zeebeClientSecret;
389
- process.env.ZEEBE_API_AUTH_URL = variables.zeebeAuthUrl;
390
- process.env.ZEEBE_API_URL = variables.zeebeUrl;
391
- process.env.ZEEBE_API_TOKEN_AUDIENCE = variables.tokenAudience;
392
- process.env.CAMUNDA_OPTIMIZE_BASE_URL = variables.optimizeBaseUrl;
393
- process.env.OPTIMIZE_API_TOKEN_AUDIENCE = 'optimize.ultrawombat.com';
395
+ if (clusterType) {
396
+ // Use cluster-specific suffixed env vars
397
+ const suffix = clusterType.toUpperCase().replace(/[\s-]/g, '_');
398
+ process.env[`ZEEBE_API_CLIENT_ID_${suffix}`] = variables.zeebeClientId;
399
+ process.env[`ZEEBE_API_CLIENT_SECRET_${suffix}`] =
400
+ variables.zeebeClientSecret;
401
+ process.env[`ZEEBE_API_AUTH_URL_${suffix}`] = variables.zeebeAuthUrl;
402
+ process.env[`ZEEBE_API_URL_${suffix}`] = variables.zeebeUrl;
403
+ process.env[`ZEEBE_API_TOKEN_AUDIENCE_${suffix}`] =
404
+ variables.tokenAudience;
405
+ process.env[`CAMUNDA_OPTIMIZE_BASE_URL_${suffix}`] =
406
+ variables.optimizeBaseUrl;
407
+ console.log(`[ClusterDetailsPage] Set credentials for cluster type: ${clusterType}`);
408
+ }
409
+ else {
410
+ process.env.ZEEBE_API_CLIENT_ID = variables.zeebeClientId;
411
+ process.env.ZEEBE_API_CLIENT_SECRET = variables.zeebeClientSecret;
412
+ process.env.ZEEBE_API_AUTH_URL = variables.zeebeAuthUrl;
413
+ process.env.ZEEBE_API_URL = variables.zeebeUrl;
414
+ process.env.ZEEBE_API_TOKEN_AUDIENCE = variables.tokenAudience;
415
+ process.env.CAMUNDA_OPTIMIZE_BASE_URL = variables.optimizeBaseUrl;
416
+ process.env.OPTIMIZE_API_TOKEN_AUDIENCE = 'optimize.ultrawombat.com';
417
+ }
394
418
  }
395
419
  return variables;
396
420
  }
@@ -500,5 +524,45 @@ class ClusterDetailsPage {
500
524
  await (0, test_1.expect)(this.updateAvailableDialog).toBeVisible({ timeout: 30000 });
501
525
  await this.updateButton.click({ timeout: 60000 });
502
526
  }
527
+ async checkMcpSupportToggle() {
528
+ if (!(await this.mcpSupportToggle.isVisible())) {
529
+ throw new Error('MCP Support toggle is not visible');
530
+ }
531
+ // Only click if not already enabled to avoid disabling on reruns
532
+ if (!(await this.mcpSupportToggle.isChecked())) {
533
+ await this.mcpSupportToggle.click({ force: true });
534
+ }
535
+ await (0, test_1.expect)(this.mcpSupportToggle).toBeChecked();
536
+ }
537
+ async clickMCPTab() {
538
+ await (0, test_1.expect)(this.mcpTab).toBeVisible({ timeout: 60000 });
539
+ await this.mcpTab.click();
540
+ }
541
+ async getMcpConfigurationText() {
542
+ await (0, test_1.expect)(this.mcpTextarea).toBeVisible({ timeout: 60000 });
543
+ return await this.mcpTextarea.innerText();
544
+ }
545
+ async createMCPClientAndReturnVariables(name, setEnvVariables = true) {
546
+ await this.createAPIClient(name);
547
+ await this.clickMCPTab();
548
+ const mcpConfigText = await this.getMcpConfigurationText();
549
+ const mcpConfig = JSON.parse(mcpConfigText);
550
+ const env = Object.values(mcpConfig.servers)[0].env;
551
+ const credentials = {
552
+ baseURL: env.CAMUNDA_BASE_URL,
553
+ clientID: env.CAMUNDA_CLIENT_ID,
554
+ clientSecret: env.CAMUNDA_CLIENT_SECRET,
555
+ OauthURL: env.CAMUNDA_OAUTH_URL,
556
+ tokenAudience: env.CAMUNDA_TOKEN_AUDIENCE,
557
+ };
558
+ if (setEnvVariables) {
559
+ process.env.MCP_BASE_URL = credentials.baseURL;
560
+ process.env.MCP_CLIENT_ID = credentials.clientID;
561
+ process.env.MCP_CLIENT_SECRET = credentials.clientSecret;
562
+ process.env.MCP_OAUTH_URL = credentials.OauthURL;
563
+ process.env.MCP_TOKEN_AUDIENCE = credentials.tokenAudience;
564
+ }
565
+ return credentials;
566
+ }
503
567
  }
504
568
  exports.ClusterDetailsPage = ClusterDetailsPage;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const _8_10_1 = require("../../../fixtures/8.10");
4
+ const UtilitiesPage_1 = require("../../../pages/8.10/UtilitiesPage");
5
+ const _setup_1 = require("../../../test-setup.js");
6
+ const apiHelpers_1 = require("../../../utils/apiHelpers");
7
+ const users_1 = require("../../../utils/users");
8
+ const test_1 = require("@playwright/test");
9
+ const testUser = (0, users_1.getTestUser)('fourteenthUser');
10
+ let authToken;
11
+ let instanceKey;
12
+ _8_10_1.test.describe.configure({ mode: 'parallel' });
13
+ _8_10_1.test.describe('Orchestration Cluster MCP Server - Cluster Tools @tasklistV2', () => {
14
+ const clusterName = 'Agentic Orchestration Cluster';
15
+ _8_10_1.test.beforeAll(async () => {
16
+ authToken = await (0, apiHelpers_1.authSaasAPI)(undefined, 'agentic_cluster');
17
+ const processDefinitionKey = await (0, apiHelpers_1.deployProcess)('./resources/mcp_server_saas/mcp_cluster_tools.bpmn', authToken, 'saas', 'agentic_cluster');
18
+ if (processDefinitionKey == null) {
19
+ throw new Error('Failed to deploy cluster tools process');
20
+ }
21
+ instanceKey = await (0, apiHelpers_1.createProcessInstance)(String(processDefinitionKey), authToken, 'saas', 'agentic_cluster');
22
+ });
23
+ _8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
24
+ await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
25
+ });
26
+ _8_10_1.test.afterEach(async ({ page }, testInfo) => {
27
+ await (0, _setup_1.captureScreenshot)(page, testInfo);
28
+ await (0, _setup_1.captureFailureVideo)(page, testInfo);
29
+ });
30
+ const clusterToolTests = [
31
+ {
32
+ name: 'getClusterStatus - returns cluster health status',
33
+ variable: 'mcpResultClusterStatus',
34
+ assertions: [
35
+ {
36
+ text: 'HEALTHY',
37
+ description: 'cluster status response contains healthy field',
38
+ },
39
+ ],
40
+ },
41
+ {
42
+ name: 'getTopology - returns cluster topology information',
43
+ variable: 'mcpResultTopology',
44
+ assertions: [
45
+ { text: 'brokers', description: 'topology response contains brokers' },
46
+ {
47
+ text: 'partitionsCount',
48
+ description: 'topology response contains partitions count',
49
+ },
50
+ ],
51
+ },
52
+ ];
53
+ for (const testCase of clusterToolTests) {
54
+ (0, _8_10_1.test)(testCase.name, async ({ homePage, appsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
55
+ _8_10_1.test.slow();
56
+ await _8_10_1.test.step('Navigate to completed process in Operate', async () => {
57
+ await homePage.clickClusters();
58
+ await appsPage.clickOperate(clusterName);
59
+ await (0, test_1.expect)(operateHomePage.operateBanner).toBeVisible({
60
+ timeout: 60000,
61
+ });
62
+ await operateHomePage.clickProcessesTab();
63
+ await operateProcessesPage.clickProcessCompletedCheckbox();
64
+ await operateProcessesPage.applyMoreFilters('Process Instance Key(s)', String(instanceKey));
65
+ await operateProcessesPage.clickProcessInstanceLink('MCP Cluster tools');
66
+ await operateProcessInstancePage.assertProcessCompleteStatusWithRetry();
67
+ });
68
+ for (const assertion of testCase.assertions) {
69
+ await _8_10_1.test.step(`Verify ${assertion.description}`, async () => {
70
+ await operateProcessInstancePage.assertProcessVariableContainsText(testCase.variable, assertion.text);
71
+ });
72
+ }
73
+ });
74
+ }
75
+ });
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const _8_10_1 = require("../../../fixtures/8.10");
4
+ const UtilitiesPage_1 = require("../../../pages/8.10/UtilitiesPage");
5
+ const _setup_1 = require("../../../test-setup.js");
6
+ const apiHelpers_1 = require("../../../utils/apiHelpers");
7
+ const incidentHelpers_1 = require("../../../utils/incidentHelpers");
8
+ const users_1 = require("../../../utils/users");
9
+ const test_1 = require("@playwright/test");
10
+ const testUser = (0, users_1.getTestUser)('fifteenthUser');
11
+ let authToken;
12
+ let toolsInstanceKey;
13
+ _8_10_1.test.describe.configure({ mode: 'parallel' });
14
+ _8_10_1.test.describe('Orchestration Cluster MCP Server - Incident Tools @tasklistV2', () => {
15
+ const clusterName = 'Agentic Orchestration Cluster';
16
+ _8_10_1.test.beforeAll(async () => {
17
+ authToken = await (0, apiHelpers_1.authSaasAPI)(undefined, 'agentic_cluster');
18
+ const [testFileProcessKey, toolsProcessKey] = await Promise.all([
19
+ (0, apiHelpers_1.deployProcess)('./resources/mcp_server_saas/mcp_incident_test_file.bpmn', authToken, 'saas', 'agentic_cluster'),
20
+ (0, apiHelpers_1.deployProcess)('./resources/mcp_server_saas/mcp_incident_tools.bpmn', authToken, 'saas', 'agentic_cluster'),
21
+ ]);
22
+ if (testFileProcessKey == null || toolsProcessKey == null) {
23
+ throw new Error('Failed to deploy incident tools processes');
24
+ }
25
+ // Create test instance — the call activity in the BPMN references a
26
+ // non-existent process, so Zeebe raises a CALLED_ELEMENT_ERROR incident
27
+ // immediately without needing a worker.
28
+ const testInstanceKey = await (0, apiHelpers_1.createProcessInstance)(String(testFileProcessKey), authToken, 'saas', 'agentic_cluster');
29
+ // Get the incident key created by the test instance (with retry logic)
30
+ const testIncidentKey = await (0, incidentHelpers_1.getIncidentKeyByProcessInstanceKey)(testInstanceKey, authToken, 'saas', 'agentic_cluster');
31
+ console.log('Creating tools instance with variables:', {
32
+ testFileProcessKey,
33
+ testIncidentKey,
34
+ });
35
+ // Create tools instance with required variables
36
+ toolsInstanceKey = await (0, apiHelpers_1.createProcessInstance)(String(toolsProcessKey), authToken, 'saas', 'agentic_cluster', { testFileProcessKey, testIncidentKey });
37
+ });
38
+ _8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
39
+ await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
40
+ });
41
+ _8_10_1.test.afterEach(async ({ page }, testInfo) => {
42
+ await (0, _setup_1.captureScreenshot)(page, testInfo);
43
+ await (0, _setup_1.captureFailureVideo)(page, testInfo);
44
+ });
45
+ const incidentToolTests = [
46
+ {
47
+ name: 'searchIncidents - search incidents with filters such as processDefinitionKey',
48
+ variable: 'mcpResultSearchIncidents',
49
+ assertions: [
50
+ {
51
+ text: 'totalItems',
52
+ description: 'search response contains totalItems field',
53
+ },
54
+ {
55
+ text: 'incidentKey',
56
+ description: 'search response contains incidentKey field',
57
+ },
58
+ {
59
+ text: 'processDefinitionKey',
60
+ description: 'search response contains processDefinitionKey field',
61
+ },
62
+ {
63
+ text: 'state',
64
+ description: 'search response contains state field',
65
+ },
66
+ ],
67
+ },
68
+ {
69
+ name: 'getIncident - retrieve an incident by key',
70
+ variable: 'mcpResultGetIncident',
71
+ assertions: [
72
+ {
73
+ text: 'incidentKey',
74
+ description: 'response contains incidentKey field',
75
+ },
76
+ {
77
+ text: 'processInstanceKey',
78
+ description: 'response contains processInstanceKey field',
79
+ },
80
+ {
81
+ text: 'errorType',
82
+ description: 'response contains errorType field',
83
+ },
84
+ {
85
+ text: 'state',
86
+ description: 'response contains state field',
87
+ },
88
+ ],
89
+ },
90
+ {
91
+ name: 'resolveIncident - resolve an incident by key',
92
+ variable: 'mcpResultResolveIncident',
93
+ assertions: [
94
+ {
95
+ text: 'resolved',
96
+ description: 'response confirms incident was resolved',
97
+ },
98
+ ],
99
+ },
100
+ ];
101
+ for (const testCase of incidentToolTests) {
102
+ (0, _8_10_1.test)(testCase.name, async ({ homePage, appsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
103
+ _8_10_1.test.slow();
104
+ await _8_10_1.test.step('Navigate to completed process in Operate', async () => {
105
+ await homePage.clickClusters();
106
+ await appsPage.clickOperate(clusterName);
107
+ await (0, test_1.expect)(operateHomePage.operateBanner).toBeVisible({
108
+ timeout: 60000,
109
+ });
110
+ await operateHomePage.clickProcessesTab();
111
+ await operateProcessesPage.clickProcessCompletedCheckbox();
112
+ await operateProcessesPage.applyMoreFilters('Process Instance Key(s)', String(toolsInstanceKey));
113
+ await operateProcessesPage.clickProcessInstanceLink('MCP Incident Tools');
114
+ await operateProcessInstancePage.assertProcessCompleteStatusWithRetry();
115
+ });
116
+ for (const assertion of testCase.assertions) {
117
+ await _8_10_1.test.step(assertion.description, async () => {
118
+ await operateProcessInstancePage.assertProcessVariableContainsText(testCase.variable, assertion.text);
119
+ });
120
+ }
121
+ });
122
+ }
123
+ });
@@ -4,6 +4,7 @@ const test_1 = require("@playwright/test");
4
4
  const _8_10_1 = require("../../fixtures/8.10");
5
5
  const _setup_1 = require("../../test-setup.js");
6
6
  const connectorSecrets_1 = require("../../utils/connectorSecrets");
7
+ const mcpSecrets_1 = require("../../utils/mcpSecrets");
7
8
  const UtilitiesPage_1 = require("../../pages/8.10/UtilitiesPage");
8
9
  const users_1 = require("../../utils/users");
9
10
  _8_10_1.test.describe.configure({ mode: 'parallel' });
@@ -44,6 +45,32 @@ _8_10_1.test.describe('Cluster Setup Tests', () => {
44
45
  await clusterSecretsPage.createSetOfSecrets(clusterName, connectorSecrets_1.agentcoreSecretsValues);
45
46
  }
46
47
  });
48
+ (0, _8_10_1.test)('Create Agentic Orchestration Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }, testInfo) => {
49
+ _8_10_1.test.skip(process.env.IS_PROD === 'true', 'Skipping test because not required on PROD test org');
50
+ _8_10_1.test.skip(process.env.IS_AG === 'true', 'Skipping test because not required when IS_AG is true');
51
+ _8_10_1.test.slow();
52
+ const clusterName = 'Agentic Orchestration Cluster';
53
+ const apiClientName = 'Test_API_Client' + (await (0, _setup_1.generateRandomStringAsync)(3));
54
+ const mcpClientName = 'MCP_Test_API_Client' + (await (0, _setup_1.generateRandomStringAsync)(3));
55
+ await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, users_1.testUsers.mainUser, (testInfo.workerIndex + 1) * 1000);
56
+ await homePage.clickClusters();
57
+ await clusterPage.createCluster(clusterName);
58
+ await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
59
+ await clusterPage.clickClusterLink(clusterName);
60
+ await clusterDetailsPage.assertComponentsHealth();
61
+ await clusterDetailsPage.clickSettingsTab();
62
+ await clusterDetailsPage.checkMcpSupportToggle();
63
+ await homePage.clickClusters();
64
+ await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
65
+ await clusterPage.clickClusterLink(clusterName);
66
+ await clusterDetailsPage.clickAPITab();
67
+ await clusterDetailsPage.createAPIClientAndReturnVariables(apiClientName, true, 'agentic_cluster');
68
+ await clusterDetailsPage.clickCloseModalButton();
69
+ const mcpCredentials = await clusterDetailsPage.createMCPClientAndReturnVariables(mcpClientName);
70
+ await clusterDetailsPage.clickCloseModalButton();
71
+ await clusterPage.clickConnectorSecretsTab(clusterName);
72
+ await clusterSecretsPage.createSetOfSecrets(clusterName, (0, mcpSecrets_1.mcpSecretsValues)(mcpCredentials));
73
+ });
47
74
  (0, _8_10_1.test)('Create AWS Cluster', async ({ page, loginPage, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }, testInfo) => {
48
75
  _8_10_1.test.slow();
49
76
  const clusterName = 'AWS Cluster';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.484",
3
+ "version": "0.0.485",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",