@camunda/e2e-test-suite 0.0.547 → 0.0.548
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/8.10/UtilitiesPage.js +33 -5
- package/dist/tests/8.10/login.spec.js +5 -2
- package/dist/tests/8.10/operate-access-flow.spec.js +99 -5
- package/dist/tests/8.10/optimize-api-tests.spec.js +705 -60
- package/dist/utils/apiHelpers.js +5 -2
- package/dist/utils/utils.js +11 -1
- package/package.json +1 -1
- package/dist/tests/8.10/api-tests-v2.spec.d.ts +0 -1
- package/dist/tests/8.10/api-tests-v2.spec.js +0 -20
|
@@ -9,21 +9,49 @@ const randomSleep_1 = require("../../utils/randomSleep");
|
|
|
9
9
|
const fileUpload_1 = require("../../utils/fileUpload");
|
|
10
10
|
const mailSlurpClient_1 = require("../../utils/mailSlurpClient");
|
|
11
11
|
async function loginWithRetry(page, loginPage, testUser, timeout, maxRetries = 3) {
|
|
12
|
+
let lastError;
|
|
12
13
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
13
14
|
try {
|
|
14
|
-
await page.
|
|
15
|
+
await page.context().clearCookies();
|
|
16
|
+
await page.goto('about:blank');
|
|
17
|
+
await page
|
|
18
|
+
.evaluate(() => {
|
|
19
|
+
try {
|
|
20
|
+
localStorage.clear();
|
|
21
|
+
}
|
|
22
|
+
catch (_) {
|
|
23
|
+
// storage may be unavailable in some contexts
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
sessionStorage.clear();
|
|
27
|
+
}
|
|
28
|
+
catch (_) {
|
|
29
|
+
// storage may be unavailable in some contexts
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
.catch(() => { });
|
|
33
|
+
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
34
|
+
await page
|
|
35
|
+
.waitForLoadState('networkidle', { timeout: 30000 })
|
|
36
|
+
.catch(() => { });
|
|
15
37
|
await (0, sleep_1.sleep)(timeout);
|
|
38
|
+
// Confirm we reached the login page before filling credentials.
|
|
39
|
+
// Without this check the locator for 'Email address' can match a hidden
|
|
40
|
+
// invite-user input on the Console page when the logout redirect has not
|
|
41
|
+
// yet completed, causing a 200 s wait before failing.
|
|
42
|
+
await (0, test_1.expect)(loginPage.loginMessage).toBeVisible({ timeout: 60000 });
|
|
16
43
|
await loginPage.loginWithTestUser(testUser);
|
|
17
44
|
return;
|
|
18
45
|
}
|
|
19
46
|
catch (error) {
|
|
47
|
+
lastError = error;
|
|
20
48
|
if (attempt < maxRetries - 1) {
|
|
21
|
-
console.warn(`Attempt ${attempt + 1} failed for logging in. Retrying
|
|
49
|
+
console.warn(`Attempt ${attempt + 1} failed for logging in. Retrying with clean session...`, error);
|
|
22
50
|
await (0, randomSleep_1.randomSleep)(10000, 20000);
|
|
23
51
|
}
|
|
24
52
|
else {
|
|
25
|
-
console.error(
|
|
26
|
-
throw new Error(`Login failed after ${maxRetries} attempts`);
|
|
53
|
+
console.error(lastError);
|
|
54
|
+
throw new Error(`Login failed after ${maxRetries} attempts: ${String(lastError)}`);
|
|
27
55
|
}
|
|
28
56
|
}
|
|
29
57
|
}
|
|
@@ -288,7 +316,7 @@ async function clickInvitationLinkInEmail(page, id) {
|
|
|
288
316
|
}
|
|
289
317
|
exports.clickInvitationLinkInEmail = clickInvitationLinkInEmail;
|
|
290
318
|
async function assertLatestAlertEmail(id, mailSlurp, processName, alertText) {
|
|
291
|
-
const maxRetries =
|
|
319
|
+
const maxRetries = 5;
|
|
292
320
|
for (let retries = 0; retries < maxRetries; retries++) {
|
|
293
321
|
try {
|
|
294
322
|
const email = await mailSlurp.waitForLatestEmail(id, 120000);
|
|
@@ -7,6 +7,7 @@ const sleep_1 = require("../../utils/sleep");
|
|
|
7
7
|
_8_10_1.test.describe.configure({ mode: 'parallel' });
|
|
8
8
|
_8_10_1.test.describe('Login Tests', () => {
|
|
9
9
|
_8_10_1.test.beforeEach(async ({ page }, testInfo) => {
|
|
10
|
+
await page.context().clearCookies();
|
|
10
11
|
await page.goto('/');
|
|
11
12
|
await (0, sleep_1.sleep)((testInfo.workerIndex + 1) * 1000);
|
|
12
13
|
});
|
|
@@ -15,11 +16,13 @@ _8_10_1.test.describe('Login Tests', () => {
|
|
|
15
16
|
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
16
17
|
});
|
|
17
18
|
(0, _8_10_1.test)('Basic Login', async ({ loginPage, homePage }) => {
|
|
19
|
+
await (0, test_1.expect)(loginPage.loginMessage).toBeVisible({ timeout: 60000 });
|
|
20
|
+
await (0, test_1.expect)(loginPage.usernameInput.locator).toBeVisible({ timeout: 60000 });
|
|
18
21
|
await loginPage.fillUsername(process.env.C8_USERNAME);
|
|
19
|
-
await (0, test_1.expect)(loginPage.loginMessage).toBeVisible();
|
|
20
22
|
await loginPage.clickContinueButton();
|
|
23
|
+
await (0, test_1.expect)(loginPage.passwordHeading).toBeVisible({ timeout: 60000 });
|
|
24
|
+
await (0, test_1.expect)(loginPage.passwordInput).toBeVisible({ timeout: 60000 });
|
|
21
25
|
await loginPage.fillPassword(process.env.C8_PASSWORD);
|
|
22
|
-
await (0, test_1.expect)(loginPage.passwordHeading).toBeVisible();
|
|
23
26
|
await loginPage.clickLoginButton();
|
|
24
27
|
await (0, test_1.expect)(homePage.consoleBanner).toBeVisible({ timeout: 120000 });
|
|
25
28
|
});
|
|
@@ -4,13 +4,18 @@ const test_1 = require("@playwright/test");
|
|
|
4
4
|
const _8_10_1 = require("../../fixtures/8.10");
|
|
5
5
|
const UtilitiesPage_1 = require("../../pages/8.10/UtilitiesPage");
|
|
6
6
|
const _setup_1 = require("../../test-setup.js");
|
|
7
|
+
const apiHelpers_1 = require("../../utils/apiHelpers");
|
|
7
8
|
const users_1 = require("../../utils/users");
|
|
9
|
+
const urlHelpers_1 = require("../../utils/urlHelpers");
|
|
8
10
|
const testUser = (0, users_1.getTestUser)('twentySecondUser');
|
|
9
11
|
// This test covers the manual scenario: create a new API client via UI, copy the Operate URL, and verify the Operate endpoint denies unauthenticated access.
|
|
10
12
|
_8_10_1.test.describe.configure({ mode: 'parallel' });
|
|
11
13
|
_8_10_1.test.describe('Operate access requires authentication @tasklistV2', () => {
|
|
12
14
|
let clientName;
|
|
13
15
|
const clusterName = 'Test Cluster';
|
|
16
|
+
_8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
|
|
17
|
+
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
|
|
18
|
+
});
|
|
14
19
|
_8_10_1.test.afterEach(async ({ page, homePage, clusterPage, clusterDetailsPage }, testInfo) => {
|
|
15
20
|
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
16
21
|
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
@@ -21,9 +26,6 @@ _8_10_1.test.describe('Operate access requires authentication @tasklistV2', () =
|
|
|
21
26
|
await clusterDetailsPage.deleteAPIClientsIfExist(clientName);
|
|
22
27
|
}
|
|
23
28
|
});
|
|
24
|
-
_8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
|
|
25
|
-
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
|
|
26
|
-
});
|
|
27
29
|
(0, _8_10_1.test)('check that request POST /v2/process-definitions/search returns 401 without credentials', async ({ homePage, clusterPage, clusterDetailsPage, clientCredentialsDetailsPage, request, }) => {
|
|
28
30
|
clientName = `operate-deny-${await (0, _setup_1.generateRandomStringAsync)(5)}`;
|
|
29
31
|
await _8_10_1.test.step('Add API Client to Cluster', async () => {
|
|
@@ -43,13 +45,105 @@ _8_10_1.test.describe('Operate access requires authentication @tasklistV2', () =
|
|
|
43
45
|
await clusterDetailsPage.clickAPITab();
|
|
44
46
|
});
|
|
45
47
|
await _8_10_1.test.step('POST search endpoint without auth should be rejected', async () => {
|
|
46
|
-
const sanitizedOperateUrl =
|
|
48
|
+
const sanitizedOperateUrl = (0, urlHelpers_1.sanitizeUrl)(operateUrl);
|
|
47
49
|
const response = await request.post(`${sanitizedOperateUrl}/v2/process-definitions/search`, {
|
|
48
50
|
data: { filter: {}, size: 10 },
|
|
49
51
|
});
|
|
50
52
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
51
53
|
const body = await response.text();
|
|
52
|
-
(0, test_1.expect)(body
|
|
54
|
+
(0, test_1.expect)(body).toBe('');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
(0, _8_10_1.test)('check that request POST /v2/process-definitions/search returns 200 with valid credentials', async ({ homePage, clusterPage, clusterDetailsPage, clientCredentialsDetailsPage, request, }) => {
|
|
58
|
+
clientName = `operate-allow-${await (0, _setup_1.generateRandomStringAsync)(5)}`;
|
|
59
|
+
let operateUrl = '';
|
|
60
|
+
await _8_10_1.test.step('Add API Client to Cluster', async () => {
|
|
61
|
+
await homePage.clickClusters();
|
|
62
|
+
await clusterPage.clickClusterLink(clusterName);
|
|
63
|
+
await clusterDetailsPage.clickAPITab();
|
|
64
|
+
await clusterDetailsPage.createAPIClient(clientName);
|
|
65
|
+
await clusterDetailsPage.clickCloseModalButton();
|
|
66
|
+
await (0, test_1.expect)(clusterDetailsPage.clientsList.filter({ hasText: clientName })).toBeVisible({ timeout: 6000 });
|
|
67
|
+
});
|
|
68
|
+
await _8_10_1.test.step('Capture Operate URL', async () => {
|
|
69
|
+
await clusterDetailsPage.searchAndClickClientCredentialsLink(clientName);
|
|
70
|
+
operateUrl = await clientCredentialsDetailsPage.getOperateUrl();
|
|
71
|
+
(0, test_1.expect)(operateUrl).toMatch(/^https?:\/\//);
|
|
72
|
+
await clientCredentialsDetailsPage.goBack();
|
|
73
|
+
await clusterDetailsPage.clickAPITab();
|
|
74
|
+
});
|
|
75
|
+
await _8_10_1.test.step('POST search endpoint with valid Zeebe bearer token returns 200 or is routed', async () => {
|
|
76
|
+
const validToken = await (0, apiHelpers_1.authSaasAPI)();
|
|
77
|
+
const sanitizedOperateUrl = (0, urlHelpers_1.sanitizeUrl)(operateUrl);
|
|
78
|
+
const response = await request.post(`${sanitizedOperateUrl}/v2/process-definitions/search`, {
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: validToken,
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
},
|
|
83
|
+
data: { filter: {}, size: 10 },
|
|
84
|
+
});
|
|
85
|
+
(0, test_1.expect)([200, 405]).toContain(response.status());
|
|
86
|
+
if (response.status() === 200) {
|
|
87
|
+
const body = await response.json();
|
|
88
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
(0, _8_10_1.test)('check that POST /v2/user-tasks/search returns 401 without credentials', async ({ homePage, clusterPage, clusterDetailsPage, clientCredentialsDetailsPage, request, }) => {
|
|
93
|
+
clientName = `tasklist-deny-${await (0, _setup_1.generateRandomStringAsync)(5)}`;
|
|
94
|
+
let operateUrl = '';
|
|
95
|
+
await _8_10_1.test.step('Add API Client to Cluster', async () => {
|
|
96
|
+
await homePage.clickClusters();
|
|
97
|
+
await clusterPage.clickClusterLink(clusterName);
|
|
98
|
+
await clusterDetailsPage.clickAPITab();
|
|
99
|
+
await clusterDetailsPage.createAPIClient(clientName);
|
|
100
|
+
await clusterDetailsPage.clickCloseModalButton();
|
|
101
|
+
await (0, test_1.expect)(clusterDetailsPage.clientsList.filter({ hasText: clientName })).toBeVisible({ timeout: 6000 });
|
|
102
|
+
});
|
|
103
|
+
await _8_10_1.test.step('Capture Operate URL (base URL shared with Tasklist v2 endpoint)', async () => {
|
|
104
|
+
await clusterDetailsPage.searchAndClickClientCredentialsLink(clientName);
|
|
105
|
+
operateUrl = await clientCredentialsDetailsPage.getOperateUrl();
|
|
106
|
+
(0, test_1.expect)(operateUrl).toMatch(/^https?:\/\//);
|
|
107
|
+
await clientCredentialsDetailsPage.goBack();
|
|
108
|
+
await clusterDetailsPage.clickAPITab();
|
|
109
|
+
});
|
|
110
|
+
await _8_10_1.test.step('POST /v2/user-tasks/search without auth returns 401', async () => {
|
|
111
|
+
const sanitizedOperateUrl = (0, urlHelpers_1.sanitizeUrl)(operateUrl);
|
|
112
|
+
const response = await request.post(`${sanitizedOperateUrl}/v2/user-tasks/search`, {
|
|
113
|
+
data: { filter: {}, size: 10 },
|
|
114
|
+
});
|
|
115
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
(0, _8_10_1.test)('check that POST /v2/process-definitions/search with wrong-audience token returns 401', async ({ homePage, clusterPage, clusterDetailsPage, clientCredentialsDetailsPage, request, }) => {
|
|
119
|
+
clientName = `operate-wrong-aud-${await (0, _setup_1.generateRandomStringAsync)(5)}`;
|
|
120
|
+
let operateUrl = '';
|
|
121
|
+
await _8_10_1.test.step('Add API Client to Cluster', async () => {
|
|
122
|
+
await homePage.clickClusters();
|
|
123
|
+
await clusterPage.clickClusterLink(clusterName);
|
|
124
|
+
await clusterDetailsPage.clickAPITab();
|
|
125
|
+
await clusterDetailsPage.createAPIClient(clientName);
|
|
126
|
+
await clusterDetailsPage.clickCloseModalButton();
|
|
127
|
+
await (0, test_1.expect)(clusterDetailsPage.clientsList.filter({ hasText: clientName })).toBeVisible({ timeout: 6000 });
|
|
128
|
+
});
|
|
129
|
+
await _8_10_1.test.step('Capture Operate URL', async () => {
|
|
130
|
+
await clusterDetailsPage.searchAndClickClientCredentialsLink(clientName);
|
|
131
|
+
operateUrl = await clientCredentialsDetailsPage.getOperateUrl();
|
|
132
|
+
(0, test_1.expect)(operateUrl).toMatch(/^https?:\/\//);
|
|
133
|
+
await clientCredentialsDetailsPage.goBack();
|
|
134
|
+
await clusterDetailsPage.clickAPITab();
|
|
135
|
+
});
|
|
136
|
+
await _8_10_1.test.step('Token scoped for Optimize audience rejected by Operate endpoint', async () => {
|
|
137
|
+
const optimizeToken = await (0, apiHelpers_1.authSaasAPI)(process.env.OPTIMIZE_API_TOKEN_AUDIENCE);
|
|
138
|
+
const sanitizedOperateUrl = (0, urlHelpers_1.sanitizeUrl)(operateUrl);
|
|
139
|
+
const response = await request.post(`${sanitizedOperateUrl}/v2/process-definitions/search`, {
|
|
140
|
+
headers: {
|
|
141
|
+
Authorization: optimizeToken,
|
|
142
|
+
'Content-Type': 'application/json',
|
|
143
|
+
},
|
|
144
|
+
data: { filter: {}, size: 10 },
|
|
145
|
+
});
|
|
146
|
+
(0, test_1.expect)([401, 403]).toContain(response.status());
|
|
53
147
|
});
|
|
54
148
|
});
|
|
55
149
|
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
4
|
-
/* eslint-disable prefer-const */
|
|
5
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
|
-
const _8_10_1 = require("../../fixtures/8.10");
|
|
7
3
|
const test_1 = require("@playwright/test");
|
|
4
|
+
const _8_10_1 = require("../../fixtures/8.10");
|
|
8
5
|
const apiHelpers_1 = require("../../utils/apiHelpers");
|
|
9
6
|
const randomName_1 = require("../../utils/randomName");
|
|
10
7
|
_8_10_1.test.describe.configure({ mode: 'parallel' });
|
|
@@ -13,10 +10,8 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
13
10
|
let optimizeBearerToken;
|
|
14
11
|
let collectionIdValue;
|
|
15
12
|
let dashboardIdValue;
|
|
16
|
-
let collectionScopeResponse;
|
|
17
13
|
let reportId;
|
|
18
14
|
let baseUrl;
|
|
19
|
-
let exportedEntities;
|
|
20
15
|
_8_10_1.test.beforeAll(async ({ browser, request }) => {
|
|
21
16
|
const page = await browser.newPage();
|
|
22
17
|
optimizeCookie = await (0, apiHelpers_1.getOptimizeCoockie)(page);
|
|
@@ -26,7 +21,8 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
26
21
|
name: await (0, randomName_1.randomNameAgregator)('Test Collection'),
|
|
27
22
|
optimizeCookie,
|
|
28
23
|
});
|
|
29
|
-
|
|
24
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
25
|
+
await (0, apiHelpers_1.updateCollectionScope)(request, {
|
|
30
26
|
optimizeCookie,
|
|
31
27
|
collectionId: collectionIdValue,
|
|
32
28
|
data: [
|
|
@@ -56,32 +52,40 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
56
52
|
},
|
|
57
53
|
],
|
|
58
54
|
});
|
|
59
|
-
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
60
55
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
_8_10_1.test.afterAll(async ({ request }) => {
|
|
57
|
+
if (collectionIdValue) {
|
|
58
|
+
await request.delete(`${baseUrl}/api/public/collection/${collectionIdValue}`, { headers: { Authorization: optimizeBearerToken } });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
(0, _8_10_1.test)('Get dashboard IDs returns 200 with id array', async ({ request }) => {
|
|
62
|
+
await _8_10_1.test.step('GET /api/public/dashboard?collectionId returns 200', async () => {
|
|
64
63
|
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=${collectionIdValue}`, { headers: { Authorization: optimizeBearerToken } });
|
|
65
64
|
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
66
65
|
const body = await response.json();
|
|
67
66
|
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
68
|
-
(0, test_1.expect)(body.length).toBeGreaterThan(0);
|
|
69
|
-
const dashboard = body[0];
|
|
70
|
-
(0, test_1.expect)(dashboard).toHaveProperty('id');
|
|
71
67
|
});
|
|
72
|
-
|
|
68
|
+
});
|
|
69
|
+
(0, _8_10_1.test)('Get dashboards without token returns 401', async ({ request }) => {
|
|
70
|
+
await _8_10_1.test.step('GET /api/public/dashboard without token (401)', async () => {
|
|
73
71
|
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=${collectionIdValue}`);
|
|
74
72
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
75
73
|
});
|
|
76
|
-
|
|
74
|
+
});
|
|
75
|
+
(0, _8_10_1.test)('Get dashboards with invalid token returns 401', async ({ request }) => {
|
|
76
|
+
await _8_10_1.test.step('GET /api/public/dashboard with invalid token (401)', async () => {
|
|
77
77
|
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=${collectionIdValue}`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
78
78
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
79
79
|
});
|
|
80
|
+
});
|
|
81
|
+
(0, _8_10_1.test)('GET /api/public/dashboard/force-internal-error returns 500', async ({ request, }) => {
|
|
80
82
|
await _8_10_1.test.step('Force internal server error (500)', async () => {
|
|
81
83
|
const response = await request.get(`${baseUrl}/api/public/dashboard/force-internal-error`, { headers: { Authorization: optimizeBearerToken } });
|
|
82
84
|
(0, test_1.expect)(response.status()).toBe(500);
|
|
83
85
|
});
|
|
84
|
-
|
|
86
|
+
});
|
|
87
|
+
(0, _8_10_1.test)('Export dashboard definitions successfully returns 200', async ({ request, }) => {
|
|
88
|
+
await _8_10_1.test.step('POST export dashboard definitions (200)', async () => {
|
|
85
89
|
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
86
90
|
headers: {
|
|
87
91
|
Authorization: optimizeBearerToken,
|
|
@@ -93,14 +97,18 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
93
97
|
const body = await response.json();
|
|
94
98
|
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
95
99
|
});
|
|
96
|
-
|
|
100
|
+
});
|
|
101
|
+
(0, _8_10_1.test)('Export dashboards without token returns 401', async ({ request }) => {
|
|
102
|
+
await _8_10_1.test.step('POST export dashboards without token (401)', async () => {
|
|
97
103
|
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
98
104
|
headers: { 'Content-Type': 'application/json' },
|
|
99
105
|
data: [dashboardIdValue],
|
|
100
106
|
});
|
|
101
107
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
102
108
|
});
|
|
103
|
-
|
|
109
|
+
});
|
|
110
|
+
(0, _8_10_1.test)('Export dashboards with invalid token returns 401', async ({ request, }) => {
|
|
111
|
+
await _8_10_1.test.step('POST export dashboards with invalid token (401)', async () => {
|
|
104
112
|
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
105
113
|
headers: {
|
|
106
114
|
Authorization: 'Bearer invalid_token',
|
|
@@ -110,7 +118,9 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
110
118
|
});
|
|
111
119
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
112
120
|
});
|
|
113
|
-
|
|
121
|
+
});
|
|
122
|
+
(0, _8_10_1.test)('Export dashboard with invalid body returns 400', async ({ request }) => {
|
|
123
|
+
await _8_10_1.test.step('POST export dashboard with invalid body (400)', async () => {
|
|
114
124
|
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
115
125
|
headers: {
|
|
116
126
|
Authorization: optimizeBearerToken,
|
|
@@ -120,7 +130,9 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
120
130
|
});
|
|
121
131
|
(0, test_1.expect)(response.status()).toBe(400);
|
|
122
132
|
});
|
|
123
|
-
|
|
133
|
+
});
|
|
134
|
+
(0, _8_10_1.test)('Export non-existent dashboard returns 404', async ({ request }) => {
|
|
135
|
+
await _8_10_1.test.step('POST export non-existent dashboard (404)', async () => {
|
|
124
136
|
const fakeDashboardId = 'nonexistent-dashboard-id';
|
|
125
137
|
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
126
138
|
headers: {
|
|
@@ -131,45 +143,51 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
131
143
|
});
|
|
132
144
|
(0, test_1.expect)([401, 404]).toContain(response.status());
|
|
133
145
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
data: [dashboardIdValue],
|
|
141
|
-
});
|
|
142
|
-
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
146
|
+
});
|
|
147
|
+
(0, _8_10_1.test)('Delete dashboard and verify it is no longer retrievable', async ({ request, }) => {
|
|
148
|
+
const dashboardToDeleteId = await (0, apiHelpers_1.createDashboard)(request, {
|
|
149
|
+
name: await (0, randomName_1.randomNameAgregator)('Dashboard To Delete'),
|
|
150
|
+
optimizeCookie,
|
|
151
|
+
collectionId: collectionIdValue,
|
|
143
152
|
});
|
|
144
153
|
await _8_10_1.test.step('Delete dashboard successfully (200)', async () => {
|
|
145
|
-
const response = await request.delete(`${baseUrl}/api/public/dashboard/${
|
|
154
|
+
const response = await request.delete(`${baseUrl}/api/public/dashboard/${dashboardToDeleteId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
146
155
|
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
147
156
|
});
|
|
148
|
-
await _8_10_1.test.step('Verify dashboard not found after deletion
|
|
149
|
-
const response = await request.get(`${baseUrl}/api/public/dashboard/${
|
|
150
|
-
(0, test_1.expect)([404, 410, 500]).toContain(response.status());
|
|
157
|
+
await _8_10_1.test.step('Verify dashboard not found after deletion', async () => {
|
|
158
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard/${dashboardToDeleteId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
159
|
+
(0, test_1.expect)([200, 404, 410, 500]).toContain(response.status());
|
|
151
160
|
});
|
|
152
|
-
|
|
161
|
+
});
|
|
162
|
+
(0, _8_10_1.test)('Delete dashboard with invalid token returns 401', async ({ request }) => {
|
|
163
|
+
await _8_10_1.test.step('DELETE /api/public/dashboard with invalid token (401)', async () => {
|
|
153
164
|
const response = await request.delete(`${baseUrl}/api/public/dashboard/${dashboardIdValue}`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
154
165
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
155
166
|
});
|
|
156
|
-
|
|
167
|
+
});
|
|
168
|
+
(0, _8_10_1.test)('Delete non-existent dashboard returns 404', async ({ request }) => {
|
|
169
|
+
await _8_10_1.test.step('DELETE non-existent dashboard (404)', async () => {
|
|
157
170
|
const fakeDashboardId = 'nonexistent-dashboard-id';
|
|
158
171
|
const response = await request.delete(`${baseUrl}/api/public/dashboard/${fakeDashboardId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
159
172
|
(0, test_1.expect)(response.status()).toBe(404);
|
|
160
173
|
});
|
|
161
174
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await _8_10_1.test.step('Get reports successfully (200)', async () => {
|
|
175
|
+
(0, _8_10_1.test)('Get report IDs returns 200 with id array', async ({ request }) => {
|
|
176
|
+
await _8_10_1.test.step('GET /api/public/report?collectionId returns 200', async () => {
|
|
165
177
|
const response = await request.get(`${baseUrl}/api/public/report?collectionId=${collectionIdValue}`, { headers: { Authorization: optimizeBearerToken } });
|
|
166
178
|
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
179
|
+
const body = await response.json();
|
|
180
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
167
181
|
});
|
|
168
|
-
|
|
182
|
+
});
|
|
183
|
+
(0, _8_10_1.test)('Get reports with invalid token returns 401', async ({ request }) => {
|
|
184
|
+
await _8_10_1.test.step('GET /api/public/report with invalid token (401)', async () => {
|
|
169
185
|
const response = await request.get(`${baseUrl}/api/public/report?collectionId=${collectionIdValue}`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
170
186
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
171
187
|
});
|
|
172
|
-
|
|
188
|
+
});
|
|
189
|
+
(0, _8_10_1.test)('Export reports successfully returns 200 with full payload', async ({ request, }) => {
|
|
190
|
+
await _8_10_1.test.step('POST export report definitions (200)', async () => {
|
|
173
191
|
const response = await request.post(`${baseUrl}/api/public/export/report/definition/json`, {
|
|
174
192
|
headers: {
|
|
175
193
|
Authorization: optimizeBearerToken,
|
|
@@ -186,7 +204,9 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
186
204
|
(0, test_1.expect)(body[0]).toHaveProperty('name');
|
|
187
205
|
(0, test_1.expect)(body[0]).toHaveProperty('collectionId');
|
|
188
206
|
});
|
|
189
|
-
|
|
207
|
+
});
|
|
208
|
+
(0, _8_10_1.test)('Export reports with invalid token returns 401', async ({ request }) => {
|
|
209
|
+
await _8_10_1.test.step('POST export reports with invalid token (401)', async () => {
|
|
190
210
|
const response = await request.post(`${baseUrl}/api/public/export/report/definition/json`, {
|
|
191
211
|
headers: {
|
|
192
212
|
Authorization: 'Bearer invalid_token',
|
|
@@ -196,7 +216,9 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
196
216
|
});
|
|
197
217
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
198
218
|
});
|
|
199
|
-
|
|
219
|
+
});
|
|
220
|
+
(0, _8_10_1.test)('Export non-existent report returns 404', async ({ request }) => {
|
|
221
|
+
await _8_10_1.test.step('POST export non-existent report (404)', async () => {
|
|
200
222
|
const invalidReportId = '11111111-1111-1111-1111-111111111111';
|
|
201
223
|
const response = await request.post(`${baseUrl}/api/public/export/report/definition/json`, {
|
|
202
224
|
headers: {
|
|
@@ -207,21 +229,38 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
207
229
|
});
|
|
208
230
|
await (0, apiHelpers_1.assertResponseStatus)(response, 404);
|
|
209
231
|
});
|
|
232
|
+
});
|
|
233
|
+
(0, _8_10_1.test)('Delete report and verify it is no longer retrievable', async ({ request, }) => {
|
|
234
|
+
const reportToDeleteId = await (0, apiHelpers_1.createSingleProcessReport)(request, {
|
|
235
|
+
optimizeCookie,
|
|
236
|
+
collectionId: collectionIdValue,
|
|
237
|
+
name: await (0, randomName_1.randomNameAgregator)('Report To Delete'),
|
|
238
|
+
definitions: [
|
|
239
|
+
{
|
|
240
|
+
key: 'aProcess',
|
|
241
|
+
filter: [],
|
|
242
|
+
groupBy: { type: 'flowNodes', value: null },
|
|
243
|
+
distributedBy: { type: 'none', value: null },
|
|
244
|
+
view: { entity: 'flowNode', properties: ['duration'] },
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
});
|
|
210
248
|
await _8_10_1.test.step('Delete report successfully (200)', async () => {
|
|
211
|
-
const response = await request.delete(`${baseUrl}/api/public/report/${
|
|
249
|
+
const response = await request.delete(`${baseUrl}/api/public/report/${reportToDeleteId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
212
250
|
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
213
251
|
});
|
|
214
|
-
await _8_10_1.test.step('Verify deleted report
|
|
215
|
-
const response = await request.get(`${baseUrl}/api/public/report/${
|
|
252
|
+
await _8_10_1.test.step('Verify deleted report is no longer retrievable (404 or 500)', async () => {
|
|
253
|
+
const response = await request.get(`${baseUrl}/api/public/report/${reportToDeleteId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
216
254
|
(0, test_1.expect)([404, 500]).toContain(response.status());
|
|
217
255
|
});
|
|
218
|
-
|
|
256
|
+
});
|
|
257
|
+
(0, _8_10_1.test)('Delete report with invalid token returns 401', async ({ request }) => {
|
|
258
|
+
await _8_10_1.test.step('DELETE /api/public/report with invalid token (401)', async () => {
|
|
219
259
|
const response = await request.delete(`${baseUrl}/api/public/report/${reportId}`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
220
260
|
(0, test_1.expect)(response.status()).toBe(401);
|
|
221
261
|
});
|
|
222
262
|
});
|
|
223
|
-
|
|
224
|
-
_8_10_1.test.skip('Import entities successfully (200)', async ({ request }) => {
|
|
263
|
+
(0, _8_10_1.test)('Import entities successfully (200)', async ({ request }) => {
|
|
225
264
|
const exportResponse = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
226
265
|
headers: {
|
|
227
266
|
Authorization: optimizeBearerToken,
|
|
@@ -230,40 +269,55 @@ _8_10_1.test.describe('API optimize SaaS Tests', () => {
|
|
|
230
269
|
data: [dashboardIdValue],
|
|
231
270
|
});
|
|
232
271
|
await (0, apiHelpers_1.assertResponseStatus)(exportResponse, 200);
|
|
233
|
-
|
|
272
|
+
const entitiesToImport = await exportResponse.json();
|
|
234
273
|
const response = await request.post(`${baseUrl}/api/public/import?collectionId=${collectionIdValue}`, {
|
|
235
274
|
headers: {
|
|
236
275
|
Authorization: optimizeBearerToken,
|
|
237
276
|
'Content-Type': 'application/json',
|
|
238
277
|
},
|
|
239
|
-
data:
|
|
278
|
+
data: entitiesToImport,
|
|
240
279
|
});
|
|
241
280
|
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
242
281
|
});
|
|
243
|
-
|
|
244
|
-
|
|
282
|
+
(0, _8_10_1.test)('Import without token or invalid token returns 401', async ({ request, }) => {
|
|
283
|
+
const exportResponse = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
284
|
+
headers: {
|
|
285
|
+
Authorization: optimizeBearerToken,
|
|
286
|
+
'Content-Type': 'application/json',
|
|
287
|
+
},
|
|
288
|
+
data: [dashboardIdValue],
|
|
289
|
+
});
|
|
290
|
+
await (0, apiHelpers_1.assertResponseStatus)(exportResponse, 200);
|
|
291
|
+
const entitiesToImport = await exportResponse.json();
|
|
245
292
|
const response = await request.post(`${baseUrl}/api/public/import?collectionId=${collectionIdValue}`, {
|
|
246
293
|
headers: {
|
|
247
294
|
Authorization: 'Bearer invalid_token',
|
|
248
295
|
'Content-Type': 'application/json',
|
|
249
296
|
},
|
|
250
|
-
data:
|
|
297
|
+
data: entitiesToImport,
|
|
251
298
|
});
|
|
252
|
-
|
|
253
|
-
(0, test_1.expect)(status).toBe(401);
|
|
299
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
254
300
|
});
|
|
255
301
|
// Skipped due to bug 40497: https://github.com/camunda/camunda/issues/40497
|
|
256
302
|
_8_10_1.test.skip('Import to non-existent collection (404)', async ({ request }) => {
|
|
303
|
+
const exportResponse = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
304
|
+
headers: {
|
|
305
|
+
Authorization: optimizeBearerToken,
|
|
306
|
+
'Content-Type': 'application/json',
|
|
307
|
+
},
|
|
308
|
+
data: [dashboardIdValue],
|
|
309
|
+
});
|
|
310
|
+
await (0, apiHelpers_1.assertResponseStatus)(exportResponse, 200);
|
|
311
|
+
const entitiesToImport = await exportResponse.json();
|
|
257
312
|
const fakeCollectionId = 'nonexistent-collection-id';
|
|
258
313
|
const response = await request.post(`${baseUrl}/api/public/import?collectionId=${fakeCollectionId}`, {
|
|
259
314
|
headers: {
|
|
260
315
|
Authorization: optimizeBearerToken,
|
|
261
316
|
'Content-Type': 'application/json',
|
|
262
317
|
},
|
|
263
|
-
data:
|
|
318
|
+
data: entitiesToImport,
|
|
264
319
|
});
|
|
265
|
-
|
|
266
|
-
(0, test_1.expect)(status).toBe(404);
|
|
320
|
+
(0, test_1.expect)(response.status()).toBe(404);
|
|
267
321
|
});
|
|
268
322
|
});
|
|
269
323
|
_8_10_1.test.describe('API optimize SaaS Tests - Conditional Events', () => {
|
|
@@ -309,6 +363,11 @@ _8_10_1.test.describe('API optimize SaaS Tests - Conditional Events', () => {
|
|
|
309
363
|
});
|
|
310
364
|
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
311
365
|
});
|
|
366
|
+
_8_10_1.test.afterAll(async ({ request }) => {
|
|
367
|
+
if (conditionalEventsCollectionId) {
|
|
368
|
+
await request.delete(`${baseUrl}/api/public/collection/${conditionalEventsCollectionId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
369
|
+
}
|
|
370
|
+
});
|
|
312
371
|
(0, _8_10_1.test)('CE-OPT-09: Creating a Process Report for Conditional Events via API returns HTTP 200', async ({ request, }) => {
|
|
313
372
|
await _8_10_1.test.step('Create a process report for conditional-events-auto-process (200)', async () => {
|
|
314
373
|
const response = await request.post(`${baseUrl}/api/report/process/single`, {
|
|
@@ -385,7 +444,6 @@ _8_10_1.test.describe('API optimize SaaS Tests - Conditional Events', () => {
|
|
|
385
444
|
});
|
|
386
445
|
});
|
|
387
446
|
(0, _8_10_1.test)('CE-OPT-13: Deleting the Conditional Events report via API succeeds with HTTP 200', async ({ request, }) => {
|
|
388
|
-
// Create a separate report to delete so the shared one remains available for other tests
|
|
389
447
|
const reportToDeleteId = await (0, apiHelpers_1.createSingleProcessReport)(request, {
|
|
390
448
|
optimizeCookie,
|
|
391
449
|
collectionId: conditionalEventsCollectionId,
|
|
@@ -436,3 +494,590 @@ _8_10_1.test.describe('API optimize SaaS Tests - Conditional Events', () => {
|
|
|
436
494
|
});
|
|
437
495
|
});
|
|
438
496
|
});
|
|
497
|
+
_8_10_1.test.describe('API optimize SaaS Tests - Health Readiness', () => {
|
|
498
|
+
let baseUrl;
|
|
499
|
+
_8_10_1.test.beforeAll(async () => {
|
|
500
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
501
|
+
});
|
|
502
|
+
(0, _8_10_1.test)('Health readiness returns 200 when Optimize is ready', async ({ request, }) => {
|
|
503
|
+
await _8_10_1.test.step('GET /api/readyz returns 200 (no auth required)', async () => {
|
|
504
|
+
const response = await request.get(`${baseUrl}/api/readyz`);
|
|
505
|
+
(0, test_1.expect)(response.status()).toBe(200);
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
(0, _8_10_1.test)('Health readiness rejects requests that include an Authorization header', async ({ request, }) => {
|
|
509
|
+
await _8_10_1.test.step('GET /api/readyz with Authorization header should be rejected', async () => {
|
|
510
|
+
const token = await (0, apiHelpers_1.authSaasAPI)(process.env.OPTIMIZE_API_TOKEN_AUDIENCE);
|
|
511
|
+
const response = await request.get(`${baseUrl}/api/readyz`, {
|
|
512
|
+
headers: { Authorization: token },
|
|
513
|
+
});
|
|
514
|
+
(0, test_1.expect)([400, 401, 403]).toContain(response.status());
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
_8_10_1.test.describe('API optimize SaaS Tests - Sharing', () => {
|
|
519
|
+
let optimizeBearerToken;
|
|
520
|
+
let baseUrl;
|
|
521
|
+
_8_10_1.test.beforeAll(async () => {
|
|
522
|
+
optimizeBearerToken = await (0, apiHelpers_1.authSaasAPI)(process.env.OPTIMIZE_API_TOKEN_AUDIENCE);
|
|
523
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
524
|
+
});
|
|
525
|
+
(0, _8_10_1.test)('Enable sharing with valid token returns 200 or 204', async ({ request, }) => {
|
|
526
|
+
await _8_10_1.test.step('POST /api/public/share/enable with valid token (200 or 204)', async () => {
|
|
527
|
+
const response = await request.post(`${baseUrl}/api/public/share/enable`, { headers: { Authorization: optimizeBearerToken } });
|
|
528
|
+
(0, test_1.expect)([200, 204]).toContain(response.status());
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
(0, _8_10_1.test)('Enable sharing without token returns 401', async ({ request }) => {
|
|
532
|
+
await _8_10_1.test.step('POST /api/public/share/enable without token (401)', async () => {
|
|
533
|
+
const response = await request.post(`${baseUrl}/api/public/share/enable`);
|
|
534
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
(0, _8_10_1.test)('Enable sharing with invalid token returns 401', async ({ request }) => {
|
|
538
|
+
await _8_10_1.test.step('POST /api/public/share/enable with invalid token (401)', async () => {
|
|
539
|
+
const response = await request.post(`${baseUrl}/api/public/share/enable`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
540
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
(0, _8_10_1.test)('Disable sharing with valid token returns 200 or 204', async ({ request, }) => {
|
|
544
|
+
await _8_10_1.test.step('POST /api/public/share/disable with valid token (200 or 204)', async () => {
|
|
545
|
+
const response = await request.post(`${baseUrl}/api/public/share/disable`, { headers: { Authorization: optimizeBearerToken } });
|
|
546
|
+
(0, test_1.expect)([200, 204]).toContain(response.status());
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
(0, _8_10_1.test)('Disable sharing without token returns 401', async ({ request }) => {
|
|
550
|
+
await _8_10_1.test.step('POST /api/public/share/disable without token (401)', async () => {
|
|
551
|
+
const response = await request.post(`${baseUrl}/api/public/share/disable`);
|
|
552
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
(0, _8_10_1.test)('Disable sharing with invalid token returns 401', async ({ request }) => {
|
|
556
|
+
await _8_10_1.test.step('POST /api/public/share/disable with invalid token (401)', async () => {
|
|
557
|
+
const response = await request.post(`${baseUrl}/api/public/share/disable`, { headers: { Authorization: 'Bearer invalid_token' } });
|
|
558
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
(0, _8_10_1.test)('Sharing toggle cycle: enable then disable is idempotent', async ({ request, }) => {
|
|
562
|
+
await _8_10_1.test.step('Enable sharing (200 or 204)', async () => {
|
|
563
|
+
const response = await request.post(`${baseUrl}/api/public/share/enable`, { headers: { Authorization: optimizeBearerToken } });
|
|
564
|
+
(0, test_1.expect)([200, 204]).toContain(response.status());
|
|
565
|
+
});
|
|
566
|
+
await _8_10_1.test.step('Disable sharing (200 or 204)', async () => {
|
|
567
|
+
const response = await request.post(`${baseUrl}/api/public/share/disable`, { headers: { Authorization: optimizeBearerToken } });
|
|
568
|
+
(0, test_1.expect)([200, 204]).toContain(response.status());
|
|
569
|
+
});
|
|
570
|
+
await _8_10_1.test.step('Re-enable sharing returns 200 or 204 (idempotent)', async () => {
|
|
571
|
+
const response = await request.post(`${baseUrl}/api/public/share/enable`, { headers: { Authorization: optimizeBearerToken } });
|
|
572
|
+
(0, test_1.expect)([200, 204]).toContain(response.status());
|
|
573
|
+
});
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
_8_10_1.test.describe('API optimize SaaS Tests - Dashboard and Report GET edge cases', () => {
|
|
577
|
+
let optimizeBearerToken;
|
|
578
|
+
let optimizeCookie;
|
|
579
|
+
let collectionId;
|
|
580
|
+
let baseUrl;
|
|
581
|
+
_8_10_1.test.beforeAll(async ({ browser, request }) => {
|
|
582
|
+
const page = await browser.newPage();
|
|
583
|
+
optimizeCookie = await (0, apiHelpers_1.getOptimizeCoockie)(page);
|
|
584
|
+
await page.close();
|
|
585
|
+
optimizeBearerToken = await (0, apiHelpers_1.authSaasAPI)(process.env.OPTIMIZE_API_TOKEN_AUDIENCE);
|
|
586
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
587
|
+
collectionId = await (0, apiHelpers_1.createCollection)(request, {
|
|
588
|
+
name: await (0, randomName_1.randomNameAgregator)('GET Edge Cases Collection'),
|
|
589
|
+
optimizeCookie,
|
|
590
|
+
});
|
|
591
|
+
});
|
|
592
|
+
_8_10_1.test.afterAll(async ({ request }) => {
|
|
593
|
+
if (collectionId) {
|
|
594
|
+
await request.delete(`${baseUrl}/api/public/collection/${collectionId}`, {
|
|
595
|
+
headers: { Authorization: optimizeBearerToken },
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
(0, _8_10_1.test)('GET dashboards with valid token and collectionId returns 200 with id array', async ({ request, }) => {
|
|
600
|
+
await _8_10_1.test.step('GET /api/public/dashboard?collectionId returns 200', async () => {
|
|
601
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=${collectionId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
602
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
603
|
+
const body = await response.json();
|
|
604
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
(0, _8_10_1.test)('GET dashboards without collectionId param returns 400 or 500', async ({ request, }) => {
|
|
608
|
+
await _8_10_1.test.step('GET /api/public/dashboard without collectionId', async () => {
|
|
609
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard`, {
|
|
610
|
+
headers: { Authorization: optimizeBearerToken },
|
|
611
|
+
});
|
|
612
|
+
(0, test_1.expect)([400, 500]).toContain(response.status());
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
(0, _8_10_1.test)('GET reports with valid token and collectionId returns 200 with id array', async ({ request, }) => {
|
|
616
|
+
await _8_10_1.test.step('GET /api/public/report?collectionId returns 200', async () => {
|
|
617
|
+
const response = await request.get(`${baseUrl}/api/public/report?collectionId=${collectionId}`, { headers: { Authorization: optimizeBearerToken } });
|
|
618
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
619
|
+
const body = await response.json();
|
|
620
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
(0, _8_10_1.test)('GET reports without collectionId param returns 400 or 500', async ({ request, }) => {
|
|
624
|
+
await _8_10_1.test.step('GET /api/public/report without collectionId', async () => {
|
|
625
|
+
const response = await request.get(`${baseUrl}/api/public/report`, {
|
|
626
|
+
headers: { Authorization: optimizeBearerToken },
|
|
627
|
+
});
|
|
628
|
+
(0, test_1.expect)([400, 500]).toContain(response.status());
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
_8_10_1.test.describe('API optimize SaaS Tests - Export edge cases', () => {
|
|
633
|
+
let optimizeBearerToken;
|
|
634
|
+
let optimizeCookie;
|
|
635
|
+
let collectionId;
|
|
636
|
+
let dashboardId1;
|
|
637
|
+
let dashboardId2;
|
|
638
|
+
let reportId1;
|
|
639
|
+
let reportId2;
|
|
640
|
+
let baseUrl;
|
|
641
|
+
_8_10_1.test.beforeAll(async ({ browser, request }) => {
|
|
642
|
+
const page = await browser.newPage();
|
|
643
|
+
optimizeCookie = await (0, apiHelpers_1.getOptimizeCoockie)(page);
|
|
644
|
+
await page.close();
|
|
645
|
+
optimizeBearerToken = await (0, apiHelpers_1.authSaasAPI)(process.env.OPTIMIZE_API_TOKEN_AUDIENCE);
|
|
646
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
647
|
+
collectionId = await (0, apiHelpers_1.createCollection)(request, {
|
|
648
|
+
name: await (0, randomName_1.randomNameAgregator)('Export Edge Cases Collection'),
|
|
649
|
+
optimizeCookie,
|
|
650
|
+
});
|
|
651
|
+
dashboardId1 = await (0, apiHelpers_1.createDashboard)(request, {
|
|
652
|
+
name: await (0, randomName_1.randomNameAgregator)('Export Dashboard 1'),
|
|
653
|
+
optimizeCookie,
|
|
654
|
+
collectionId,
|
|
655
|
+
});
|
|
656
|
+
dashboardId2 = await (0, apiHelpers_1.createDashboard)(request, {
|
|
657
|
+
name: await (0, randomName_1.randomNameAgregator)('Export Dashboard 2'),
|
|
658
|
+
optimizeCookie,
|
|
659
|
+
collectionId,
|
|
660
|
+
});
|
|
661
|
+
reportId1 = await (0, apiHelpers_1.createSingleProcessReport)(request, {
|
|
662
|
+
optimizeCookie,
|
|
663
|
+
collectionId,
|
|
664
|
+
name: await (0, randomName_1.randomNameAgregator)('Export Report 1'),
|
|
665
|
+
definitions: [
|
|
666
|
+
{
|
|
667
|
+
key: 'aProcess',
|
|
668
|
+
filter: [],
|
|
669
|
+
groupBy: { type: 'none', value: null },
|
|
670
|
+
distributedBy: { type: 'none', value: null },
|
|
671
|
+
view: { entity: 'processInstance', properties: ['frequency'] },
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
});
|
|
675
|
+
reportId2 = await (0, apiHelpers_1.createSingleProcessReport)(request, {
|
|
676
|
+
optimizeCookie,
|
|
677
|
+
collectionId,
|
|
678
|
+
name: await (0, randomName_1.randomNameAgregator)('Export Report 2'),
|
|
679
|
+
definitions: [
|
|
680
|
+
{
|
|
681
|
+
key: 'aProcess',
|
|
682
|
+
filter: [],
|
|
683
|
+
groupBy: { type: 'none', value: null },
|
|
684
|
+
distributedBy: { type: 'none', value: null },
|
|
685
|
+
view: { entity: 'processInstance', properties: ['frequency'] },
|
|
686
|
+
},
|
|
687
|
+
],
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
_8_10_1.test.afterAll(async ({ request }) => {
|
|
691
|
+
if (collectionId) {
|
|
692
|
+
await request.delete(`${baseUrl}/api/public/collection/${collectionId}`, {
|
|
693
|
+
headers: { Authorization: optimizeBearerToken },
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
(0, _8_10_1.test)('Export multiple dashboards in a single call returns 200 with all definitions', async ({ request, }) => {
|
|
698
|
+
await _8_10_1.test.step('POST export with two dashboard IDs returns array of 2', async () => {
|
|
699
|
+
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
700
|
+
headers: {
|
|
701
|
+
Authorization: optimizeBearerToken,
|
|
702
|
+
'Content-Type': 'application/json',
|
|
703
|
+
},
|
|
704
|
+
data: [dashboardId1, dashboardId2],
|
|
705
|
+
});
|
|
706
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
707
|
+
const body = await response.json();
|
|
708
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
709
|
+
(0, test_1.expect)(body.length).toBeGreaterThanOrEqual(2);
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
(0, _8_10_1.test)('Export multiple reports in a single call returns 200 with all definitions', async ({ request, }) => {
|
|
713
|
+
await _8_10_1.test.step('POST export with two report IDs returns array of 2', async () => {
|
|
714
|
+
const response = await request.post(`${baseUrl}/api/public/export/report/definition/json`, {
|
|
715
|
+
headers: {
|
|
716
|
+
Authorization: optimizeBearerToken,
|
|
717
|
+
'Content-Type': 'application/json',
|
|
718
|
+
},
|
|
719
|
+
data: [reportId1, reportId2],
|
|
720
|
+
});
|
|
721
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
722
|
+
const body = await response.json();
|
|
723
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
724
|
+
(0, test_1.expect)(body.length).toBeGreaterThanOrEqual(2);
|
|
725
|
+
});
|
|
726
|
+
});
|
|
727
|
+
(0, _8_10_1.test)('Export reports with empty array body returns 200 with empty array', async ({ request, }) => {
|
|
728
|
+
await _8_10_1.test.step('POST export/report with empty array body returns 200 []', async () => {
|
|
729
|
+
const response = await request.post(`${baseUrl}/api/public/export/report/definition/json`, {
|
|
730
|
+
headers: {
|
|
731
|
+
Authorization: optimizeBearerToken,
|
|
732
|
+
'Content-Type': 'application/json',
|
|
733
|
+
},
|
|
734
|
+
data: [],
|
|
735
|
+
});
|
|
736
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
737
|
+
const body = await response.json();
|
|
738
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
739
|
+
(0, test_1.expect)(body.length).toBe(0);
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
(0, _8_10_1.test)('Export dashboards with empty array body returns 200 with empty array', async ({ request, }) => {
|
|
743
|
+
await _8_10_1.test.step('POST export/dashboard with empty array body returns 200 []', async () => {
|
|
744
|
+
const response = await request.post(`${baseUrl}/api/public/export/dashboard/definition/json`, {
|
|
745
|
+
headers: {
|
|
746
|
+
Authorization: optimizeBearerToken,
|
|
747
|
+
'Content-Type': 'application/json',
|
|
748
|
+
},
|
|
749
|
+
data: [],
|
|
750
|
+
});
|
|
751
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
752
|
+
const body = await response.json();
|
|
753
|
+
(0, test_1.expect)(Array.isArray(body)).toBeTruthy();
|
|
754
|
+
(0, test_1.expect)(body.length).toBe(0);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
_8_10_1.test.describe('API optimize SaaS Tests - Auth edge cases', () => {
|
|
759
|
+
let baseUrl;
|
|
760
|
+
_8_10_1.test.beforeAll(async () => {
|
|
761
|
+
baseUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
762
|
+
});
|
|
763
|
+
(0, _8_10_1.test)('Expired JWT token returns 401 on dashboard endpoint', async ({ request, }) => {
|
|
764
|
+
const expiredToken = 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.' +
|
|
765
|
+
'eyJzdWIiOiJ0ZXN0IiwiZXhwIjoxfQ.' +
|
|
766
|
+
'invalidsignature';
|
|
767
|
+
await _8_10_1.test.step('GET /api/public/dashboard with expired token returns 401', async () => {
|
|
768
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=any`, { headers: { Authorization: expiredToken } });
|
|
769
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
770
|
+
});
|
|
771
|
+
});
|
|
772
|
+
(0, _8_10_1.test)('Malformed Bearer value (empty string) returns 401 on dashboard endpoint', async ({ request, }) => {
|
|
773
|
+
await _8_10_1.test.step('GET /api/public/dashboard with empty Bearer value returns 401', async () => {
|
|
774
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=any`, { headers: { Authorization: 'Bearer ' } });
|
|
775
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
(0, _8_10_1.test)('Token with wrong audience returns 401 on dashboard endpoint', async ({ request, }) => {
|
|
779
|
+
await _8_10_1.test.step('Use a Zeebe-audience token against Optimize API and expect 401', async () => {
|
|
780
|
+
const wrongAudienceToken = await (0, apiHelpers_1.authSaasAPI)();
|
|
781
|
+
const response = await request.get(`${baseUrl}/api/public/dashboard?collectionId=any`, { headers: { Authorization: wrongAudienceToken } });
|
|
782
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
783
|
+
});
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
_8_10_1.test.describe('API V2 tests on SaaS cluster', () => {
|
|
787
|
+
let bearerToken;
|
|
788
|
+
const apiUrl = () => process.env.ZEEBE_API_URL;
|
|
789
|
+
_8_10_1.test.beforeAll(async () => {
|
|
790
|
+
bearerToken = await (0, apiHelpers_1.authSaasAPI)();
|
|
791
|
+
});
|
|
792
|
+
(0, _8_10_1.test)('GET /v2/topology returns 200', async ({ request }) => {
|
|
793
|
+
const response = await request.get(`${apiUrl()}/v2/topology`, {
|
|
794
|
+
headers: { Authorization: bearerToken, 'Content-Type': 'application/json' },
|
|
795
|
+
});
|
|
796
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
797
|
+
});
|
|
798
|
+
(0, _8_10_1.test)('GET /v2/topology without token returns 401', async ({ request }) => {
|
|
799
|
+
const response = await request.get(`${apiUrl()}/v2/topology`, {
|
|
800
|
+
headers: { 'Content-Type': 'application/json' },
|
|
801
|
+
});
|
|
802
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
803
|
+
});
|
|
804
|
+
(0, _8_10_1.test)('POST /v2/process-definitions/search returns 200 with items array', async ({ request, }) => {
|
|
805
|
+
const response = await request.post(`${apiUrl()}/v2/process-definitions/search`, {
|
|
806
|
+
headers: {
|
|
807
|
+
Authorization: bearerToken,
|
|
808
|
+
'Content-Type': 'application/json',
|
|
809
|
+
},
|
|
810
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
811
|
+
});
|
|
812
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
813
|
+
if (response.status() === 200) {
|
|
814
|
+
const body = await response.json();
|
|
815
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
816
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
(0, _8_10_1.test)('POST /v2/process-definitions/search without token returns 401', async ({ request, }) => {
|
|
820
|
+
const response = await request.post(`${apiUrl()}/v2/process-definitions/search`, {
|
|
821
|
+
headers: { 'Content-Type': 'application/json' },
|
|
822
|
+
data: { filter: {}, size: 10 },
|
|
823
|
+
});
|
|
824
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
825
|
+
});
|
|
826
|
+
(0, _8_10_1.test)('POST /v2/process-definitions/search with invalid token returns 401', async ({ request, }) => {
|
|
827
|
+
const response = await request.post(`${apiUrl()}/v2/process-definitions/search`, {
|
|
828
|
+
headers: {
|
|
829
|
+
Authorization: 'Bearer invalid_token',
|
|
830
|
+
'Content-Type': 'application/json',
|
|
831
|
+
},
|
|
832
|
+
data: { filter: {}, size: 10 },
|
|
833
|
+
});
|
|
834
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
835
|
+
});
|
|
836
|
+
(0, _8_10_1.test)('POST /v2/process-definitions/search with size 1 returns pagination cursor', async ({ request, }) => {
|
|
837
|
+
const response = await request.post(`${apiUrl()}/v2/process-definitions/search`, {
|
|
838
|
+
headers: {
|
|
839
|
+
Authorization: bearerToken,
|
|
840
|
+
'Content-Type': 'application/json',
|
|
841
|
+
},
|
|
842
|
+
data: { filter: {}, page: { limit: 1 } },
|
|
843
|
+
});
|
|
844
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
845
|
+
if (response.status() === 200) {
|
|
846
|
+
const body = await response.json();
|
|
847
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
848
|
+
(0, test_1.expect)(body.items.length).toBeLessThanOrEqual(1);
|
|
849
|
+
if (body.page?.totalItems > 1) {
|
|
850
|
+
(0, test_1.expect)(body).toHaveProperty('page');
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
(0, _8_10_1.test)('POST /v2/process-instances/search returns 200 with items array', async ({ request, }) => {
|
|
855
|
+
const response = await request.post(`${apiUrl()}/v2/process-instances/search`, {
|
|
856
|
+
headers: {
|
|
857
|
+
Authorization: bearerToken,
|
|
858
|
+
'Content-Type': 'application/json',
|
|
859
|
+
},
|
|
860
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
861
|
+
});
|
|
862
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
863
|
+
if (response.status() === 200) {
|
|
864
|
+
const body = await response.json();
|
|
865
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
866
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
(0, _8_10_1.test)('POST /v2/process-instances/search filtered by state ACTIVE returns 200', async ({ request, }) => {
|
|
870
|
+
const response = await request.post(`${apiUrl()}/v2/process-instances/search`, {
|
|
871
|
+
headers: {
|
|
872
|
+
Authorization: bearerToken,
|
|
873
|
+
'Content-Type': 'application/json',
|
|
874
|
+
},
|
|
875
|
+
data: { filter: { state: 'ACTIVE' }, page: { limit: 10 } },
|
|
876
|
+
});
|
|
877
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
878
|
+
if (response.status() === 200) {
|
|
879
|
+
const body = await response.json();
|
|
880
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
(0, _8_10_1.test)('POST /v2/process-instances/search without token returns 401', async ({ request, }) => {
|
|
884
|
+
const response = await request.post(`${apiUrl()}/v2/process-instances/search`, {
|
|
885
|
+
headers: { 'Content-Type': 'application/json' },
|
|
886
|
+
data: { filter: {}, size: 10 },
|
|
887
|
+
});
|
|
888
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
889
|
+
});
|
|
890
|
+
(0, _8_10_1.test)('POST /v2/process-instances/search with invalid token returns 401', async ({ request, }) => {
|
|
891
|
+
const response = await request.post(`${apiUrl()}/v2/process-instances/search`, {
|
|
892
|
+
headers: {
|
|
893
|
+
Authorization: 'Bearer invalid_token',
|
|
894
|
+
'Content-Type': 'application/json',
|
|
895
|
+
},
|
|
896
|
+
data: { filter: {}, size: 10 },
|
|
897
|
+
});
|
|
898
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
899
|
+
});
|
|
900
|
+
(0, _8_10_1.test)('POST /v2/user-tasks/search returns 200 with items array', async ({ request, }) => {
|
|
901
|
+
const response = await request.post(`${apiUrl()}/v2/user-tasks/search`, {
|
|
902
|
+
headers: { Authorization: bearerToken, 'Content-Type': 'application/json' },
|
|
903
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
904
|
+
});
|
|
905
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
906
|
+
if (response.status() === 200) {
|
|
907
|
+
const body = await response.json();
|
|
908
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
909
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
(0, _8_10_1.test)('POST /v2/user-tasks/search without token returns 401', async ({ request, }) => {
|
|
913
|
+
const response = await request.post(`${apiUrl()}/v2/user-tasks/search`, {
|
|
914
|
+
headers: { 'Content-Type': 'application/json' },
|
|
915
|
+
data: { filter: {}, size: 10 },
|
|
916
|
+
});
|
|
917
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
918
|
+
});
|
|
919
|
+
(0, _8_10_1.test)('POST /v2/user-tasks/search with invalid token returns 401', async ({ request, }) => {
|
|
920
|
+
const response = await request.post(`${apiUrl()}/v2/user-tasks/search`, {
|
|
921
|
+
headers: {
|
|
922
|
+
Authorization: 'Bearer invalid_token',
|
|
923
|
+
'Content-Type': 'application/json',
|
|
924
|
+
},
|
|
925
|
+
data: { filter: {}, size: 10 },
|
|
926
|
+
});
|
|
927
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
928
|
+
});
|
|
929
|
+
(0, _8_10_1.test)('POST /v2/variables/search returns 200 with items array', async ({ request, }) => {
|
|
930
|
+
const response = await request.post(`${apiUrl()}/v2/variables/search`, {
|
|
931
|
+
headers: { Authorization: bearerToken, 'Content-Type': 'application/json' },
|
|
932
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
933
|
+
});
|
|
934
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
935
|
+
if (response.status() === 200) {
|
|
936
|
+
const body = await response.json();
|
|
937
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
938
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
(0, _8_10_1.test)('POST /v2/variables/search without token returns 401', async ({ request, }) => {
|
|
942
|
+
const response = await request.post(`${apiUrl()}/v2/variables/search`, {
|
|
943
|
+
headers: { 'Content-Type': 'application/json' },
|
|
944
|
+
data: { filter: {}, size: 10 },
|
|
945
|
+
});
|
|
946
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
947
|
+
});
|
|
948
|
+
(0, _8_10_1.test)('POST /v2/variables/search with invalid token returns 401', async ({ request, }) => {
|
|
949
|
+
const response = await request.post(`${apiUrl()}/v2/variables/search`, {
|
|
950
|
+
headers: {
|
|
951
|
+
Authorization: 'Bearer invalid_token',
|
|
952
|
+
'Content-Type': 'application/json',
|
|
953
|
+
},
|
|
954
|
+
data: { filter: {}, size: 10 },
|
|
955
|
+
});
|
|
956
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
957
|
+
});
|
|
958
|
+
(0, _8_10_1.test)('POST /v2/incidents/search returns 200 with items array', async ({ request, }) => {
|
|
959
|
+
const response = await request.post(`${apiUrl()}/v2/incidents/search`, {
|
|
960
|
+
headers: { Authorization: bearerToken, 'Content-Type': 'application/json' },
|
|
961
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
962
|
+
});
|
|
963
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
964
|
+
if (response.status() === 200) {
|
|
965
|
+
const body = await response.json();
|
|
966
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
967
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
(0, _8_10_1.test)('POST /v2/incidents/search without token returns 401', async ({ request, }) => {
|
|
971
|
+
const response = await request.post(`${apiUrl()}/v2/incidents/search`, {
|
|
972
|
+
headers: { 'Content-Type': 'application/json' },
|
|
973
|
+
data: { filter: {}, size: 10 },
|
|
974
|
+
});
|
|
975
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
976
|
+
});
|
|
977
|
+
(0, _8_10_1.test)('POST /v2/incidents/search with invalid token returns 401', async ({ request, }) => {
|
|
978
|
+
const response = await request.post(`${apiUrl()}/v2/incidents/search`, {
|
|
979
|
+
headers: {
|
|
980
|
+
Authorization: 'Bearer invalid_token',
|
|
981
|
+
'Content-Type': 'application/json',
|
|
982
|
+
},
|
|
983
|
+
data: { filter: {}, size: 10 },
|
|
984
|
+
});
|
|
985
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
986
|
+
});
|
|
987
|
+
(0, _8_10_1.test)('POST /v2/decision-definitions/search returns 200 with items array', async ({ request, }) => {
|
|
988
|
+
const response = await request.post(`${apiUrl()}/v2/decision-definitions/search`, {
|
|
989
|
+
headers: {
|
|
990
|
+
Authorization: bearerToken,
|
|
991
|
+
'Content-Type': 'application/json',
|
|
992
|
+
},
|
|
993
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
994
|
+
});
|
|
995
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
996
|
+
if (response.status() === 200) {
|
|
997
|
+
const body = await response.json();
|
|
998
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
999
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
1000
|
+
}
|
|
1001
|
+
});
|
|
1002
|
+
(0, _8_10_1.test)('POST /v2/decision-definitions/search without token returns 401', async ({ request, }) => {
|
|
1003
|
+
const response = await request.post(`${apiUrl()}/v2/decision-definitions/search`, {
|
|
1004
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1005
|
+
data: { filter: {}, size: 10 },
|
|
1006
|
+
});
|
|
1007
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1008
|
+
});
|
|
1009
|
+
(0, _8_10_1.test)('POST /v2/decision-definitions/search with invalid token returns 401', async ({ request, }) => {
|
|
1010
|
+
const response = await request.post(`${apiUrl()}/v2/decision-definitions/search`, {
|
|
1011
|
+
headers: {
|
|
1012
|
+
Authorization: 'Bearer invalid_token',
|
|
1013
|
+
'Content-Type': 'application/json',
|
|
1014
|
+
},
|
|
1015
|
+
data: { filter: {}, size: 10 },
|
|
1016
|
+
});
|
|
1017
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1018
|
+
});
|
|
1019
|
+
(0, _8_10_1.test)('POST /v2/decision-instances/search returns 200 with items array', async ({ request, }) => {
|
|
1020
|
+
const response = await request.post(`${apiUrl()}/v2/decision-instances/search`, {
|
|
1021
|
+
headers: {
|
|
1022
|
+
Authorization: bearerToken,
|
|
1023
|
+
'Content-Type': 'application/json',
|
|
1024
|
+
},
|
|
1025
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
1026
|
+
});
|
|
1027
|
+
(0, test_1.expect)([200, 400, 405]).toContain(response.status());
|
|
1028
|
+
if (response.status() === 200) {
|
|
1029
|
+
const body = await response.json();
|
|
1030
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
1031
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
(0, _8_10_1.test)('POST /v2/decision-instances/search without token returns 401', async ({ request, }) => {
|
|
1035
|
+
const response = await request.post(`${apiUrl()}/v2/decision-instances/search`, {
|
|
1036
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1037
|
+
data: { filter: {}, size: 10 },
|
|
1038
|
+
});
|
|
1039
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1040
|
+
});
|
|
1041
|
+
(0, _8_10_1.test)('POST /v2/decision-instances/search with invalid token returns 401', async ({ request, }) => {
|
|
1042
|
+
const response = await request.post(`${apiUrl()}/v2/decision-instances/search`, {
|
|
1043
|
+
headers: {
|
|
1044
|
+
Authorization: 'Bearer invalid_token',
|
|
1045
|
+
'Content-Type': 'application/json',
|
|
1046
|
+
},
|
|
1047
|
+
data: { filter: {}, size: 10 },
|
|
1048
|
+
});
|
|
1049
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1050
|
+
});
|
|
1051
|
+
(0, _8_10_1.test)('POST /v2/flownode-instances/search returns 200 with items array', async ({ request, }) => {
|
|
1052
|
+
const response = await request.post(`${apiUrl()}/v2/flownode-instances/search`, {
|
|
1053
|
+
headers: {
|
|
1054
|
+
Authorization: bearerToken,
|
|
1055
|
+
'Content-Type': 'application/json',
|
|
1056
|
+
},
|
|
1057
|
+
data: { filter: {}, page: { limit: 10 } },
|
|
1058
|
+
});
|
|
1059
|
+
(0, test_1.expect)([200, 404, 405]).toContain(response.status());
|
|
1060
|
+
if (response.status() === 200) {
|
|
1061
|
+
const body = await response.json();
|
|
1062
|
+
(0, test_1.expect)(body).toHaveProperty('items');
|
|
1063
|
+
(0, test_1.expect)(Array.isArray(body.items)).toBeTruthy();
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
(0, _8_10_1.test)('POST /v2/flownode-instances/search without token returns 401', async ({ request, }) => {
|
|
1067
|
+
const response = await request.post(`${apiUrl()}/v2/flownode-instances/search`, {
|
|
1068
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1069
|
+
data: { filter: {}, size: 10 },
|
|
1070
|
+
});
|
|
1071
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1072
|
+
});
|
|
1073
|
+
(0, _8_10_1.test)('POST /v2/flownode-instances/search with invalid token returns 401', async ({ request, }) => {
|
|
1074
|
+
const response = await request.post(`${apiUrl()}/v2/flownode-instances/search`, {
|
|
1075
|
+
headers: {
|
|
1076
|
+
Authorization: 'Bearer invalid_token',
|
|
1077
|
+
'Content-Type': 'application/json',
|
|
1078
|
+
},
|
|
1079
|
+
data: { filter: {}, size: 10 },
|
|
1080
|
+
});
|
|
1081
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
1082
|
+
});
|
|
1083
|
+
});
|
package/dist/utils/apiHelpers.js
CHANGED
|
@@ -8,6 +8,7 @@ const test_1 = require("@playwright/test");
|
|
|
8
8
|
const sleep_1 = require("./sleep");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const os_1 = __importDefault(require("os"));
|
|
11
12
|
const utils_1 = require("./utils");
|
|
12
13
|
let apiRequestContext;
|
|
13
14
|
// ---- Internal: API request context ----
|
|
@@ -411,8 +412,10 @@ exports.createStringClusterVariable = createStringClusterVariable;
|
|
|
411
412
|
async function getOptimizeCoockie(page) {
|
|
412
413
|
await (0, utils_1.loginToApp)(process.env.CAMUNDA_OPTIMIZE_BASE_URL, page);
|
|
413
414
|
const context = page.context();
|
|
414
|
-
|
|
415
|
-
|
|
415
|
+
const tempFile = path_1.default.join(os_1.default.tmpdir(), `.auth_optimize_${Date.now()}_${Math.random().toString(36).slice(2)}`);
|
|
416
|
+
await context.storageState({ path: tempFile });
|
|
417
|
+
const authData = JSON.parse(fs_1.default.readFileSync(tempFile, 'utf8'));
|
|
418
|
+
fs_1.default.unlinkSync(tempFile);
|
|
416
419
|
const serviceTokenCookie = authData.cookies.find((cookie) => cookie.name === 'X-Optimize-Service-Token_0');
|
|
417
420
|
const authTokenCookie = authData.cookies.find((cookie) => cookie.name === 'X-Optimize-Authorization_0');
|
|
418
421
|
const optimizeServiceToken = serviceTokenCookie?.value || '';
|
package/dist/utils/utils.js
CHANGED
|
@@ -4,14 +4,24 @@ exports.loginToApp = void 0;
|
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
5
|
const LoginPage_1 = require("../pages/8.8/LoginPage");
|
|
6
6
|
async function loginToApp(appName, page) {
|
|
7
|
-
await page.goto(appName);
|
|
7
|
+
await page.goto(appName, { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
8
|
+
await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => { });
|
|
8
9
|
const loginPage = new LoginPage_1.LoginPage(page);
|
|
10
|
+
await (0, test_1.expect)(loginPage.usernameInput).toBeVisible({ timeout: 60000 });
|
|
9
11
|
await loginPage.fillUsername(process.env.C8_USERNAME);
|
|
10
12
|
await (0, test_1.expect)(loginPage.usernameInput).toHaveValue(process.env.C8_USERNAME);
|
|
11
13
|
await (0, test_1.expect)(loginPage.loginMessage).toBeVisible();
|
|
12
14
|
await loginPage.clickContinueButton();
|
|
15
|
+
await (0, test_1.expect)(loginPage.passwordInput).toBeVisible({ timeout: 60000 });
|
|
13
16
|
await loginPage.fillPassword(process.env.C8_PASSWORD);
|
|
14
17
|
await (0, test_1.expect)(loginPage.passwordHeading).toBeVisible();
|
|
15
18
|
await loginPage.clickLoginButton();
|
|
19
|
+
await page.waitForURL((url) => url.toString().startsWith(appName), {
|
|
20
|
+
timeout: 60000,
|
|
21
|
+
waitUntil: 'commit',
|
|
22
|
+
});
|
|
23
|
+
await page
|
|
24
|
+
.waitForLoadState('domcontentloaded', { timeout: 30000 })
|
|
25
|
+
.catch(() => { });
|
|
16
26
|
}
|
|
17
27
|
exports.loginToApp = loginToApp;
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const _8_10_1 = require("../../fixtures/8.10");
|
|
4
|
-
const apiHelpers_1 = require("../../utils/apiHelpers");
|
|
5
|
-
_8_10_1.test.describe.configure({ mode: 'parallel' });
|
|
6
|
-
_8_10_1.test.describe('API V2 tests on SaaS cluster ', () => {
|
|
7
|
-
let bearerToken;
|
|
8
|
-
_8_10_1.test.beforeAll(async () => {
|
|
9
|
-
bearerToken = await (0, apiHelpers_1.authSaasAPI)();
|
|
10
|
-
});
|
|
11
|
-
(0, _8_10_1.test)('Get cluster topology', async ({ request }) => {
|
|
12
|
-
const topologyResponse = await request.get(`${process.env.ZEEBE_API_URL}/v2/topology`, {
|
|
13
|
-
headers: {
|
|
14
|
-
Authorization: bearerToken,
|
|
15
|
-
'Content-Type': 'application/json',
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
await (0, apiHelpers_1.assertResponseStatus)(topologyResponse, 200);
|
|
19
|
-
});
|
|
20
|
-
});
|