@camunda/e2e-test-suite 0.0.423 → 0.0.425
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/SM-8.9/ModelerCreatePage.js +4 -0
- package/dist/tests/8.9/orchestration-cluster-mcp-server/mcp-incident-tools.spec.d.ts +1 -0
- package/dist/tests/8.9/orchestration-cluster-mcp-server/mcp-incident-tools.spec.js +123 -0
- package/dist/tests/SM-8.9/web-modeler-user-flows.spec.js +7 -4
- package/dist/utils/incidentHelpers.d.ts +1 -0
- package/dist/utils/incidentHelpers.js +39 -0
- package/package.json +1 -1
|
@@ -398,9 +398,11 @@ class ModelerCreatePage {
|
|
|
398
398
|
async fillIdInput(id) {
|
|
399
399
|
try {
|
|
400
400
|
await this.processIdInput.fill(id);
|
|
401
|
+
await (0, test_1.expect)(this.processIdInput).toHaveValue(id);
|
|
401
402
|
}
|
|
402
403
|
catch {
|
|
403
404
|
await this.processIdSecondLocator.fill(id);
|
|
405
|
+
await (0, test_1.expect)(this.processIdSecondLocator).toHaveValue(id);
|
|
404
406
|
}
|
|
405
407
|
}
|
|
406
408
|
async clickElemendIdInput() {
|
|
@@ -562,6 +564,7 @@ class ModelerCreatePage {
|
|
|
562
564
|
}
|
|
563
565
|
async fillNameInput(name) {
|
|
564
566
|
await this.nameInput.fill(name);
|
|
567
|
+
await (0, test_1.expect)(this.nameInput).toHaveValue(name);
|
|
565
568
|
}
|
|
566
569
|
async clickJobTypeInput() {
|
|
567
570
|
await this.jobTypeInput.click();
|
|
@@ -578,6 +581,7 @@ class ModelerCreatePage {
|
|
|
578
581
|
async enterDiagramName(name) {
|
|
579
582
|
await this.diagramNameInput.fill(name, { timeout: 60000 });
|
|
580
583
|
await this.diagramNameInput.press('Enter', { timeout: 60000 });
|
|
584
|
+
await (0, sleep_1.sleep)(1000);
|
|
581
585
|
}
|
|
582
586
|
async clickVariableInput() {
|
|
583
587
|
await this.variableInput.click();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
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 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_9_1.test.describe.configure({ mode: 'parallel' });
|
|
14
|
+
_8_9_1.test.describe('Orchestration Cluster MCP Server - Incident 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_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_9_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
|
|
39
|
+
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
|
|
40
|
+
});
|
|
41
|
+
_8_9_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_9_1.test)(testCase.name, async ({ homePage, appsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
103
|
+
_8_9_1.test.slow();
|
|
104
|
+
await _8_9_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_9_1.test.step(assertion.description, async () => {
|
|
118
|
+
await operateProcessInstancePage.assertProcessVariableContainsText(testCase.variable, assertion.text);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
@@ -149,7 +149,7 @@ SM_8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
149
149
|
await (0, fileUpload_1.uploadFile)(page, bpmnFileName);
|
|
150
150
|
});
|
|
151
151
|
await SM_8_9_1.test.step('Open uploaded BPMN diagram', async () => {
|
|
152
|
-
await (0, sleep_1.sleep)(
|
|
152
|
+
await (0, sleep_1.sleep)(3000); // Wait for file upload to be processed before clicking
|
|
153
153
|
await modelerHomePage.clickProcessDiagram(bpmnFileName.replace('.bpmn', ''));
|
|
154
154
|
await modelerCreatePage.clickDiagramBreadcrumb();
|
|
155
155
|
await modelerCreatePage.clickEditDiagramNameButton();
|
|
@@ -159,13 +159,14 @@ SM_8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
159
159
|
await modelerCreatePage.fillNameInput(processName);
|
|
160
160
|
await modelerCreatePage.clickIdInput();
|
|
161
161
|
await modelerCreatePage.fillIdInput(processName);
|
|
162
|
-
await (0, sleep_1.sleep)(
|
|
162
|
+
await (0, sleep_1.sleep)(2000); // Allow modeler auto-save to persist changes
|
|
163
163
|
});
|
|
164
164
|
await SM_8_9_1.test.step('Deploy and run process with variable', async () => {
|
|
165
165
|
const variables = '{"myVar": 8}';
|
|
166
166
|
await modelerCreatePage.runProcessInstance(variables);
|
|
167
167
|
});
|
|
168
168
|
await SM_8_9_1.test.step('View process instance in Operate and verify completion', async () => {
|
|
169
|
+
await (0, sleep_1.sleep)(3000); // Allow Zeebe to index the instance before navigating to Operate
|
|
169
170
|
await navigationPage.goToOperate();
|
|
170
171
|
await operateHomePage.clickProcessesTab();
|
|
171
172
|
await operateProcessesPage.clickProcessInstanceLink(processName, 'completed');
|
|
@@ -176,11 +177,13 @@ SM_8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
176
177
|
await SM_8_9_1.test.step('Navigate to Optimize and verify process in dashboard', async () => {
|
|
177
178
|
await navigationPage.goToOptimize();
|
|
178
179
|
await optimizeHomePage.clickDashboardLink();
|
|
179
|
-
await (0, sleep_1.sleep)(
|
|
180
|
+
await (0, sleep_1.sleep)(3000); // Brief wait for Optimize dashboard to initialize
|
|
180
181
|
await page.reload();
|
|
181
182
|
await optimizeDashboardPage.clickFilterTable();
|
|
182
183
|
await optimizeDashboardPage.fillFilterTable(processName);
|
|
183
|
-
await optimizeDashboardPage.processAssertion(processName
|
|
184
|
+
await optimizeDashboardPage.processAssertion(processName, {
|
|
185
|
+
timeout: 60000,
|
|
186
|
+
});
|
|
184
187
|
});
|
|
185
188
|
}
|
|
186
189
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getIncidentKeyByProcessInstanceKey(processInstanceKey: string, authToken?: string, environment?: 'saas' | 'sm', clusterType?: string, maxRetries?: number, retryDelayMs?: number): Promise<string>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getIncidentKeyByProcessInstanceKey = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
const apiHelpers_1 = require("./apiHelpers");
|
|
6
|
+
const sleep_1 = require("./sleep");
|
|
7
|
+
async function getIncidentKeyByProcessInstanceKey(processInstanceKey, authToken, environment, clusterType, maxRetries = 10, retryDelayMs = 2000) {
|
|
8
|
+
const apiRequestContext = await (0, apiHelpers_1.getApiRequestContext)();
|
|
9
|
+
const url = (0, apiHelpers_1.buildZeebeApiUrl)('/v2/incidents/search', environment, clusterType);
|
|
10
|
+
let lastError = null;
|
|
11
|
+
// Retry logic to wait for incident 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: { filter: { processInstanceKey: String(processInstanceKey) } },
|
|
17
|
+
});
|
|
18
|
+
(0, test_1.expect)(response.status()).toBe(200);
|
|
19
|
+
const responseBody = await response.json();
|
|
20
|
+
if (responseBody?.items && responseBody.items.length > 0) {
|
|
21
|
+
const incidentKey = responseBody.items[0]?.incidentKey;
|
|
22
|
+
if (incidentKey != null) {
|
|
23
|
+
console.log(`Found incident key ${incidentKey} on attempt ${attempt}`);
|
|
24
|
+
return String(incidentKey);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
lastError = new Error(`No incidents found for processInstanceKey: ${processInstanceKey}`);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
lastError = error;
|
|
31
|
+
}
|
|
32
|
+
if (attempt < maxRetries) {
|
|
33
|
+
console.log(`Incident not found yet, retrying in ${retryDelayMs}ms (${attempt}/${maxRetries})...`);
|
|
34
|
+
await (0, sleep_1.sleep)(retryDelayMs);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Failed to find incident after ${maxRetries} attempts: ${lastError?.message}`);
|
|
38
|
+
}
|
|
39
|
+
exports.getIncidentKeyByProcessInstanceKey = getIncidentKeyByProcessInstanceKey;
|