@camunda/e2e-test-suite 0.0.794 → 0.0.795
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/c8Run-8.10/OperateProcessInstancePage.d.ts +10 -0
- package/dist/pages/c8Run-8.10/OperateProcessInstancePage.js +44 -0
- package/dist/tests/c8Run-8.10/mcp-connector-authentication.spec.d.ts +1 -0
- package/dist/tests/c8Run-8.10/mcp-connector-authentication.spec.js +74 -0
- package/dist/tests/c8Run-8.10/mcp-user-flows.spec.d.ts +1 -0
- package/dist/tests/c8Run-8.10/mcp-user-flows.spec.js +109 -0
- package/package.json +1 -1
|
@@ -13,5 +13,15 @@ declare class OperateProcessInstancePage {
|
|
|
13
13
|
connectorResultVariableValue(variableName: string): Promise<Locator>;
|
|
14
14
|
completedIconAssertion(): Promise<void>;
|
|
15
15
|
activeIconAssertion(): Promise<void>;
|
|
16
|
+
getProcessVariableValue(variableName: string): Promise<Locator>;
|
|
17
|
+
assertProcessVariableContainsText(variableName: string, text: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Gets the JSON value of a variable by name
|
|
20
|
+
*/
|
|
21
|
+
getVariableJsonValue(variableName: string): Promise<unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Verifies that a variable exists and contains expected JSON content
|
|
24
|
+
*/
|
|
25
|
+
verifyVariableJsonContent(variableName: string, assertions: (value: unknown) => void | Promise<void>): Promise<void>;
|
|
16
26
|
}
|
|
17
27
|
export { OperateProcessInstancePage };
|
|
@@ -72,5 +72,49 @@ class OperateProcessInstancePage {
|
|
|
72
72
|
}
|
|
73
73
|
throw new Error(`Active icon not visible after ${maxRetries} attempts.`);
|
|
74
74
|
}
|
|
75
|
+
async getProcessVariableValue(variableName) {
|
|
76
|
+
return await this.page
|
|
77
|
+
.getByTestId(`variable-${variableName}`)
|
|
78
|
+
.getByRole('cell')
|
|
79
|
+
.nth(1);
|
|
80
|
+
}
|
|
81
|
+
async assertProcessVariableContainsText(variableName, text) {
|
|
82
|
+
const maxRetries = 3;
|
|
83
|
+
for (let retries = 0; retries < maxRetries; retries++) {
|
|
84
|
+
try {
|
|
85
|
+
const valueCell = await this.getProcessVariableValue(variableName);
|
|
86
|
+
await (0, test_1.expect)(valueCell).toContainText(text, { timeout: 30000 });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.log(`Failed to assert variable ${variableName}: ${error}`);
|
|
91
|
+
await this.page.reload();
|
|
92
|
+
await (0, sleep_1.sleep)(10000);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
throw new Error(`Failed to assert variable ${variableName} contains ${text} after ${maxRetries} attempts.`);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the JSON value of a variable by name
|
|
99
|
+
*/
|
|
100
|
+
async getVariableJsonValue(variableName) {
|
|
101
|
+
const variable = await this.getProcessVariableValue(variableName);
|
|
102
|
+
await (0, test_1.expect)(variable).toBeVisible();
|
|
103
|
+
const valueText = (await variable.textContent()) || '{}';
|
|
104
|
+
try {
|
|
105
|
+
return JSON.parse(valueText);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new Error(`Failed to parse JSON for variable "${variableName}". ` +
|
|
109
|
+
`Raw value: ${valueText}. Original error: ${String(error)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Verifies that a variable exists and contains expected JSON content
|
|
114
|
+
*/
|
|
115
|
+
async verifyVariableJsonContent(variableName, assertions) {
|
|
116
|
+
const value = await this.getVariableJsonValue(variableName);
|
|
117
|
+
await assertions(value);
|
|
118
|
+
}
|
|
75
119
|
}
|
|
76
120
|
exports.OperateProcessInstancePage = OperateProcessInstancePage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const c8Run_8_10_1 = require("../../fixtures/c8Run-8.10");
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
const UtilitiesPage_1 = require("../../pages/c8Run-8.10/UtilitiesPage");
|
|
6
|
+
const _setup_1 = require("../../test-setup.js");
|
|
7
|
+
const apiHelpers_1 = require("../../utils/apiHelpers");
|
|
8
|
+
const keycloakHelpers_1 = require("../../utils/keycloakHelpers");
|
|
9
|
+
const zeebeClient_1 = require("../../utils/zeebeClient");
|
|
10
|
+
const sleep_1 = require("../../utils/sleep");
|
|
11
|
+
let bearerToken;
|
|
12
|
+
const authMethods = [
|
|
13
|
+
{
|
|
14
|
+
name: 'Basic Auth',
|
|
15
|
+
processId: 'mcp_remote_client_basic_auth',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'Bearer Token',
|
|
19
|
+
processId: 'mcp_remote_client_bearer_auth',
|
|
20
|
+
getVariables: () => ({ bearerToken }),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'OAuth Client Credentials',
|
|
24
|
+
processId: 'mcp_remote_client_oauth_auth',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
c8Run_8_10_1.test.beforeAll(async () => {
|
|
28
|
+
if (process.env.MCP_SERVER_AVAILABLE !== 'true') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
await (0, apiHelpers_1.validateMcpServerHealth)('http://127.0.0.1:12001'); // No auth
|
|
32
|
+
await (0, apiHelpers_1.validateMcpServerHealth)('http://127.0.0.1:12002'); // Basic auth
|
|
33
|
+
await (0, apiHelpers_1.validateMcpServerHealth)('http://127.0.0.1:12004'); // OAuth
|
|
34
|
+
await (0, apiHelpers_1.waitForConnectorsReady)();
|
|
35
|
+
await (0, keycloakHelpers_1.validateKeycloakHealth)();
|
|
36
|
+
bearerToken = await (0, keycloakHelpers_1.getAccessToken)();
|
|
37
|
+
await (0, zeebeClient_1.deploy)([
|
|
38
|
+
'./resources/mcp_server/mcp_remote_client_basic_auth.bpmn',
|
|
39
|
+
'./resources/mcp_server/mcp_remote_client_bearer_auth.bpmn',
|
|
40
|
+
'./resources/mcp_server/mcp_remote_client_oauth_auth.bpmn',
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
c8Run_8_10_1.test.describe('@tasklistV2 MCP Client connector authentication tests', () => {
|
|
44
|
+
c8Run_8_10_1.test.skip(process.env.MCP_SERVER_AVAILABLE !== 'true', 'MCP authentication servers require Docker and are only available on Linux CI runners');
|
|
45
|
+
c8Run_8_10_1.test.beforeEach(async ({ page, operateLoginPage, operateHomePage }) => {
|
|
46
|
+
await (0, UtilitiesPage_1.navigateToApp)(page, 'operate');
|
|
47
|
+
await operateLoginPage.login('demo', 'demo');
|
|
48
|
+
await operateHomePage.operateBannerIsVisible();
|
|
49
|
+
});
|
|
50
|
+
c8Run_8_10_1.test.afterEach(async ({ page }, testInfo) => {
|
|
51
|
+
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
52
|
+
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
53
|
+
});
|
|
54
|
+
for (const { name, processId, getVariables } of authMethods) {
|
|
55
|
+
(0, c8Run_8_10_1.test)(`As a user I can authenticate using ${name} and list tools`, async ({ operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
56
|
+
await (0, zeebeClient_1.createInstances)(processId, 1, 1, getVariables?.());
|
|
57
|
+
await (0, sleep_1.sleep)(2000);
|
|
58
|
+
await c8Run_8_10_1.test.step('Navigate to completed process instance', async () => {
|
|
59
|
+
await operateHomePage.clickProcessesTab();
|
|
60
|
+
await operateProcessesPage.clickProcessCompletedCheckbox();
|
|
61
|
+
await operateProcessesPage.clickProcessInstanceLink(processId);
|
|
62
|
+
await operateProcessInstancePage.completedIconAssertion();
|
|
63
|
+
});
|
|
64
|
+
await c8Run_8_10_1.test.step(`Verify ${name} successfully listed tools`, async () => {
|
|
65
|
+
await operateProcessInstancePage.verifyVariableJsonContent('listToolsResult', (value) => {
|
|
66
|
+
const data = value;
|
|
67
|
+
(0, test_1.expect)(data.toolDefinitions).toBeDefined();
|
|
68
|
+
(0, test_1.expect)(data.toolDefinitions.length).toBeGreaterThan(0);
|
|
69
|
+
(0, test_1.expect)(data.toolDefinitions.some((tool) => tool.name)).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const c8Run_8_10_1 = require("../../fixtures/c8Run-8.10");
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
const UtilitiesPage_1 = require("../../pages/c8Run-8.10/UtilitiesPage");
|
|
6
|
+
const _setup_1 = require("../../test-setup.js");
|
|
7
|
+
const apiHelpers_1 = require("../../utils/apiHelpers");
|
|
8
|
+
const zeebeClient_1 = require("../../utils/zeebeClient");
|
|
9
|
+
const sleep_1 = require("../../utils/sleep");
|
|
10
|
+
c8Run_8_10_1.test.beforeAll(async () => {
|
|
11
|
+
if (process.env.MCP_SERVER_AVAILABLE !== 'true') {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
await (0, apiHelpers_1.validateMcpServerHealth)();
|
|
15
|
+
await (0, apiHelpers_1.waitForConnectorsReady)();
|
|
16
|
+
await (0, zeebeClient_1.deploy)(['./resources/mcp_server/mcp_remote_client_operations.bpmn']);
|
|
17
|
+
await (0, zeebeClient_1.createInstances)('mcp_remote_client', 1, 1);
|
|
18
|
+
await (0, sleep_1.sleep)(2000);
|
|
19
|
+
});
|
|
20
|
+
c8Run_8_10_1.test.describe('@tasklistV2 MCP Client connector tests', () => {
|
|
21
|
+
c8Run_8_10_1.test.skip(process.env.MCP_SERVER_AVAILABLE !== 'true', 'MCP server is only available on Linux and macOS CI runners');
|
|
22
|
+
c8Run_8_10_1.test.beforeEach(async ({ page, operateLoginPage, operateHomePage }) => {
|
|
23
|
+
await (0, UtilitiesPage_1.navigateToApp)(page, 'operate');
|
|
24
|
+
await operateLoginPage.login('demo', 'demo');
|
|
25
|
+
await operateHomePage.operateBannerIsVisible();
|
|
26
|
+
});
|
|
27
|
+
c8Run_8_10_1.test.afterEach(async ({ page }, testInfo) => {
|
|
28
|
+
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
29
|
+
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
30
|
+
});
|
|
31
|
+
(0, c8Run_8_10_1.test)('As an user I can invoke the MCP Client connector and use all its operations', async ({ operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
32
|
+
c8Run_8_10_1.test.slow();
|
|
33
|
+
await c8Run_8_10_1.test.step('Navigate to completed process instance', async () => {
|
|
34
|
+
await operateHomePage.clickProcessesTab();
|
|
35
|
+
await operateProcessesPage.clickProcessCompletedCheckbox();
|
|
36
|
+
await operateProcessesPage.clickProcessInstanceLink('mcp_remote_client');
|
|
37
|
+
await operateProcessInstancePage.completedIconAssertion();
|
|
38
|
+
});
|
|
39
|
+
await c8Run_8_10_1.test.step('Verify listToolsResult variable contains tools', async () => {
|
|
40
|
+
await operateProcessInstancePage.verifyVariableJsonContent('listToolsResult', (value) => {
|
|
41
|
+
const data = value;
|
|
42
|
+
(0, test_1.expect)(data.toolDefinitions).toBeDefined();
|
|
43
|
+
(0, test_1.expect)(data.toolDefinitions.length).toBeGreaterThan(0);
|
|
44
|
+
const greetTool = data.toolDefinitions.find((tool) => tool.name === 'greet');
|
|
45
|
+
(0, test_1.expect)(greetTool).toBeDefined();
|
|
46
|
+
(0, test_1.expect)(greetTool?.description).toBe('Return a nice greeting message');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
await c8Run_8_10_1.test.step('Verify callToolResult variable from greet tool call', async () => {
|
|
50
|
+
await operateProcessInstancePage.verifyVariableJsonContent('callToolResult', (value) => {
|
|
51
|
+
const data = value;
|
|
52
|
+
(0, test_1.expect)(data.name).toBe('greet');
|
|
53
|
+
(0, test_1.expect)(data.isError).toBe(false);
|
|
54
|
+
(0, test_1.expect)(data.content).toBeDefined();
|
|
55
|
+
(0, test_1.expect)(data.content[0].type).toBe('text');
|
|
56
|
+
(0, test_1.expect)(data.content[0].text).toContain('Hello, John');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
await c8Run_8_10_1.test.step('Verify listResourcesResult variable contains resources', async () => {
|
|
60
|
+
await operateProcessInstancePage.verifyVariableJsonContent('listResourcesResult', (value) => {
|
|
61
|
+
const data = value;
|
|
62
|
+
(0, test_1.expect)(data.resources).toBeDefined();
|
|
63
|
+
(0, test_1.expect)(data.resources.length).toBeGreaterThan(0);
|
|
64
|
+
const jokesResource = data.resources.find((resource) => resource.uri === 'file://jokes-guide.md');
|
|
65
|
+
(0, test_1.expect)(jokesResource).toBeDefined();
|
|
66
|
+
(0, test_1.expect)(jokesResource?.name).toBe('Jokes Guideline');
|
|
67
|
+
(0, test_1.expect)(jokesResource?.mimeType).toBe('text/markdown');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
await c8Run_8_10_1.test.step('Verify listResourcesTemplateResult variable contains resource templates', async () => {
|
|
71
|
+
await operateProcessInstancePage.verifyVariableJsonContent('listResourcesTemplateResult', (value) => {
|
|
72
|
+
const data = value;
|
|
73
|
+
(0, test_1.expect)(data.resourceTemplates).toBeDefined();
|
|
74
|
+
(0, test_1.expect)(data.resourceTemplates).toEqual([]);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
await c8Run_8_10_1.test.step('Verify readResourceResult variable from jokes-guide.md', async () => {
|
|
78
|
+
await operateProcessInstancePage.verifyVariableJsonContent('readResourceResult', (value) => {
|
|
79
|
+
const data = value;
|
|
80
|
+
(0, test_1.expect)(data.contents).toBeDefined();
|
|
81
|
+
(0, test_1.expect)(data.contents.length).toBeGreaterThan(0);
|
|
82
|
+
(0, test_1.expect)(data.contents[0].uri).toBe('file://jokes-guide.md');
|
|
83
|
+
(0, test_1.expect)(data.contents[0].mimeType).toBe('text/markdown');
|
|
84
|
+
(0, test_1.expect)(data.contents[0].text).toContain('How to Write Jokes');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
await c8Run_8_10_1.test.step('Verify listPromptsResult variable contains prompts', async () => {
|
|
88
|
+
await operateProcessInstancePage.verifyVariableJsonContent('listPromptsResult', (value) => {
|
|
89
|
+
const data = value;
|
|
90
|
+
(0, test_1.expect)(data.promptDescriptions).toBeDefined();
|
|
91
|
+
(0, test_1.expect)(data.promptDescriptions.length).toBeGreaterThan(0);
|
|
92
|
+
const greetingPrompt = data.promptDescriptions.find((prompt) => prompt.name === 'get-greeting');
|
|
93
|
+
(0, test_1.expect)(greetingPrompt).toBeDefined();
|
|
94
|
+
(0, test_1.expect)(greetingPrompt?.description).toContain('personalized greeting');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
await c8Run_8_10_1.test.step('Verify getPromptResult variable from get-greeting prompt', async () => {
|
|
98
|
+
await operateProcessInstancePage.verifyVariableJsonContent('getPromptResult', (value) => {
|
|
99
|
+
const data = value;
|
|
100
|
+
(0, test_1.expect)(data.description).toBe('Greeting Prompt');
|
|
101
|
+
(0, test_1.expect)(data.messages).toBeDefined();
|
|
102
|
+
(0, test_1.expect)(data.messages.length).toBeGreaterThan(0);
|
|
103
|
+
(0, test_1.expect)(data.messages[0].role).toBe('user');
|
|
104
|
+
(0, test_1.expect)(data.messages[0].content.text).toContain('John');
|
|
105
|
+
(0, test_1.expect)(data.messages[0].content.text).toContain('greet tool');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|