@camunda/e2e-test-suite 0.0.1229 → 0.0.1231
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.9/ClusterDetailsPage.js +14 -2
- package/dist/pages/8.9/ClusterPage.js +9 -1
- package/dist/pages/8.9/HomePage.d.ts +1 -0
- package/dist/pages/8.9/HomePage.js +19 -0
- package/dist/pages/8.9/UtilitiesPage.js +6 -2
- package/dist/pages/SM-8.9/OCIdentityRolesPage.js +21 -2
- package/dist/pages/SM-8.9/UtilitiesPage.d.ts +1 -1
- package/dist/pages/SM-8.9/UtilitiesPage.js +9 -3
- package/package.json +1 -1
|
@@ -87,9 +87,21 @@ class ClusterDetailsPage {
|
|
|
87
87
|
name: 'Create new Client',
|
|
88
88
|
});
|
|
89
89
|
this.settingsTab = page.getByRole('tab', { name: 'Settings' });
|
|
90
|
-
this.rbaEnableButton = page.getByRole('button', { name: 'Enable' });
|
|
91
|
-
this.rbaDisableButton = page.getByRole('button', { name: 'Disable' });
|
|
92
90
|
this.dialog = page.getByRole('dialog');
|
|
91
|
+
// Scope the confirmation buttons to the open modal and match exactly. The
|
|
92
|
+
// authorizations toggle behind the modal is a button too, and its
|
|
93
|
+
// accessible name flips to "Authorizations enabled"/"Authorizations
|
|
94
|
+
// disabled" the moment it is clicked — a substring match on
|
|
95
|
+
// "Enable"/"Disable" then resolves to two elements (strict-mode violation),
|
|
96
|
+
// or to the toggle alone, whose click the modal backdrop intercepts.
|
|
97
|
+
this.rbaEnableButton = this.dialog.getByRole('button', {
|
|
98
|
+
name: 'Enable',
|
|
99
|
+
exact: true,
|
|
100
|
+
});
|
|
101
|
+
this.rbaDisableButton = this.dialog.getByRole('button', {
|
|
102
|
+
name: 'Disable',
|
|
103
|
+
exact: true,
|
|
104
|
+
});
|
|
93
105
|
this.deleteButton = page.getByRole('button', { name: 'Delete' });
|
|
94
106
|
// The danger button in Console's confirmation modals is now named just
|
|
95
107
|
// "Delete" (it used to expose "danger Delete"), so scope to the open
|
|
@@ -375,7 +375,15 @@ class ClusterPage {
|
|
|
375
375
|
}
|
|
376
376
|
else {
|
|
377
377
|
await this.createCluster(clusterName, region);
|
|
378
|
-
|
|
378
|
+
// The Healthy badge is only re-read after a reload, and
|
|
379
|
+
// expectLocatorWithRetry reloads once per attempt -- so `maxRetries` is
|
|
380
|
+
// what sets the polling resolution, not `totalTimeout`. With the old
|
|
381
|
+
// 120s/600s/5 the loop reloaded 5 times and gave up after ~570s, short
|
|
382
|
+
// of its own 600s budget. Polling every 15s instead reloads ~45 times,
|
|
383
|
+
// and 900s gives a cluster provisioning alongside the other parallel
|
|
384
|
+
// workers' clusters the room it actually needs (still well inside the
|
|
385
|
+
// 36-minute test.slow() budget).
|
|
386
|
+
await this.assertClusterHealthyStatusWithRetry(clusterName, 15000, 900000, 60);
|
|
379
387
|
}
|
|
380
388
|
}
|
|
381
389
|
async assertClusterHealthyStatusWithRetry(name, visibilityTimeout = 100000, totalTimeout = 500000, maxRetries) {
|
|
@@ -17,6 +17,7 @@ declare class HomePage {
|
|
|
17
17
|
readonly buttonSkipCustomization: Locator;
|
|
18
18
|
constructor(page: Page);
|
|
19
19
|
clickClusters(): Promise<void>;
|
|
20
|
+
clickClustersWithReloadRecovery(): Promise<void>;
|
|
20
21
|
clickDashboard(): Promise<void>;
|
|
21
22
|
clickOrganization(): Promise<void>;
|
|
22
23
|
closeInformationDialog(): Promise<void>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HomePage = void 0;
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
|
+
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
|
|
5
6
|
class HomePage {
|
|
6
7
|
page;
|
|
7
8
|
dashboardTab;
|
|
@@ -52,6 +53,24 @@ class HomePage {
|
|
|
52
53
|
await (0, test_1.expect)(this.clusterTab).toBeVisible({ timeout: 30000 });
|
|
53
54
|
await this.clusterTab.click({ timeout: 15000 });
|
|
54
55
|
}
|
|
56
|
+
// Same navigation as clickClusters(), but recovers from a Console SPA crash
|
|
57
|
+
// by remounting the app. Toggling authorizations restarts the cluster, and
|
|
58
|
+
// while it restarts the cluster-settings page's own API calls fail; Console
|
|
59
|
+
// has been seen to fall into its error boundary ("An error has occurred")
|
|
60
|
+
// there, which unmounts the banner along with the Clusters link. Waiting
|
|
61
|
+
// longer cannot recover a crashed route — only a reload can — so use this
|
|
62
|
+
// after an action that restarts the cluster. A route that crashes on every
|
|
63
|
+
// reload still fails, so a real Console regression is not hidden.
|
|
64
|
+
async clickClustersWithReloadRecovery() {
|
|
65
|
+
await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.clusterTab, {
|
|
66
|
+
visibilityTimeout: 30000,
|
|
67
|
+
totalTimeout: 180000,
|
|
68
|
+
maxRetries: 3,
|
|
69
|
+
postAction: async () => {
|
|
70
|
+
await this.page.reload();
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
55
74
|
async clickDashboard() {
|
|
56
75
|
await this.dashboardTab.click({ timeout: 90000 });
|
|
57
76
|
}
|
|
@@ -297,7 +297,9 @@ async function disableRBA(clusterName, homePage, clusterPage, clusterDetailsPage
|
|
|
297
297
|
});
|
|
298
298
|
await clusterDetailsPage.clickSettingsTab();
|
|
299
299
|
await clusterDetailsPage.disableAuthorizations();
|
|
300
|
-
|
|
300
|
+
// The toggle restarts the cluster; Console can crash out of the settings
|
|
301
|
+
// route while it does, taking the Clusters nav link with it.
|
|
302
|
+
await homePage.clickClustersWithReloadRecovery();
|
|
301
303
|
await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
|
|
302
304
|
await clusterPage.clickClusterLink(clusterName);
|
|
303
305
|
await (0, test_1.expect)(clusterDetailsPage.rbaEnabledMessage.first()).not.toBeVisible({
|
|
@@ -317,7 +319,9 @@ async function enableAuthorizations(clusterName, homePage, clusterPage, clusterD
|
|
|
317
319
|
});
|
|
318
320
|
await clusterDetailsPage.clickSettingsTab();
|
|
319
321
|
await clusterDetailsPage.enableAuthorizations();
|
|
320
|
-
|
|
322
|
+
// The toggle restarts the cluster; Console can crash out of the settings
|
|
323
|
+
// route while it does, taking the Clusters nav link with it.
|
|
324
|
+
await homePage.clickClustersWithReloadRecovery();
|
|
321
325
|
await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
|
|
322
326
|
await clusterPage.clickClusterLink(clusterName);
|
|
323
327
|
await clusterDetailsPage.assertComponentsHealth();
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.OCIdentityRolesPage = void 0;
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
5
|
const UtilitiesPage_1 = require("../SM-8.9/UtilitiesPage");
|
|
6
|
+
const expectLocatorWithPagination_1 = require("../../utils/assertionHelpers/expectLocatorWithPagination");
|
|
7
|
+
const findLocatorWithPagination_1 = require("../../utils/assertionHelpers/findLocatorWithPagination");
|
|
6
8
|
class OCIdentityRolesPage {
|
|
7
9
|
page;
|
|
8
10
|
selectResourceTypeTab;
|
|
@@ -100,6 +102,12 @@ class OCIdentityRolesPage {
|
|
|
100
102
|
await this.selectResourceTypeTab('Mapping Rules').click();
|
|
101
103
|
}
|
|
102
104
|
async clickRole(roleID) {
|
|
105
|
+
// The roles table paginates at 10 rows and the cluster already ships six
|
|
106
|
+
// built-in roles, so a role this suite created is regularly on page 2 and
|
|
107
|
+
// is never in the DOM on page 1 - walk the pages before asserting.
|
|
108
|
+
await (0, findLocatorWithPagination_1.findLocatorWithPagination)(this.page, this.roleCell(roleID).first(), {
|
|
109
|
+
timeout: 60000,
|
|
110
|
+
});
|
|
103
111
|
await (0, test_1.expect)(this.roleCell(roleID).first()).toBeVisible({ timeout: 60000 });
|
|
104
112
|
await this.roleCell(roleID).first().click();
|
|
105
113
|
}
|
|
@@ -122,15 +130,26 @@ class OCIdentityRolesPage {
|
|
|
122
130
|
await this.createNameField.fill(role.name);
|
|
123
131
|
await this.createRoleModalCreateButton.click();
|
|
124
132
|
await (0, test_1.expect)(this.createRoleModal).not.toBeVisible();
|
|
125
|
-
|
|
133
|
+
// A freshly created role sorts to the end of a table that paginates at 10
|
|
134
|
+
// rows, so on a cluster that already holds ten roles it lands on page 2.
|
|
135
|
+
// Polling page 1 can never see it - page through instead.
|
|
136
|
+
await (0, expectLocatorWithPagination_1.expectLocatorWithPagination)(this.page, this.rolesList
|
|
126
137
|
.getByRole('cell', {
|
|
127
138
|
name: role.name,
|
|
128
139
|
})
|
|
129
|
-
.first(),
|
|
140
|
+
.first(), { maxRetries: 10 });
|
|
130
141
|
}
|
|
131
142
|
async deleteRole(name, options) {
|
|
132
143
|
const { throwError = true } = options || {};
|
|
133
144
|
try {
|
|
145
|
+
// Same pagination trap as createRole: the row - and therefore its
|
|
146
|
+
// Delete button - is regularly on page 2 by the time cleanup runs. With
|
|
147
|
+
// throwError:false the miss is swallowed, which is how stale roles pile
|
|
148
|
+
// up on the cluster and push later roles off page 1 in the first place.
|
|
149
|
+
const found = await (0, findLocatorWithPagination_1.findLocatorWithPagination)(this.page, this.deleteRoleButton(name), { timeout: 30000 });
|
|
150
|
+
if (!found) {
|
|
151
|
+
throw new Error(`Role "${name}" was not found on any page of the roles table`);
|
|
152
|
+
}
|
|
134
153
|
await this.deleteRoleButton(name).click();
|
|
135
154
|
await (0, test_1.expect)(this.deleteRoleModal).toBeVisible();
|
|
136
155
|
await this.deleteRoleModalDeleteButton.click();
|
|
@@ -24,7 +24,7 @@ export declare function modelRestConnector(modelerCreatePage: ModelerCreatePage,
|
|
|
24
24
|
username: string;
|
|
25
25
|
password: string;
|
|
26
26
|
}): Promise<void>;
|
|
27
|
-
export declare function assertLocatorVisibleWithPaginated(page: Page, locator: Locator, text: string): Promise<void>;
|
|
27
|
+
export declare function assertLocatorVisibleWithPaginated(page: Page, locator: Locator, text: string, timeout?: number): Promise<void>;
|
|
28
28
|
export declare function assertLocatorVisibleWithRetry(page: Page, locator: Locator, text: string, timeout?: number, notVisible?: boolean, maxRetries?: number, clickLocator?: Locator): Promise<void>;
|
|
29
29
|
export declare function assertPageTextWithRetry(page: Page, text: string, notVisible?: boolean, timeout?: number, maxRetries?: number): Promise<void>;
|
|
30
30
|
export declare function modelAndRunConnectorsTimerEventDiagram(modelerCreatePage: ModelerCreatePage, modelerHomePage: ModelerHomePage, processName: string, page: Page, connectorMarketplacePage: ConnectorMarketplacePage, connectorTemplatePage: ConnectorTemplatePage, tenant?: string): Promise<void>;
|
|
@@ -48,10 +48,13 @@ async function assignMappingToRole(page, ocIdentityHomePage, ocIdentityRolesPage
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
catch (error) {
|
|
51
|
-
|
|
51
|
+
// Register the id before creating so a create that fails part-way still
|
|
52
|
+
// leaves the role on the afterEach cleanup list; a leaked role stays on
|
|
53
|
+
// the cluster forever and pushes later roles onto page 2 of the table.
|
|
52
54
|
if (testMappings && role.toLowerCase() != 'admin') {
|
|
53
55
|
testMappings.roleIds.push(role);
|
|
54
56
|
}
|
|
57
|
+
await ocIdentityRolesPage.createRole({ id: role, name: role });
|
|
55
58
|
}
|
|
56
59
|
await ocIdentityRolesPage.assignMappingRuleToRole(role, mappingRuleId);
|
|
57
60
|
await assertLocatorVisibleWithPaginated(page, ocIdentityRolesPage.mappingRuleRow(mappingRuleId).first(), `${mappingRuleId} Mapping Rule`);
|
|
@@ -231,7 +234,7 @@ async function modelRestConnector(modelerCreatePage, connectorSettingsPage, conn
|
|
|
231
234
|
await (0, sleep_1.sleep)(10000);
|
|
232
235
|
}
|
|
233
236
|
exports.modelRestConnector = modelRestConnector;
|
|
234
|
-
async function assertLocatorVisibleWithPaginated(page, locator, text) {
|
|
237
|
+
async function assertLocatorVisibleWithPaginated(page, locator, text, timeout = 20000) {
|
|
235
238
|
const maxRetries = 6;
|
|
236
239
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
237
240
|
try {
|
|
@@ -240,7 +243,10 @@ async function assertLocatorVisibleWithPaginated(page, locator, text) {
|
|
|
240
243
|
if (attempt > 2) {
|
|
241
244
|
await (0, findLocatorInPaginatedList_1.findLocatorInPaginatedList)(page, locator);
|
|
242
245
|
}
|
|
243
|
-
|
|
246
|
+
// Without an explicit budget this inherits the 5s expect default, so
|
|
247
|
+
// six attempts only poll for ~60s in total - not enough for a freshly
|
|
248
|
+
// assigned mapping rule to show up on the role detail page.
|
|
249
|
+
await (0, test_1.expect)(locator).toBeVisible({ timeout });
|
|
244
250
|
return;
|
|
245
251
|
}
|
|
246
252
|
catch (error) {
|