@camunda/e2e-test-suite 0.0.742 → 0.0.743

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.
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const test_1 = require("@playwright/test");
4
+ const _8_10_1 = require("../../fixtures/8.10");
5
+ const _setup_1 = require("../../test-setup.js");
6
+ const UtilitiesPage_1 = require("../../pages/8.10/UtilitiesPage");
7
+ const users_1 = require("../../utils/users");
8
+ const agenticDashboardHelpers_1 = require("../../utils/agenticDashboardHelpers");
9
+ const testUser = (0, users_1.getTestUser)('twentyFirstUser');
10
+ const clusterName = 'Test Cluster';
11
+ _8_10_1.test.describe.configure({ mode: 'serial' });
12
+ _8_10_1.test.describe('Agentic Control Plane Dashboard API Tests @agentic-dashboard-api @8.10', () => {
13
+ _8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
14
+ await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
15
+ });
16
+ _8_10_1.test.afterEach(async ({ page }, testInfo) => {
17
+ await (0, _setup_1.captureScreenshot)(page, testInfo);
18
+ await (0, _setup_1.captureFailureVideo)(page, testInfo);
19
+ });
20
+ (0, _8_10_1.test)('Dashboard API responses load without server errors', async ({ page, appsPage, optimizeHomePage, }) => {
21
+ const responses = await (0, agenticDashboardHelpers_1.captureDashboardResponses)(page, async () => {
22
+ await (0, agenticDashboardHelpers_1.openAgenticControlPlane)(page, appsPage, optimizeHomePage, clusterName);
23
+ });
24
+ const dashboardResponses = responses.filter(agenticDashboardHelpers_1.isLikelyDashboardApiResponse);
25
+ (0, test_1.expect)(dashboardResponses.length).toBeGreaterThan(0);
26
+ (0, test_1.expect)(dashboardResponses.some(agenticDashboardHelpers_1.isAgenticDashboardDefinitionResponse)).toBe(true);
27
+ for (const response of dashboardResponses) {
28
+ (0, test_1.expect)(response.status).toBe(200);
29
+ }
30
+ });
31
+ (0, _8_10_1.test)('Dashboard payload exposes execution count and comparison data', async ({ page, appsPage, optimizeHomePage, }) => {
32
+ const responses = await (0, agenticDashboardHelpers_1.captureDashboardResponses)(page, async () => {
33
+ await (0, agenticDashboardHelpers_1.openAgenticControlPlane)(page, appsPage, optimizeHomePage, clusterName);
34
+ });
35
+ const definitionBodies = (0, agenticDashboardHelpers_1.parseJsonResponseBodies)(responses.filter(agenticDashboardHelpers_1.isAgenticDashboardDefinitionResponse));
36
+ (0, test_1.expect)(definitionBodies.length).toBeGreaterThan(0);
37
+ (0, test_1.expect)(definitionBodies.some(agenticDashboardHelpers_1.dashboardHasComparisonTile)).toBe(true);
38
+ const reportBodies = (0, agenticDashboardHelpers_1.parseJsonResponseBodies)(responses.filter(agenticDashboardHelpers_1.isReportEvaluateResponse));
39
+ (0, test_1.expect)(reportBodies.length).toBeGreaterThan(0);
40
+ const executionReport = (0, agenticDashboardHelpers_1.findReportByName)(reportBodies, agenticDashboardHelpers_1.EXECUTION_REPORT_NAME);
41
+ (0, test_1.expect)(executionReport).toBeDefined();
42
+ const executionCount = (0, agenticDashboardHelpers_1.getReportNumericResult)(executionReport);
43
+ (0, test_1.expect)(typeof executionCount).toBe('number');
44
+ (0, test_1.expect)(Number.isFinite(executionCount)).toBe(true);
45
+ });
46
+ (0, _8_10_1.test)('Dashboard API uses current terminology and not legacy wording', async ({ page, appsPage, optimizeHomePage, }) => {
47
+ const responses = await (0, agenticDashboardHelpers_1.captureDashboardResponses)(page, async () => {
48
+ await (0, agenticDashboardHelpers_1.openAgenticControlPlane)(page, appsPage, optimizeHomePage, clusterName);
49
+ });
50
+ const dashboardResponses = responses.filter(agenticDashboardHelpers_1.isLikelyDashboardApiResponse);
51
+ (0, test_1.expect)(dashboardResponses.length).toBeGreaterThan(0);
52
+ const joined = dashboardResponses
53
+ .map((r) => r.bodyText)
54
+ .join('\n')
55
+ .toLowerCase();
56
+ (0, test_1.expect)(joined.includes(agenticDashboardHelpers_1.CURRENT_TERMINOLOGY)).toBeTruthy();
57
+ (0, test_1.expect)(joined.includes(agenticDashboardHelpers_1.LEGACY_TERMINOLOGY)).toBeFalsy();
58
+ });
59
+ (0, _8_10_1.test)('Changing the date range triggers refreshed report API calls', async ({ page, appsPage, optimizeHomePage, }) => {
60
+ await (0, agenticDashboardHelpers_1.openAgenticControlPlane)(page, appsPage, optimizeHomePage, clusterName);
61
+ let dateRangeChanged = false;
62
+ const responses = await (0, agenticDashboardHelpers_1.captureDashboardResponses)(page, async () => {
63
+ dateRangeChanged = await (0, agenticDashboardHelpers_1.changeDashboardDateRange)(page);
64
+ });
65
+ (0, test_1.expect)(dateRangeChanged).toBe(true);
66
+ const reportResponses = responses.filter(agenticDashboardHelpers_1.isReportEvaluateResponse);
67
+ (0, test_1.expect)(reportResponses.length).toBeGreaterThan(0);
68
+ for (const response of reportResponses) {
69
+ (0, test_1.expect)(response.status).toBe(200);
70
+ }
71
+ });
72
+ (0, _8_10_1.test)('Report payloads do not expose Phase 1 out-of-scope details', async ({ page, appsPage, optimizeHomePage, }) => {
73
+ const responses = await (0, agenticDashboardHelpers_1.captureDashboardResponses)(page, async () => {
74
+ await (0, agenticDashboardHelpers_1.openAgenticControlPlane)(page, appsPage, optimizeHomePage, clusterName);
75
+ });
76
+ const dashboardResponses = responses.filter(agenticDashboardHelpers_1.isLikelyDashboardApiResponse);
77
+ (0, test_1.expect)(dashboardResponses.length).toBeGreaterThan(0);
78
+ const joined = dashboardResponses
79
+ .map((r) => r.bodyText)
80
+ .join('\n')
81
+ .toLowerCase();
82
+ (0, test_1.expect)(joined.includes('reasoning token')).toBeFalsy();
83
+ (0, test_1.expect)(joined.includes('tool_name')).toBeFalsy();
84
+ (0, test_1.expect)(joined.includes('per-tool')).toBeFalsy();
85
+ });
86
+ });
@@ -0,0 +1,37 @@
1
+ import { type Page } from '@playwright/test';
2
+ export type CapturedResponse = {
3
+ url: string;
4
+ method: string;
5
+ status: number;
6
+ bodyText: string;
7
+ contentType: string;
8
+ };
9
+ type AppsPage = {
10
+ clickCamundaApps: () => Promise<void>;
11
+ clickOptimize: (clusterName: string) => Promise<void>;
12
+ };
13
+ type OptimizeHomePage = {
14
+ optimizeBanner: {
15
+ isVisible: (opts?: {
16
+ timeout?: number;
17
+ }) => Promise<boolean>;
18
+ };
19
+ };
20
+ type RoleName = 'link' | 'button' | 'option' | 'menuitem' | 'tab';
21
+ export declare const AGENTIC_DASHBOARD_DEFINITION_PATH = "/api/dashboard/agentic";
22
+ export declare const REPORT_EVALUATE_PATH_PATTERN: RegExp;
23
+ export declare const EXECUTION_REPORT_NAME = "total executions";
24
+ export declare const CURRENT_TERMINOLOGY = "total executions";
25
+ export declare const LEGACY_TERMINOLOGY = "completed agent runs";
26
+ export declare function clickFirstVisibleByName(page: Page, role: RoleName, names: string[]): Promise<boolean>;
27
+ export declare function openAgenticControlPlane(page: Page, appsPage: AppsPage, optimizeHomePage: OptimizeHomePage, clusterName: string): Promise<void>;
28
+ export declare function changeDashboardDateRange(page: Page): Promise<boolean>;
29
+ export declare function isAgenticDashboardDefinitionResponse(response: CapturedResponse): boolean;
30
+ export declare function isReportEvaluateResponse(response: CapturedResponse): boolean;
31
+ export declare function isLikelyDashboardApiResponse(response: CapturedResponse): boolean;
32
+ export declare function captureDashboardResponses(page: Page, action: () => Promise<void>): Promise<CapturedResponse[]>;
33
+ export declare function parseJsonResponseBodies(responses: CapturedResponse[]): unknown[];
34
+ export declare function findReportByName(bodies: unknown[], name: string): unknown;
35
+ export declare function getReportNumericResult(body: unknown): number | undefined;
36
+ export declare function dashboardHasComparisonTile(definition: unknown): boolean;
37
+ export {};
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dashboardHasComparisonTile = exports.getReportNumericResult = exports.findReportByName = exports.parseJsonResponseBodies = exports.captureDashboardResponses = exports.isLikelyDashboardApiResponse = exports.isReportEvaluateResponse = exports.isAgenticDashboardDefinitionResponse = exports.changeDashboardDateRange = exports.openAgenticControlPlane = exports.clickFirstVisibleByName = exports.LEGACY_TERMINOLOGY = exports.CURRENT_TERMINOLOGY = exports.EXECUTION_REPORT_NAME = exports.REPORT_EVALUATE_PATH_PATTERN = exports.AGENTIC_DASHBOARD_DEFINITION_PATH = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ exports.AGENTIC_DASHBOARD_DEFINITION_PATH = '/api/dashboard/agentic';
6
+ exports.REPORT_EVALUATE_PATH_PATTERN = /\/api\/report\/[^/]+\/evaluate/;
7
+ exports.EXECUTION_REPORT_NAME = 'total executions';
8
+ exports.CURRENT_TERMINOLOGY = 'total executions';
9
+ exports.LEGACY_TERMINOLOGY = 'completed agent runs';
10
+ const candidateDashboardLabels = [
11
+ 'Agentic Control Plane',
12
+ 'Control Plane',
13
+ 'Agentic Dashboard',
14
+ ];
15
+ async function clickFirstVisibleByName(page, role, names) {
16
+ for (const name of names) {
17
+ const locator = page.getByRole(role, { name, exact: false });
18
+ if (await locator
19
+ .first()
20
+ .isVisible({ timeout: 3000 })
21
+ .catch(() => false)) {
22
+ await locator.first().click({ timeout: 20000 });
23
+ return true;
24
+ }
25
+ }
26
+ return false;
27
+ }
28
+ exports.clickFirstVisibleByName = clickFirstVisibleByName;
29
+ async function openAgenticControlPlane(page, appsPage, optimizeHomePage, clusterName) {
30
+ await appsPage.clickCamundaApps();
31
+ await appsPage.clickOptimize(clusterName);
32
+ await test_1.expect
33
+ .poll(async () => optimizeHomePage.optimizeBanner.isVisible({ timeout: 5000 }), {
34
+ timeout: 120000,
35
+ })
36
+ .toBe(true);
37
+ const clickedLink = await clickFirstVisibleByName(page, 'link', candidateDashboardLabels);
38
+ if (!clickedLink) {
39
+ const clickedButton = await clickFirstVisibleByName(page, 'button', candidateDashboardLabels);
40
+ (0, test_1.expect)(clickedButton).toBeTruthy();
41
+ }
42
+ }
43
+ exports.openAgenticControlPlane = openAgenticControlPlane;
44
+ async function changeDashboardDateRange(page) {
45
+ const dateRange = page.locator('.dateRange').first();
46
+ const trigger = dateRange.locator('button.cds--list-box__field').first();
47
+ const triggerReady = await trigger
48
+ .waitFor({ state: 'visible', timeout: 30000 })
49
+ .then(() => true)
50
+ .catch(() => false);
51
+ if (!triggerReady) {
52
+ return false;
53
+ }
54
+ await trigger.click({ timeout: 20000 });
55
+ const menu = page.locator('ul[role="menu"].cds--menu--shown').last();
56
+ const menuReady = await menu
57
+ .waitFor({ state: 'visible', timeout: 10000 })
58
+ .then(() => true)
59
+ .catch(() => false);
60
+ if (!menuReady) {
61
+ return false;
62
+ }
63
+ const options = menu.locator('[role="menuitemcheckbox"]');
64
+ await test_1.expect
65
+ .poll(async () => options.count(), { timeout: 10000 })
66
+ .toBeGreaterThan(0);
67
+ const optionCount = await options.count();
68
+ for (let index = 0; index < optionCount; index += 1) {
69
+ const option = options.nth(index);
70
+ const isChecked = (await option.getAttribute('aria-checked')) === 'true';
71
+ if (!isChecked) {
72
+ await option.click({ timeout: 15000 });
73
+ return true;
74
+ }
75
+ }
76
+ await page.keyboard.press('Escape').catch(() => false);
77
+ return false;
78
+ }
79
+ exports.changeDashboardDateRange = changeDashboardDateRange;
80
+ function isAgenticDashboardDefinitionResponse(response) {
81
+ return response.url.toLowerCase().includes(exports.AGENTIC_DASHBOARD_DEFINITION_PATH);
82
+ }
83
+ exports.isAgenticDashboardDefinitionResponse = isAgenticDashboardDefinitionResponse;
84
+ function isReportEvaluateResponse(response) {
85
+ return exports.REPORT_EVALUATE_PATH_PATTERN.test(response.url.toLowerCase());
86
+ }
87
+ exports.isReportEvaluateResponse = isReportEvaluateResponse;
88
+ function isLikelyDashboardApiResponse(response) {
89
+ return (isAgenticDashboardDefinitionResponse(response) ||
90
+ isReportEvaluateResponse(response));
91
+ }
92
+ exports.isLikelyDashboardApiResponse = isLikelyDashboardApiResponse;
93
+ async function captureDashboardResponses(page, action) {
94
+ const captured = [];
95
+ const listener = async (response) => {
96
+ try {
97
+ const request = response.request();
98
+ const method = request.method();
99
+ if (method !== 'GET' && method !== 'POST')
100
+ return;
101
+ const contentType = response.headers()['content-type'] || '';
102
+ if (!contentType.includes('application/json'))
103
+ return;
104
+ const bodyText = await response.text();
105
+ captured.push({
106
+ url: response.url(),
107
+ method,
108
+ status: response.status(),
109
+ bodyText,
110
+ contentType,
111
+ });
112
+ }
113
+ catch {
114
+ return;
115
+ }
116
+ };
117
+ page.on('response', listener);
118
+ await action();
119
+ await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => { });
120
+ await page.waitForTimeout(5000);
121
+ page.off('response', listener);
122
+ return captured;
123
+ }
124
+ exports.captureDashboardResponses = captureDashboardResponses;
125
+ function parseJsonResponseBodies(responses) {
126
+ const parsed = [];
127
+ for (const response of responses) {
128
+ try {
129
+ parsed.push(JSON.parse(response.bodyText));
130
+ }
131
+ catch {
132
+ continue;
133
+ }
134
+ }
135
+ return parsed;
136
+ }
137
+ exports.parseJsonResponseBodies = parseJsonResponseBodies;
138
+ function findReportByName(bodies, name) {
139
+ const target = name.toLowerCase();
140
+ for (const body of bodies) {
141
+ if (body !== null &&
142
+ typeof body === 'object' &&
143
+ typeof body.name === 'string' &&
144
+ (body.name.toLowerCase() === target ||
145
+ body.name.toLowerCase().includes(target))) {
146
+ return body;
147
+ }
148
+ }
149
+ return undefined;
150
+ }
151
+ exports.findReportByName = findReportByName;
152
+ function getReportNumericResult(body) {
153
+ if (body === null || typeof body !== 'object')
154
+ return undefined;
155
+ const result = body.result;
156
+ if (result === null || typeof result !== 'object')
157
+ return undefined;
158
+ const measures = result.measures;
159
+ if (Array.isArray(measures)) {
160
+ for (const measure of measures) {
161
+ const data = measure?.data;
162
+ if (typeof data === 'number' && Number.isFinite(data))
163
+ return data;
164
+ }
165
+ }
166
+ const instanceCount = result.instanceCount;
167
+ if (typeof instanceCount === 'number' && Number.isFinite(instanceCount)) {
168
+ return instanceCount;
169
+ }
170
+ return undefined;
171
+ }
172
+ exports.getReportNumericResult = getReportNumericResult;
173
+ function dashboardHasComparisonTile(definition) {
174
+ if (definition === null || typeof definition !== 'object')
175
+ return false;
176
+ const tiles = definition.tiles;
177
+ if (!Array.isArray(tiles))
178
+ return false;
179
+ return tiles.some((tile) => {
180
+ const configuration = tile?.configuration;
181
+ return (configuration !== null &&
182
+ typeof configuration === 'object' &&
183
+ configuration.comparisonPeriod === true);
184
+ });
185
+ }
186
+ exports.dashboardHasComparisonTile = dashboardHasComparisonTile;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.742",
3
+ "version": "0.0.743",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",