@camunda/e2e-test-suite 0.0.1025 → 0.0.1027

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.
@@ -8,6 +8,8 @@ declare class Authorization {
8
8
  protected readonly createAuthorizationOwnerTypeOption: (name: string) => Locator;
9
9
  protected readonly createAuthorizationOwnerComboBox: Locator;
10
10
  protected readonly createAuthorizationOwnerOption: (name: string) => Locator;
11
+ protected readonly createAuthorizationOwnerSearchInput: Locator;
12
+ protected readonly createAuthorizationOwnerSearchOption: (name: string) => Locator;
11
13
  protected readonly createAuthorizationResourceTypeDropdown: Locator;
12
14
  protected readonly createAuthorizationResourceTypeOption: (name: string) => Locator;
13
15
  protected readonly createAuthorizationResourceIdField: Locator;
@@ -19,6 +21,7 @@ declare class Authorization {
19
21
  protected readonly deleteAuthorizationModalDeleteButton: Locator;
20
22
  protected readonly tableFilter: Locator;
21
23
  constructor(page: Page);
24
+ private selectAuthorizationOwner;
22
25
  createAuthorization(authorization: {
23
26
  ownerType: string;
24
27
  ownerId: string;
@@ -14,6 +14,8 @@ class Authorization {
14
14
  createAuthorizationOwnerTypeOption;
15
15
  createAuthorizationOwnerComboBox;
16
16
  createAuthorizationOwnerOption;
17
+ createAuthorizationOwnerSearchInput;
18
+ createAuthorizationOwnerSearchOption;
17
19
  createAuthorizationResourceTypeDropdown;
18
20
  createAuthorizationResourceTypeOption;
19
21
  createAuthorizationResourceIdField;
@@ -51,6 +53,16 @@ class Authorization {
51
53
  name,
52
54
  exact: true,
53
55
  });
56
+ // Every owner type now renders a server-backed search dropdown instead of
57
+ // the combobox that listed all owners up front. The dropdown is a Carbon
58
+ // Search inside a ListBox, so it has no combobox role; its results are
59
+ // list-box menu items that carry the owner ID as their title.
60
+ this.createAuthorizationOwnerSearchInput =
61
+ this.createAuthorizationModal.getByPlaceholder('Search by owner ID');
62
+ this.createAuthorizationOwnerSearchOption = (name) => this.createAuthorizationModal
63
+ .locator('.cds--list-box__menu-item')
64
+ .filter({ hasText: name })
65
+ .first();
54
66
  this.createAuthorizationResourceTypeDropdown =
55
67
  this.createAuthorizationModal.getByRole('combobox', {
56
68
  name: 'Resource type',
@@ -79,18 +91,38 @@ class Authorization {
79
91
  });
80
92
  this.tableFilter = page.getByRole('searchbox', { name: 'Filter table' });
81
93
  }
82
- async createAuthorization(authorization) {
83
- await this.createAuthorizationButton.click();
84
- await (0, test_1.expect)(this.createAuthorizationModal).toBeVisible();
85
- await this.createAuthorizationOwnerTypeCombobox.click();
86
- await this.createAuthorizationOwnerTypeOption(authorization.ownerType).click();
94
+ // Released 8.10 alpha images still render the Carbon combobox that lists
95
+ // every owner, so accept whichever owner field this build shows.
96
+ async selectAuthorizationOwner(ownerId) {
97
+ await (0, test_1.expect)(this.createAuthorizationOwnerSearchInput.or(this.createAuthorizationOwnerComboBox)).toBeVisible({ timeout: 30000 });
98
+ if (await this.createAuthorizationOwnerSearchInput.isVisible()) {
99
+ await this.createAuthorizationOwnerSearchInput.fill(ownerId);
100
+ const ownerOption = this.createAuthorizationOwnerSearchOption(ownerId);
101
+ // The search is debounced and served by the API, so a just-created
102
+ // owner can take a while to surface.
103
+ await (0, test_1.expect)(ownerOption).toBeVisible({ timeout: 60000 });
104
+ await ownerOption.click({ timeout: 30000 });
105
+ // Picking an owner replaces the search input with a tag holding the
106
+ // selection, which is how we know the choice was committed.
107
+ await (0, test_1.expect)(this.createAuthorizationOwnerSearchInput).toBeHidden({
108
+ timeout: 30000,
109
+ });
110
+ return;
111
+ }
87
112
  await this.createAuthorizationOwnerComboBox.click();
88
- await (0, test_1.expect)(this.createAuthorizationOwnerOption(authorization.ownerId)).toBeVisible({
113
+ await (0, test_1.expect)(this.createAuthorizationOwnerOption(ownerId)).toBeVisible({
89
114
  timeout: 30000,
90
115
  });
91
- await this.createAuthorizationOwnerOption(authorization.ownerId).click({
116
+ await this.createAuthorizationOwnerOption(ownerId).click({
92
117
  timeout: 30000,
93
118
  });
119
+ }
120
+ async createAuthorization(authorization) {
121
+ await this.createAuthorizationButton.click();
122
+ await (0, test_1.expect)(this.createAuthorizationModal).toBeVisible();
123
+ await this.createAuthorizationOwnerTypeCombobox.click();
124
+ await this.createAuthorizationOwnerTypeOption(authorization.ownerType).click();
125
+ await this.selectAuthorizationOwner(authorization.ownerId);
94
126
  // The Resource type is pre-selected and disabled when the dialog is
95
127
  // opened from a specific resource-type tab. Only pick it from the dropdown
96
128
  // when the field is still enabled (editable).
@@ -87,6 +87,6 @@ declare class IdentityUsersPage {
87
87
  createResourceAuthorization(processId: string): Promise<void>;
88
88
  clickAssignAuthorizationButton(): Promise<void>;
89
89
  clickAssignedRolesTab(): Promise<void>;
90
- assertUserIsAssignedCorrectRole(username: string, roles: string[]): Promise<void>;
90
+ assertUserIsAssignedCorrectRole(username: string, roles: (string | string[])[]): Promise<void>;
91
91
  }
92
92
  export { IdentityUsersPage };
@@ -462,6 +462,9 @@ class IdentityUsersPage {
462
462
  async clickAssignedRolesTab() {
463
463
  await this.assignedRolesTab.click();
464
464
  }
465
+ // A role entry may be a single name, or a list of interchangeable names when
466
+ // Management Identity ships the same permission set under more than one label
467
+ // (e.g. 'Hub'/'Web Modeler'); any one of the listed names satisfies the entry.
465
468
  async assertUserIsAssignedCorrectRole(username, roles) {
466
469
  await this.page.getByRole('cell', { name: username, exact: true }).click();
467
470
  // Wait for the Assigned Roles tab to render before clicking it; after
@@ -469,9 +472,13 @@ class IdentityUsersPage {
469
472
  await (0, test_1.expect)(this.assignedRolesTab).toBeVisible({ timeout: 30000 });
470
473
  await this.assignedRolesTab.click();
471
474
  for (const role of roles) {
475
+ const acceptedNames = Array.isArray(role) ? role : [role];
476
+ const roleCell = acceptedNames
477
+ .map((name) => this.page.getByRole('cell', { name, exact: true }))
478
+ .reduce((combined, cell) => combined.or(cell));
472
479
  // Use a generous timeout: on slow/post-upgrade clusters the role table
473
480
  // may take several seconds to populate after the tab switch.
474
- await (0, test_1.expect)(this.page.getByRole('cell', { name: role, exact: true })).toBeVisible({ timeout: 60000 });
481
+ await (0, test_1.expect)(roleCell.first()).toBeVisible({ timeout: 60000 });
475
482
  }
476
483
  }
477
484
  }
@@ -263,9 +263,15 @@ class OCTenantPage {
263
263
  await this.roleIdSearchBox.click();
264
264
  }
265
265
  async fillRoleIdSearchBox(roleId, roleIdentifier) {
266
- await this.roleIdSearchBox.fill(roleId);
267
266
  const result = this.page.getByText(roleIdentifier).first();
268
- await (0, test_1.expect)(result).toBeVisible({ timeout: 15000 });
267
+ // The dropdown matches against the roles fetched with an empty search
268
+ // filter, so clearing the box re-triggers that fetch before retyping.
269
+ await (0, test_1.expect)(async () => {
270
+ await this.roleIdSearchBox.fill('');
271
+ await this.page.waitForLoadState('networkidle');
272
+ await this.roleIdSearchBox.fill(roleId);
273
+ await (0, test_1.expect)(result).toBeVisible({ timeout: 15000 });
274
+ }).toPass({ timeout: 90000, intervals: [2000] });
269
275
  await result.click();
270
276
  }
271
277
  async clickAssignRoleSubButton() {
@@ -279,6 +285,7 @@ class OCTenantPage {
279
285
  return;
280
286
  }
281
287
  await this.clickAssignRoleButton();
288
+ await this.page.waitForLoadState('networkidle');
282
289
  await this.clickRoleIdSearchBox();
283
290
  await this.fillRoleIdSearchBox(roleId, roleIdentifier);
284
291
  await this.clickAssignRoleSubButton();
@@ -109,14 +109,21 @@ if (process.env.IS_MIGRATION === 'true') {
109
109
  });
110
110
  });
111
111
  (0, SM_8_10_1.test)('Assert Users Persist in Management Identity With Correct Roles @tasklistV2', async ({ managementIdentityPage, identityUsersPage, }) => {
112
+ // 8.10 provisions 'Hub'/'Hub Admin' *alongside* 'Web Modeler'/'Web
113
+ // Modeler Admin' rather than renaming them, and both name pairs grant
114
+ // identical permissions, so an upgraded cluster may surface the modeler
115
+ // access under either pair. Each nested list accepts whichever of the
116
+ // equivalent names that cluster persisted. See camunda-docs
117
+ // docs/self-managed/upgrade/components/890-to-8100.md
118
+ // #management-identity-roles-and-permissions.
112
119
  await managementIdentityPage.clickUsersLink();
113
120
  await identityUsersPage.assertUserIsAssignedCorrectRole('demo', [
114
121
  'Default user role',
115
122
  'ManagementIdentity',
116
123
  'Optimize',
117
124
  'Orchestration',
118
- 'Hub',
119
- 'Hub Admin',
125
+ ['Hub', 'Web Modeler'],
126
+ ['Hub Admin', 'Web Modeler Admin'],
120
127
  ]);
121
128
  await managementIdentityPage.clickUsersLink();
122
129
  await identityUsersPage.assertUserIsAssignedCorrectRole('bart', [
@@ -124,8 +131,8 @@ if (process.env.IS_MIGRATION === 'true') {
124
131
  'ManagementIdentity',
125
132
  'Optimize',
126
133
  'Orchestration',
127
- 'Hub',
128
- 'Hub Admin',
134
+ ['Hub', 'Web Modeler'],
135
+ ['Hub Admin', 'Web Modeler Admin'],
129
136
  ]);
130
137
  await managementIdentityPage.clickUsersLink();
131
138
  await identityUsersPage.assertUserIsAssignedCorrectRole('lisa', [
@@ -133,8 +140,8 @@ if (process.env.IS_MIGRATION === 'true') {
133
140
  'ManagementIdentity',
134
141
  'Optimize',
135
142
  'Orchestration',
136
- 'Hub',
137
- 'Hub Admin',
143
+ ['Hub', 'Web Modeler'],
144
+ ['Hub Admin', 'Web Modeler Admin'],
138
145
  ]);
139
146
  });
140
147
  (0, SM_8_10_1.test)('Assert Demo User Can Deploy Processes', async ({ page, modelerHomePage, navigationPage, modelerCreatePage, operateHomePage, operateProcessesPage, operateProcessInstancePage, taskDetailsPage, taskPanelPage, }) => {
@@ -6,6 +6,12 @@ async function findLocatorWithPagination(page, locator, options) {
6
6
  const maxPages = 10;
7
7
  const paginationButton = page.getByRole('button', { name: 'Next page' });
8
8
  const backupPaginationButton = page.getByRole('button', { name: 'Load more' });
9
+ // The design-system DataTable the Admin UI is migrating onto labels its
10
+ // forward control just "Next", unlike Carbon's "Next page". Scope it to the
11
+ // pagination bar so an unrelated wizard "Next" can never be clicked.
12
+ const dataTablePaginationButton = page
13
+ .locator('[data-slot="data-table-pagination"]')
14
+ .getByRole('button', { name: 'Next', exact: true });
9
15
  const startTime = Date.now();
10
16
  for (let pageNum = 0; pageNum < maxPages; pageNum++) {
11
17
  if (Date.now() - startTime > timeout) {
@@ -20,7 +26,10 @@ async function findLocatorWithPagination(page, locator, options) {
20
26
  console.log(`Found locator "${locator}" on page ${pageNum + 1}`);
21
27
  return true;
22
28
  }
23
- const nextButton = paginationButton.or(backupPaginationButton).last();
29
+ const nextButton = paginationButton
30
+ .or(backupPaginationButton)
31
+ .or(dataTablePaginationButton)
32
+ .last();
24
33
  const isVisible = await nextButton
25
34
  .isVisible({ timeout: 1000 })
26
35
  .catch(() => false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1025",
3
+ "version": "0.0.1027",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",