@camunda/e2e-test-suite 0.0.1041 → 0.0.1042

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.
@@ -29,6 +29,8 @@ declare class Authorization {
29
29
  resourceId: string;
30
30
  accessPermissions: string[];
31
31
  }): Promise<void>;
32
+ private expectAuthorizationListed;
33
+ private filterAuthorizationsByOwner;
32
34
  deleteAuthorization(resourceId: string, resourceType: string): Promise<void>;
33
35
  }
34
36
  export { Authorization };
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Authorization = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  const UtilitiesPage_1 = require("../SM-8.10/UtilitiesPage");
6
+ const findLocatorWithPagination_1 = require("../../utils/assertionHelpers/findLocatorWithPagination");
6
7
  const submitModalWithRetry_1 = require("../../utils/assertionHelpers/submitModalWithRetry");
7
8
  const sleep_1 = require("../../utils/sleep");
8
9
  class Authorization {
@@ -89,7 +90,13 @@ class Authorization {
89
90
  this.deleteAuthorizationModal.getByRole('button', {
90
91
  name: /delete authorization/i,
91
92
  });
92
- this.tableFilter = page.getByRole('searchbox', { name: 'Filter table' });
93
+ // Carbon labels the table toolbar search "Filter table"; the
94
+ // design-system shell the Admin is migrating onto exposes the placeholder
95
+ // as the accessible name instead. Match either.
96
+ this.tableFilter = page
97
+ .getByRole('searchbox', { name: 'Filter table' })
98
+ .or(page.getByRole('searchbox', { name: 'Search by owner ID' }))
99
+ .first();
93
100
  }
94
101
  // Released 8.10 alpha images still render the Carbon combobox that lists
95
102
  // every owner, so accept whichever owner field this build shows.
@@ -162,14 +169,81 @@ class Authorization {
162
169
  }
163
170
  await (0, submitModalWithRetry_1.submitModalWithRetry)(this.createAuthorizationSubmitButton, this.createAuthorizationModal);
164
171
  await this.selectResourceTypeTab(authorization.resourceType).click();
165
- const item = this.page.getByRole('row').filter({
172
+ const item = this.page
173
+ .getByRole('row')
174
+ .filter({
166
175
  hasText: `${authorization.ownerId}${authorization.resourceId}`,
167
- });
168
- await this.tableFilter.click();
169
- await this.tableFilter.fill(authorization.resourceType);
170
- await (0, UtilitiesPage_1.assertLocatorVisibleWithRetry)(this.page, item, authorization.resourceType, 5000, false, 10, this.selectResourceTypeTab(authorization.resourceType));
176
+ })
177
+ .first();
178
+ await this.expectAuthorizationListed(authorization, item);
179
+ }
180
+ // The toolbar search filters by owner ID, so filling it with the resource
181
+ // type narrowed nothing, and the retry helper it fed reloads before it
182
+ // asserts, which dropped the filter entirely. That left the new row to be
183
+ // found on page 1 of the unfiltered table - and the authorizations table
184
+ // paginates, so with the RBA specs creating owners in parallel it is
185
+ // regularly on a later page. Filter by owner, then page through what is
186
+ // left; fall back to the unfiltered table for builds whose search has not
187
+ // caught up with a just-created owner yet.
188
+ async expectAuthorizationListed(authorization, item) {
189
+ const deadline = Date.now() + 180000;
190
+ const budget = (max) => Math.max(5000, Math.min(max, deadline - Date.now()));
191
+ const maxAttempts = 5;
192
+ let lastError;
193
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
194
+ if (attempt > 0 && Date.now() >= deadline) {
195
+ break;
196
+ }
197
+ try {
198
+ const resourceTab = this.selectResourceTypeTab(authorization.resourceType);
199
+ await (0, test_1.expect)(resourceTab).toBeVisible({ timeout: budget(30000) });
200
+ await resourceTab.click({ timeout: budget(30000) });
201
+ for (const filterValue of [authorization.ownerId, '']) {
202
+ await this.filterAuthorizationsByOwner(filterValue);
203
+ const found = await (0, findLocatorWithPagination_1.findLocatorWithPagination)(this.page, item, {
204
+ timeout: budget(filterValue === '' ? 45000 : 15000),
205
+ });
206
+ if (found) {
207
+ await (0, test_1.expect)(item).toBeVisible({ timeout: 5000 });
208
+ return;
209
+ }
210
+ }
211
+ throw new Error(`No row for owner "${authorization.ownerId}" and resource ` +
212
+ `"${authorization.resourceId}" in the ` +
213
+ `${authorization.resourceType} table`);
214
+ }
215
+ catch (error) {
216
+ lastError = error;
217
+ if (attempt < maxAttempts - 1) {
218
+ console.warn(`Attempt ${attempt + 1} did not list the ` +
219
+ `${authorization.resourceType} authorization for ` +
220
+ `"${authorization.ownerId}". Retrying...`);
221
+ await this.page.reload();
222
+ await this.page.waitForLoadState('domcontentloaded');
223
+ }
224
+ }
225
+ }
226
+ throw new Error(`Authorization for "${authorization.ownerId}" on ` +
227
+ `"${authorization.resourceId}" was not listed: ${String(lastError)}`);
228
+ }
229
+ async filterAuthorizationsByOwner(ownerId) {
230
+ const hasFilter = await this.tableFilter
231
+ .isVisible({ timeout: 5000 })
232
+ .catch(() => false);
233
+ if (!hasFilter) {
234
+ return;
235
+ }
236
+ await this.tableFilter.fill(ownerId);
237
+ await (0, sleep_1.sleep)(1000);
171
238
  }
172
239
  async deleteAuthorization(resourceId, resourceType) {
240
+ // Same paginated table as createAuthorization: the row being deleted is
241
+ // not necessarily on page 1, and the toolbar search cannot narrow by
242
+ // resource ID.
243
+ const found = await (0, findLocatorWithPagination_1.findLocatorWithPagination)(this.page, this.deleteAuthorizationButton(resourceId), { timeout: 60000 });
244
+ if (!found) {
245
+ throw new Error(`No ${resourceType} authorization row for resource "${resourceId}"`);
246
+ }
173
247
  await this.deleteAuthorizationButton(resourceId).click();
174
248
  await (0, test_1.expect)(this.deleteAuthorizationModal).toBeVisible();
175
249
  await this.deleteAuthorizationModalDeleteButton.click();
@@ -29,9 +29,14 @@ class OCIdentityMappingRulesPage {
29
29
  this.deleteMappingRuleDialog = page.getByRole('dialog', {
30
30
  name: 'Delete Mapping rule',
31
31
  });
32
- this.filterTableSearchbox = page.getByRole('searchbox', {
33
- name: 'Filter table',
34
- });
32
+ // The design-system Admin shell replaced Carbon's table toolbar search
33
+ // (labelled "Filter table") with an input whose aria-label is its
34
+ // placeholder, so match the new shell first and fall back to the legacy
35
+ // one - the same dual-shell pattern the Admin nav locators use.
36
+ this.filterTableSearchbox = page
37
+ .getByRole('searchbox', { name: 'Search by mapping rule ID' })
38
+ .or(page.getByRole('searchbox', { name: 'Filter table' }))
39
+ .first();
35
40
  this.deleteMappingRuleButton = this.deleteMappingRuleDialog
36
41
  .getByRole('button', {
37
42
  name: 'Delete Mapping rule',
@@ -172,6 +172,16 @@ class OCIdentityRolesPage {
172
172
  async deleteRole(name, options) {
173
173
  const { throwError = true } = options || {};
174
174
  try {
175
+ // The roles table paginates at 10 rows and the RBA specs run in
176
+ // parallel against a cluster that already ships six built-in roles, so
177
+ // a role created by this test is regularly on page 2 by the time it is
178
+ // deleted. Without walking the pages the row - and therefore its Delete
179
+ // button - simply never resolves, which is what the 10s click timeout
180
+ // reported.
181
+ const found = await (0, findLocatorWithPagination_1.findLocatorWithPagination)(this.page, this.deleteRoleButton(name), { timeout: 30000 });
182
+ if (!found) {
183
+ throw new Error(`Role "${name}" was not found on any page of the roles table`);
184
+ }
175
185
  await this.deleteRoleButton(name).click();
176
186
  await (0, test_1.expect)(this.deleteRoleModal).toBeVisible();
177
187
  await this.deleteRoleModalDeleteButton.click();
@@ -25,6 +25,7 @@ if (node_process_1.default.env.IS_RBA === 'true') {
25
25
  await navigationPage.goToOCAdmin();
26
26
  const ids = idsToBeDeleted[testInfo.title];
27
27
  if (ids['mappingIds'].length > 0) {
28
+ await ocIdentityHomePage.clickMappingRulesTab();
28
29
  for (const id of ids['mappingIds']) {
29
30
  await ocIdentityMappingRulesPage.deleteMappingRule(id);
30
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1041",
3
+ "version": "0.0.1042",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",