@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.
@@ -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,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
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.794",
3
+ "version": "0.0.795",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",