@camunda/e2e-test-suite 0.0.674 → 0.0.675
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pages/c8Run-8.7/IdentityHomePage.d.ts +2 -4
- package/dist/pages/c8Run-8.7/IdentityHomePage.js +51 -82
- package/dist/pages/c8Run-8.7/OperateProcessInstancePage.js +3 -3
- package/dist/tests/c8Run-8.7/operate-api-tests-docker.spec.js +55 -44
- package/dist/tests/c8Run-8.7/tasklist-api-tests-docker.spec.js +2 -2
- package/package.json +1 -1
|
@@ -6,16 +6,14 @@ declare class IdentityHomePage {
|
|
|
6
6
|
readonly operateCell: Locator;
|
|
7
7
|
readonly connectorsCell: Locator;
|
|
8
8
|
readonly accessToAPIsTab: Locator;
|
|
9
|
-
readonly writePermissionCell: Locator;
|
|
10
|
-
readonly readPermissionCell: Locator;
|
|
11
9
|
readonly assignPermissionsButton: Locator;
|
|
12
10
|
readonly dialog: Locator;
|
|
13
|
-
readonly writePermissionCheckBox: Locator;
|
|
14
|
-
readonly readPermissionCheckBox: Locator;
|
|
15
11
|
readonly addButton: Locator;
|
|
16
12
|
readonly permissionCell: (name: string) => Locator;
|
|
17
13
|
readonly select: Locator;
|
|
18
14
|
constructor(page: Page);
|
|
15
|
+
private selectAllCheckboxes;
|
|
16
|
+
private assignPermissions;
|
|
19
17
|
assignPermissionToTasklistAPI(): Promise<void>;
|
|
20
18
|
assignPermissionToOperateAPI(): Promise<void>;
|
|
21
19
|
selectOptionFromDropdown(option: string): Promise<void>;
|
|
@@ -11,12 +11,8 @@ class IdentityHomePage {
|
|
|
11
11
|
operateCell;
|
|
12
12
|
connectorsCell;
|
|
13
13
|
accessToAPIsTab;
|
|
14
|
-
writePermissionCell;
|
|
15
|
-
readPermissionCell;
|
|
16
14
|
assignPermissionsButton;
|
|
17
15
|
dialog;
|
|
18
|
-
writePermissionCheckBox;
|
|
19
|
-
readPermissionCheckBox;
|
|
20
16
|
addButton;
|
|
21
17
|
permissionCell;
|
|
22
18
|
select;
|
|
@@ -26,18 +22,10 @@ class IdentityHomePage {
|
|
|
26
22
|
name: 'Camunda logo Identity',
|
|
27
23
|
});
|
|
28
24
|
this.accessToAPIsTab = page.getByRole('tab', { name: 'Access to APIs' });
|
|
29
|
-
this.writePermissionCell = page.getByRole('cell', { name: 'write:*' });
|
|
30
|
-
this.readPermissionCell = page.getByRole('cell', { name: 'read:*' });
|
|
31
25
|
this.assignPermissionsButton = page.getByRole('button', {
|
|
32
26
|
name: 'Assign permissions',
|
|
33
27
|
});
|
|
34
28
|
this.dialog = page.getByRole('dialog');
|
|
35
|
-
this.writePermissionCheckBox = page
|
|
36
|
-
.locator('label')
|
|
37
|
-
.filter({ hasText: 'write:*' });
|
|
38
|
-
this.readPermissionCheckBox = page
|
|
39
|
-
.locator('label')
|
|
40
|
-
.filter({ hasText: 'read:*' });
|
|
41
29
|
this.addButton = page.getByRole('button', { name: 'Add' });
|
|
42
30
|
this.permissionCell = (name) => page.getByRole('cell', { name: name });
|
|
43
31
|
this.tasklistCell = this.permissionCell('Tasklist');
|
|
@@ -45,86 +33,67 @@ class IdentityHomePage {
|
|
|
45
33
|
this.connectorsCell = this.permissionCell('Connectors');
|
|
46
34
|
this.select = this.page.locator('select');
|
|
47
35
|
}
|
|
48
|
-
async
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
async selectAllCheckboxes(apiName) {
|
|
37
|
+
const labels = this.dialog.locator('.cds--checkbox-label');
|
|
38
|
+
try {
|
|
39
|
+
await labels.first().waitFor({ state: 'visible', timeout: 30000 });
|
|
40
|
+
for (const label of await labels.all()) {
|
|
41
|
+
await label.click();
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
56
44
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
await (0, test_1.expect)(this.dialog).toBeVisible();
|
|
61
|
-
await this.writePermissionCheckBox.waitFor({ state: 'visible' });
|
|
62
|
-
await this.writePermissionCheckBox.click();
|
|
63
|
-
await this.readPermissionCheckBox.click();
|
|
64
|
-
await this.addButton.click();
|
|
65
|
-
await (0, test_1.expect)(this.permissionCell('write:*')).toBeVisible();
|
|
66
|
-
await (0, test_1.expect)(this.permissionCell('read:*')).toBeVisible();
|
|
67
|
-
await (0, sleep_1.sleep)(5000);
|
|
45
|
+
catch {
|
|
46
|
+
console.log(`No checkboxes found for ${apiName}, skipping Add`);
|
|
47
|
+
return false;
|
|
68
48
|
}
|
|
69
49
|
}
|
|
70
|
-
async
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// shared writePermissionCell/readPermissionCheckBox locators target — those
|
|
74
|
-
// wildcards still exist for the Tasklist API, so they stay untouched here.
|
|
75
|
-
// The dialog renders Carbon checkboxes labelled e.g. "write (Write
|
|
76
|
-
// permission)", and the assigned-permissions table renders the raw scope
|
|
77
|
-
// name (`read` / `write`) in a cell.
|
|
78
|
-
const operateWritePermissionCell = this.page.getByRole('cell', {
|
|
79
|
-
name: 'write',
|
|
80
|
-
exact: true,
|
|
81
|
-
});
|
|
82
|
-
const operateReadPermissionCell = this.page.getByRole('cell', {
|
|
83
|
-
name: 'read',
|
|
84
|
-
exact: true,
|
|
85
|
-
});
|
|
86
|
-
const operateWriteCheckBox = this.page.getByRole('checkbox', {
|
|
87
|
-
name: 'write (Write permission)',
|
|
88
|
-
});
|
|
89
|
-
const operateReadCheckBox = this.page.getByRole('checkbox', {
|
|
90
|
-
name: 'read (Read permission)',
|
|
91
|
-
exact: true,
|
|
92
|
-
});
|
|
93
|
-
await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.operateCell);
|
|
94
|
-
await this.operateCell.click();
|
|
50
|
+
async assignPermissions(appCell, apiName) {
|
|
51
|
+
await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, appCell);
|
|
52
|
+
await appCell.click();
|
|
95
53
|
await this.accessToAPIsTab.click();
|
|
96
54
|
await (0, sleep_1.sleep)(2000);
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
55
|
+
if (await this.page
|
|
56
|
+
.getByRole('cell')
|
|
57
|
+
.filter({ hasText: /^write/ })
|
|
58
|
+
.isVisible()) {
|
|
59
|
+
console.log(`Permissions already assigned to ${apiName}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
await this.assignPermissionsButton.click();
|
|
63
|
+
await this.selectOptionFromDropdown(apiName);
|
|
64
|
+
await (0, test_1.expect)(this.dialog).toBeVisible();
|
|
65
|
+
const checked = await this.selectAllCheckboxes(apiName);
|
|
66
|
+
if (!checked) {
|
|
67
|
+
return;
|
|
100
68
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
await operateWriteCheckBox.click();
|
|
107
|
-
await operateReadCheckBox.click();
|
|
69
|
+
await (0, sleep_1.sleep)(1000);
|
|
70
|
+
// Retry clicking Add until the dialog closes — the button can be
|
|
71
|
+
// present but unresponsive if the form hasn't registered the
|
|
72
|
+
// checkbox state yet (seen in docker compose: dialog stays open).
|
|
73
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
108
74
|
await this.addButton.click();
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
75
|
+
try {
|
|
76
|
+
await this.dialog.waitFor({ state: 'hidden', timeout: 5000 });
|
|
77
|
+
console.log(`Dialog closed after Add click (attempt ${attempt})`);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
console.log(`Dialog still open after Add attempt ${attempt}, retrying...`);
|
|
82
|
+
if (attempt === 3) {
|
|
83
|
+
throw new Error(`Dialog did not close after ${attempt} Add attempts for ${apiName}`);
|
|
84
|
+
}
|
|
85
|
+
await (0, sleep_1.sleep)(1000);
|
|
86
|
+
}
|
|
112
87
|
}
|
|
88
|
+
await (0, sleep_1.sleep)(3000);
|
|
89
|
+
}
|
|
90
|
+
async assignPermissionToTasklistAPI() {
|
|
91
|
+
await this.assignPermissions(this.tasklistCell, 'Tasklist API');
|
|
92
|
+
}
|
|
93
|
+
async assignPermissionToOperateAPI() {
|
|
94
|
+
await this.assignPermissions(this.operateCell, 'Operate API');
|
|
113
95
|
}
|
|
114
96
|
async selectOptionFromDropdown(option) {
|
|
115
|
-
// The Identity "Assign permissions to application" dialog renders the
|
|
116
|
-
// API list as a Carbon Select, which wraps a NATIVE <select> with native
|
|
117
|
-
// <option class="cds--select-option"> children. Native <option> elements
|
|
118
|
-
// are never "visible" to Playwright (the browser draws the option list as
|
|
119
|
-
// an OS-level widget, not as visible DOM), so clicking one via
|
|
120
|
-
// getByRole('option').click() always times out waiting for visibility —
|
|
121
|
-
// observed in nightly run 26731057113, where the option resolved but the
|
|
122
|
-
// click never succeeded ("element is not visible").
|
|
123
|
-
//
|
|
124
|
-
// Locator.selectOption() is the correct primitive for a native <select>:
|
|
125
|
-
// it sets the value and dispatches the `input`/`change` events that
|
|
126
|
-
// Carbon's onChange handler listens for, closing the picker and
|
|
127
|
-
// re-rendering the form with the write/read permission rows.
|
|
128
97
|
await this.select.selectOption({ label: option });
|
|
129
98
|
await (0, sleep_1.sleep)(1000);
|
|
130
99
|
}
|
|
@@ -34,7 +34,7 @@ class OperateProcessInstancePage {
|
|
|
34
34
|
}
|
|
35
35
|
async completedIconAssertion() {
|
|
36
36
|
let retryCount = 0;
|
|
37
|
-
const maxRetries =
|
|
37
|
+
const maxRetries = 5;
|
|
38
38
|
while (retryCount < maxRetries) {
|
|
39
39
|
try {
|
|
40
40
|
await (0, test_1.expect)(this.completedIcon).toBeVisible({
|
|
@@ -43,14 +43,14 @@ class OperateProcessInstancePage {
|
|
|
43
43
|
return; // Exit the function if the expectation is met
|
|
44
44
|
}
|
|
45
45
|
catch (error) {
|
|
46
|
-
// If the
|
|
46
|
+
// If the completed icon isn't found, reload the page and try again
|
|
47
47
|
retryCount++;
|
|
48
48
|
console.log(`Attempt ${retryCount} failed. Retrying...`);
|
|
49
49
|
await this.page.reload();
|
|
50
50
|
await (0, sleep_1.sleep)(10000);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
throw new Error(`
|
|
53
|
+
throw new Error(`Completed icon not visible after ${maxRetries} attempts.`);
|
|
54
54
|
}
|
|
55
55
|
async activeIconAssertion() {
|
|
56
56
|
let retryCount = 0;
|
|
@@ -42,66 +42,77 @@ if (process.env.RUN_AS_DOCKER_COMPOSE == 'true') {
|
|
|
42
42
|
});
|
|
43
43
|
(0, c8Run_8_7_1.test)('Search for process definitions', async ({ request }) => {
|
|
44
44
|
await (0, test_1.expect)(async () => {
|
|
45
|
-
const
|
|
45
|
+
const response = await request.post('/v1/process-definitions/search', {
|
|
46
46
|
headers: {
|
|
47
47
|
Authorization: `Bearer ${operateToken}`,
|
|
48
48
|
'Content-Type': 'application/json',
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
|
-
await (0, apiHelpers_1.assertResponseStatus)(
|
|
51
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
52
52
|
}).toPass(constants_1.defaultAssertionOptions);
|
|
53
53
|
});
|
|
54
54
|
(0, c8Run_8_7_1.test)('Get a process definition via key', async ({ request }) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
await (0, test_1.expect)(async () => {
|
|
56
|
+
const searchResponse = await request.post('/v1/process-definitions/search', {
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: `Bearer ${operateToken}`,
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
await (0, apiHelpers_1.assertResponseStatus)(searchResponse, 200);
|
|
63
|
+
const processKey = await searchResponse.json();
|
|
64
|
+
const response = await request.get('/v1/process-definitions/' + processKey.items[0].key, {
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${operateToken}`,
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
71
|
+
}).toPass(constants_1.defaultAssertionOptions);
|
|
69
72
|
});
|
|
70
73
|
(0, c8Run_8_7_1.test)('Search for process instances', async ({ request }) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
await (0, test_1.expect)(async () => {
|
|
75
|
+
const response = await request.post('/v1/process-instances/search', {
|
|
76
|
+
headers: {
|
|
77
|
+
Authorization: `Bearer ${operateToken}`,
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
82
|
+
}).toPass(constants_1.defaultAssertionOptions);
|
|
78
83
|
});
|
|
79
84
|
(0, c8Run_8_7_1.test)('Search for flownode-instances', async ({ request }) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
await (0, test_1.expect)(async () => {
|
|
86
|
+
const response = await request.post('/v1/flownode-instances/search', {
|
|
87
|
+
headers: {
|
|
88
|
+
Authorization: `Bearer ${operateToken}`,
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
93
|
+
}).toPass(constants_1.defaultAssertionOptions);
|
|
87
94
|
});
|
|
88
95
|
(0, c8Run_8_7_1.test)('Search for variables for process instancess', async ({ request }) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
await (0, test_1.expect)(async () => {
|
|
97
|
+
const response = await request.post('/v1/variables/search', {
|
|
98
|
+
headers: {
|
|
99
|
+
Authorization: `Bearer ${operateToken}`,
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
104
|
+
}).toPass(constants_1.defaultAssertionOptions);
|
|
96
105
|
});
|
|
97
106
|
(0, c8Run_8_7_1.test)('Search for incidents', async ({ request }) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
await (0, test_1.expect)(async () => {
|
|
108
|
+
const response = await request.post('/v1/incidents/search', {
|
|
109
|
+
headers: {
|
|
110
|
+
Authorization: `Bearer ${operateToken}`,
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
await (0, apiHelpers_1.assertResponseStatus)(response, 200);
|
|
115
|
+
}).toPass(constants_1.defaultAssertionOptions);
|
|
105
116
|
});
|
|
106
117
|
});
|
|
107
118
|
}
|
|
@@ -41,13 +41,13 @@ if (process.env.RUN_AS_DOCKER_COMPOSE == 'true') {
|
|
|
41
41
|
});
|
|
42
42
|
(0, c8Run_8_7_1.test)('Search for tasks', async ({ request }) => {
|
|
43
43
|
await (0, test_1.expect)(async () => {
|
|
44
|
-
const
|
|
44
|
+
const response = await request.post(tasklistBaseURL + '/v1/tasks/search', {
|
|
45
45
|
headers: {
|
|
46
46
|
Authorization: `Bearer ${tasklistToken}`,
|
|
47
47
|
'Content-Type': 'application/json',
|
|
48
48
|
},
|
|
49
49
|
});
|
|
50
|
-
(0, test_1.expect)(
|
|
50
|
+
(0, test_1.expect)(response.status()).toBe(200);
|
|
51
51
|
}).toPass(constants_1.defaultAssertionOptions);
|
|
52
52
|
});
|
|
53
53
|
(0, c8Run_8_7_1.test)('Get a task via ID', async ({ request }) => {
|