@camunda/e2e-test-suite 0.0.439 → 0.0.441

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.
@@ -21,6 +21,7 @@ declare class IdentityTenantPage {
21
21
  readonly cancelButton: Locator;
22
22
  readonly dialog: Locator;
23
23
  readonly row: (name: string) => Locator;
24
+ readonly usersTab: Locator;
24
25
  constructor(page: Page);
25
26
  clickCreateTenantMainButton(): Promise<void>;
26
27
  clickCreateTenantSubButton(): Promise<void>;
@@ -26,11 +26,13 @@ class IdentityTenantPage {
26
26
  cancelButton;
27
27
  dialog;
28
28
  row;
29
+ usersTab;
29
30
  constructor(page) {
30
31
  this.page = page;
31
32
  this.createTenantMainButton = page.getByRole('button', {
32
33
  name: 'Create Tenant',
33
34
  });
35
+ this.usersTab = page.getByRole('tab', { name: 'Users' });
34
36
  this.enterTenantNameInput = page.getByPlaceholder('Enter tenant name');
35
37
  this.enterTenantIdInput = page.getByPlaceholder('Enter tenant ID');
36
38
  this.createTenantSubButton = page.getByRole('button', {
@@ -144,9 +146,25 @@ class IdentityTenantPage {
144
146
  await (0, sleep_1.sleep)(30000);
145
147
  }
146
148
  async clickTenant(tenantName) {
147
- const tenant = this.page.getByText(tenantName).first();
148
- await (0, UtilitiesPage_1.assertLocatorVisibleWithPaginated)(this.page, tenant, `Tenant with name ${tenantName} not found`);
149
- await tenant.click({ timeout: 30000 });
149
+ const maxRetries = 5;
150
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
151
+ try {
152
+ await this.page.waitForLoadState('domcontentloaded').catch(() => { });
153
+ const tenantRow = this.row(tenantName);
154
+ await (0, UtilitiesPage_1.assertLocatorVisibleWithPaginated)(this.page, tenantRow, `Tenant with name ${tenantName} not found`);
155
+ await tenantRow.locator('td').first().click({ timeout: 30000 });
156
+ await this.usersTab.waitFor({ state: 'visible', timeout: 30000 });
157
+ return;
158
+ }
159
+ catch (error) {
160
+ console.warn(`Attempt ${attempt} to click tenant '${tenantName}' failed. Retrying...`, error);
161
+ if (attempt === maxRetries) {
162
+ throw new Error(`Failed to click tenant '${tenantName}' after ${maxRetries} attempts.`);
163
+ }
164
+ await this.page.reload({ timeout: 30000 }).catch(() => { });
165
+ await (0, sleep_1.sleep)(3000);
166
+ }
167
+ }
150
168
  }
151
169
  async isRowVisible(name) {
152
170
  await (0, sleep_1.sleep)(1000);
@@ -187,12 +205,16 @@ class IdentityTenantPage {
187
205
  }
188
206
  async assignClientToTenant(clientName) {
189
207
  await this.clickAssignedApplicationsTab();
208
+ await (0, sleep_1.sleep)(3000);
190
209
  if (await this.isRowVisible(clientName)) {
191
210
  return;
192
211
  }
193
212
  await this.clickAssignApplicationsButton();
194
213
  await this.clickSearchApplicationsInput();
195
214
  await this.fillSearchApplicationsInput(clientName);
215
+ await (0, test_1.expect)(this.page.getByText(clientName, { exact: true })).toBeVisible({
216
+ timeout: 15000,
217
+ });
196
218
  await this.page.getByText(clientName, { exact: true }).click();
197
219
  await this.clickAssignApplicationsFinalButton();
198
220
  await (0, test_1.expect)(this.page.getByText('Applications assigned').first()).toBeVisible({
@@ -4,11 +4,12 @@ import { KeycloakLoginPage } from '../SM-8.8/KeycloakLoginPage';
4
4
  import { KeycloakAdminPage } from '../SM-8.8/KeycloakAdminPage';
5
5
  import { OCIdentityHomePage } from './OCIdentityHomePage';
6
6
  import { OCIdentityRolesPage } from './OCIdentityRolesPage';
7
+ import { IdentityTenantPage } from './IdentityTenantPage';
7
8
  export declare const keycloakAdminCredentials: () => {
8
9
  username: string;
9
10
  password: string;
10
11
  };
11
- export declare const setupKeycloakUser: (navigationPage: NavigationPage, identityPage: ManagementIdentityPage, keycloakLoginPage: KeycloakLoginPage, keycloakAdminPage: KeycloakAdminPage, ocIdentityHomePage: OCIdentityHomePage, ocIdentityRolesPage: OCIdentityRolesPage) => Promise<{
12
+ export declare const setupKeycloakUser: (navigationPage: NavigationPage, identityPage: ManagementIdentityPage, keycloakLoginPage: KeycloakLoginPage, keycloakAdminPage: KeycloakAdminPage, ocIdentityHomePage: OCIdentityHomePage, ocIdentityRolesPage: OCIdentityRolesPage, assignToDefaultTenant?: boolean, managementIdentityTenantPage?: IdentityTenantPage) => Promise<{
12
13
  testUsername: string;
13
14
  testPassword: string;
14
15
  }>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createKeycloakUser = exports.createUser = exports.setupKeycloakUser = exports.keycloakAdminCredentials = void 0;
4
+ const test_1 = require("@playwright/test");
4
5
  const keycloakAdminCredentials = () => {
5
6
  return {
6
7
  username: 'admin',
@@ -8,13 +9,21 @@ const keycloakAdminCredentials = () => {
8
9
  };
9
10
  };
10
11
  exports.keycloakAdminCredentials = keycloakAdminCredentials;
11
- const setupKeycloakUser = async (navigationPage, identityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityRolesPage) => {
12
+ const setupKeycloakUser = async (navigationPage, identityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityRolesPage, assignToDefaultTenant = false, managementIdentityTenantPage) => {
12
13
  const testUsername = `test-user-${new Date().getTime()}-${Math.random()
13
14
  .toString(36)
14
15
  .substring(7)}`;
15
16
  const testPassword = 'test-password';
16
17
  await createKeycloakUser(navigationPage, keycloakLoginPage, keycloakAdminPage, testUsername, testPassword);
17
18
  await createIdentityUser(navigationPage, identityPage, testUsername);
19
+ if (assignToDefaultTenant && managementIdentityTenantPage) {
20
+ const userEmail = `qacamunda+${testUsername}@gmail.com`;
21
+ await navigationPage.goToManagementIdentity();
22
+ await (0, test_1.expect)(identityPage.usersLink).toBeVisible({ timeout: 10000 });
23
+ if (await identityPage.tenantTab.isVisible()) {
24
+ await managementIdentityTenantPage.assignUserToTenant('Default', testUsername, userEmail);
25
+ }
26
+ }
18
27
  await createOCUser(navigationPage, ocIdentityHomePage, ocIdentityRolesPage, testUsername);
19
28
  return { testUsername, testPassword };
20
29
  };
@@ -32,7 +32,10 @@ class ManagementIdentityPage {
32
32
  name: 'Camunda logo Management Identity',
33
33
  });
34
34
  this.usersLink = page.locator('a').filter({ hasText: 'Users' });
35
- this.tenantTab = page.getByRole('link', { name: 'Tenants' });
35
+ this.tenantTab = page
36
+ .getByRole('link', { name: 'Tenants' })
37
+ .or(page.locator('a').filter({ hasText: 'Tenants' }))
38
+ .first();
36
39
  this.assignedRolesTab = page.getByRole('tab', { name: 'Assigned roles' });
37
40
  this.demoUser = page.getByRole('cell', { name: 'demo' }).first();
38
41
  this.confirmDeleteButton = page.getByRole('button', {
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const _8_9_1 = require("../../../fixtures/8.9");
4
+ const UtilitiesPage_1 = require("../../../pages/8.9/UtilitiesPage");
5
+ const _setup_1 = require("../../../test-setup.js");
6
+ const apiHelpers_1 = require("../../../utils/apiHelpers");
7
+ const variableHelpers_1 = require("../../../utils/variableHelpers");
8
+ const users_1 = require("../../../utils/users");
9
+ const test_1 = require("@playwright/test");
10
+ const testUser = (0, users_1.getTestUser)('sixteenthUser');
11
+ let authToken;
12
+ let toolsInstanceKey;
13
+ _8_9_1.test.describe.configure({ mode: 'parallel' });
14
+ _8_9_1.test.describe('Orchestration Cluster MCP Server - Variable Tools @tasklistV2', () => {
15
+ const clusterName = 'Agentic Orchestration Cluster';
16
+ _8_9_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_variable_test_file.bpmn', authToken, 'saas', 'agentic_cluster'),
20
+ (0, apiHelpers_1.deployProcess)('./resources/mcp_server_saas/mcp_variable_tools.bpmn', authToken, 'saas', 'agentic_cluster'),
21
+ ]);
22
+ if (testFileProcessKey == null || toolsProcessKey == null) {
23
+ throw new Error('Failed to deploy variable tools processes');
24
+ }
25
+ // Create test instance which will create variables
26
+ const testInstanceKey = await (0, apiHelpers_1.createProcessInstance)(String(testFileProcessKey), authToken, 'saas', 'agentic_cluster', { testVariable1: 'test_value_1', testVariable2: 'test_value_2' });
27
+ // Get a variable key created by the test instance (with retry logic)
28
+ const testVariableKey = await (0, variableHelpers_1.getVariableKeyByProcessInstanceKey)(testInstanceKey, 'testVariable1', authToken, 'saas', 'agentic_cluster');
29
+ console.log('Creating tools instance with variables:', {
30
+ testFileProcessKey,
31
+ testVariableKey,
32
+ });
33
+ // Create tools instance with required variables
34
+ toolsInstanceKey = await (0, apiHelpers_1.createProcessInstance)(String(toolsProcessKey), authToken, 'saas', 'agentic_cluster', { testFileProcessKey, testVariableKey });
35
+ });
36
+ _8_9_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
37
+ await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
38
+ });
39
+ _8_9_1.test.afterEach(async ({ page }, testInfo) => {
40
+ await (0, _setup_1.captureScreenshot)(page, testInfo);
41
+ await (0, _setup_1.captureFailureVideo)(page, testInfo);
42
+ });
43
+ const variableToolTests = [
44
+ {
45
+ name: 'searchVariables - search variables with filters',
46
+ variable: 'mcpResultSearchVariables',
47
+ assertions: [
48
+ {
49
+ text: 'items',
50
+ description: 'search response contains items field',
51
+ },
52
+ {
53
+ text: 'variableKey',
54
+ description: 'search response contains variableKey field',
55
+ },
56
+ {
57
+ text: 'name',
58
+ description: 'search response contains name field',
59
+ },
60
+ {
61
+ text: 'value',
62
+ description: 'search response contains value field',
63
+ },
64
+ {
65
+ text: 'processInstanceKey',
66
+ description: 'search response contains processInstanceKey field',
67
+ },
68
+ ],
69
+ },
70
+ {
71
+ name: 'getVariable - retrieve a variable by key',
72
+ variable: 'mcpResultGetVariable',
73
+ assertions: [
74
+ {
75
+ text: 'variableKey',
76
+ description: 'response contains variableKey field',
77
+ },
78
+ {
79
+ text: 'name',
80
+ description: 'response contains name field',
81
+ },
82
+ {
83
+ text: 'value',
84
+ description: 'response contains value field',
85
+ },
86
+ {
87
+ text: 'processInstanceKey',
88
+ description: 'response contains processInstanceKey field',
89
+ },
90
+ {
91
+ text: 'scopeKey',
92
+ description: 'response contains scopeKey field',
93
+ },
94
+ ],
95
+ },
96
+ ];
97
+ for (const testCase of variableToolTests) {
98
+ (0, _8_9_1.test)(testCase.name, async ({ homePage, appsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
99
+ _8_9_1.test.slow();
100
+ await _8_9_1.test.step('Navigate to completed process in Operate', async () => {
101
+ await homePage.clickClusters();
102
+ await appsPage.clickOperate(clusterName);
103
+ await (0, test_1.expect)(operateHomePage.operateBanner).toBeVisible({
104
+ timeout: 60000,
105
+ });
106
+ await operateHomePage.clickProcessesTab();
107
+ await operateProcessesPage.clickProcessCompletedCheckbox();
108
+ await operateProcessesPage.applyMoreFilters('Process Instance Key(s)', String(toolsInstanceKey));
109
+ await operateProcessesPage.clickProcessInstanceLink('MCP Variable Tools');
110
+ await operateProcessInstancePage.assertProcessCompleteStatusWithRetry();
111
+ });
112
+ for (const assertion of testCase.assertions) {
113
+ await _8_9_1.test.step(assertion.description, async () => {
114
+ await operateProcessInstancePage.assertProcessVariableContainsText(testCase.variable, assertion.text);
115
+ });
116
+ }
117
+ });
118
+ }
119
+ });
@@ -9,14 +9,14 @@ const loggingUtils_1 = require("../../utils/loggingUtils");
9
9
  const resetSession_1 = require("../../utils/resetSession");
10
10
  const KeycloakUtils_1 = require("../../pages/SM-8.8/KeycloakUtils");
11
11
  SM_8_8_1.test.describe.parallel('Smoke Tests', () => {
12
- SM_8_8_1.test.beforeEach(async ({ navigationPage, managementIdentityPage, keycloakLoginPage, keycloakAdminPage, page, browser, loginPage, ocIdentityHomePage, ocIdentityRolesPage, }, testInfo) => {
12
+ SM_8_8_1.test.beforeEach(async ({ navigationPage, managementIdentityPage, managementIdentityTenantPage, keycloakLoginPage, keycloakAdminPage, page, browser, loginPage, ocIdentityHomePage, ocIdentityRolesPage, }, testInfo) => {
13
13
  if (process.env.IS_MIGRATION === 'true') {
14
14
  await navigationPage.goToOCIdentity((testInfo.workerIndex + 1) * 1000);
15
15
  }
16
16
  else {
17
17
  console.log(`BeforeEach start: timeout = ${testInfo.timeout}`);
18
18
  (0, loggingUtils_1.setupTestLogging)(testInfo);
19
- const { testUsername, testPassword } = await (0, KeycloakUtils_1.setupKeycloakUser)(navigationPage, managementIdentityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityRolesPage);
19
+ const { testUsername, testPassword } = await (0, KeycloakUtils_1.setupKeycloakUser)(navigationPage, managementIdentityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityRolesPage, process.env.IS_MT === 'true', managementIdentityTenantPage);
20
20
  console.log(`BeforeEach end: timeout = ${testInfo.timeout}`);
21
21
  await (0, resetSession_1.resetSession)(browser, page);
22
22
  await loginPage.login(testUsername, testPassword);
@@ -0,0 +1 @@
1
+ export declare function getVariableKeyByProcessInstanceKey(processInstanceKey: string, variableName: string, authToken?: string, environment?: 'saas' | 'sm', clusterType?: string, maxRetries?: number, retryDelayMs?: number): Promise<string>;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVariableKeyByProcessInstanceKey = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ const apiHelpers_1 = require("./apiHelpers");
6
+ const sleep_1 = require("./sleep");
7
+ async function getVariableKeyByProcessInstanceKey(processInstanceKey, variableName, authToken, environment, clusterType, maxRetries = 10, retryDelayMs = 2000) {
8
+ const apiRequestContext = await (0, apiHelpers_1.getApiRequestContext)();
9
+ const url = (0, apiHelpers_1.buildZeebeApiUrl)('/v2/variables/search', environment, clusterType);
10
+ let lastError = null;
11
+ // Retry logic to wait for variable to be created and indexed
12
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
13
+ try {
14
+ const response = await apiRequestContext.post(url, {
15
+ headers: { Authorization: authToken ?? '' },
16
+ data: {
17
+ filter: {
18
+ processInstanceKey: String(processInstanceKey),
19
+ name: variableName,
20
+ },
21
+ },
22
+ });
23
+ (0, test_1.expect)(response.status()).toBe(200);
24
+ const responseBody = await response.json();
25
+ if (responseBody?.items && responseBody.items.length > 0) {
26
+ const variableKey = responseBody.items[0]?.variableKey;
27
+ if (variableKey != null) {
28
+ console.log(`Found variable key ${variableKey} for ${variableName} on attempt ${attempt}`);
29
+ return String(variableKey);
30
+ }
31
+ }
32
+ lastError = new Error(`No variable ${variableName} found for processInstanceKey: ${processInstanceKey}`);
33
+ }
34
+ catch (error) {
35
+ lastError = error;
36
+ }
37
+ if (attempt < maxRetries) {
38
+ console.log(`Variable ${variableName} not found yet, retrying in ${retryDelayMs}ms (${attempt}/${maxRetries})...`);
39
+ await (0, sleep_1.sleep)(retryDelayMs);
40
+ }
41
+ }
42
+ throw new Error(`Failed to find variable ${variableName} after ${maxRetries} attempts: ${lastError?.message}`);
43
+ }
44
+ exports.getVariableKeyByProcessInstanceKey = getVariableKeyByProcessInstanceKey;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.439",
3
+ "version": "0.0.441",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",