@camunda/e2e-test-suite 0.0.478 → 0.0.480

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.
@@ -23,15 +23,17 @@ class LoginPage {
23
23
  this.coreLoginButton = page.getByRole('button', { name: 'Login' });
24
24
  this.keycloakBanner = page.locator('body#keycloak-bg[data-page-id="login-login"]');
25
25
  }
26
- // Race logic: call before interacting
27
26
  async detectLoginForm() {
28
- const winner = await Promise.race([
29
- this.usernameInput.waitFor({ state: 'visible' }).then(() => 'default'),
30
- this.coreUsernameInput.waitFor({ state: 'visible' }).then(() => 'core'),
31
- this.keycloakBanner.waitFor({ state: 'visible' }).then(() => 'keycloak'),
32
- ]);
33
- this.useCore = winner === 'core';
34
- this.useKeycloak = winner === 'keycloak';
27
+ const anyForm = this.usernameInput
28
+ .or(this.coreUsernameInput)
29
+ .or(this.keycloakBanner);
30
+ await anyForm.waitFor({ state: 'visible', timeout: 15000 });
31
+ if (await this.coreUsernameInput.isVisible()) {
32
+ this.useCore = true;
33
+ }
34
+ else if (await this.keycloakBanner.isVisible()) {
35
+ this.useKeycloak = true;
36
+ }
35
37
  }
36
38
  async fillUsername(username) {
37
39
  if (await this.page.locator('#username').isVisible()) {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModelerHomePage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- const sleep_1 = require("../../utils/sleep");
6
5
  const expectLocatorWithRetry_1 = require("../../utils/assertionHelpers/expectLocatorWithRetry");
7
6
  class ModelerHomePage {
8
7
  page;
@@ -75,13 +74,14 @@ class ModelerHomePage {
75
74
  await this.createNewProjectButton.click();
76
75
  }
77
76
  async enterNewProjectName(name) {
78
- await (0, sleep_1.sleep)(1000);
77
+ await (0, test_1.expect)(this.projectNameInput).toBeVisible({ timeout: 10000 });
79
78
  await this.projectNameInput.click({ timeout: 60000 });
80
79
  await this.projectNameInput.fill(name);
81
80
  await this.projectNameInput.press('Enter');
82
81
  }
83
82
  async createCrossComponentProjectFolder() {
84
- await (0, sleep_1.sleep)(10000);
83
+ await this.page.waitForLoadState('networkidle');
84
+ await (0, test_1.expect)(this.createNewProjectButton).toBeVisible({ timeout: 30000 });
85
85
  await this.clickMessageBanner();
86
86
  if (await this.crossComponentProjectFolder.isVisible()) {
87
87
  console.log('Cross Component Project folder already exists. Clicking into it');
@@ -90,7 +90,7 @@ class ModelerHomePage {
90
90
  }
91
91
  await this.clickCreateNewProjectButton();
92
92
  await this.enterNewProjectName(this.defaultFolderName);
93
- await (0, sleep_1.sleep)(5000);
93
+ await (0, test_1.expect)(this.page.getByRole('heading', { name: this.defaultFolderName })).toBeVisible({ timeout: 10000 });
94
94
  }
95
95
  async clickCrossComponentProjectFolder() {
96
96
  let attempts = 0;
@@ -109,7 +109,7 @@ class ModelerHomePage {
109
109
  if (attempts < maxAttempts) {
110
110
  console.log(`Attempt ${attempts} failed. Reloading page and retrying...`);
111
111
  await this.page.reload();
112
- await (0, sleep_1.sleep)(10000);
112
+ await this.page.waitForLoadState('domcontentloaded');
113
113
  }
114
114
  else {
115
115
  throw new Error('Failed to click crossComponentProjectFolder after 3 attempts.');
@@ -149,7 +149,7 @@ class ModelerHomePage {
149
149
  await this.formTemplateOption.click();
150
150
  }
151
151
  async enterFormName(name) {
152
- await (0, sleep_1.sleep)(1000);
152
+ await (0, test_1.expect)(this.formNameInput).toBeVisible({ timeout: 10000 });
153
153
  await this.formNameInput.click({ timeout: 60000 });
154
154
  await this.formNameInput.fill(name);
155
155
  await this.formNameInput.press('Enter');
@@ -168,10 +168,13 @@ class ModelerHomePage {
168
168
  }
169
169
  async clickMessageBanner() {
170
170
  try {
171
- await Promise.race([
172
- this.messageBanner.click(),
173
- this.closeButton.click(),
174
- ]);
171
+ const banner = this.messageBanner.or(this.closeButton);
172
+ if (await banner.isVisible({ timeout: 2000 })) {
173
+ await banner.click();
174
+ }
175
+ else {
176
+ console.log('No banner or close button found to click');
177
+ }
175
178
  }
176
179
  catch {
177
180
  console.log('No banner or close button found to click');
@@ -77,14 +77,11 @@ class NavigationPage {
77
77
  await (0, test_1.expect)(loginEntryPoint).toBeVisible({ timeout: 30000 });
78
78
  const isBannerVisible = await banner.isVisible().catch(() => false);
79
79
  if (isBannerVisible) {
80
- try {
81
- await (0, test_1.expect)(loginPage.usernameInput).toBeVisible({ timeout: 5000 });
80
+ const loginVisible = await loginPage.usernameInput.isVisible();
81
+ if (loginVisible) {
82
82
  await loginPage.login(username, password);
83
83
  }
84
- catch (error) {
85
- // The login selector did NOT appear. The banner is real. We are on the correct page.
86
- // The navigation was successful, so we can just return.
87
- }
84
+ // If login selector not visible, banner is real - navigation succeeded
88
85
  }
89
86
  else {
90
87
  await loginPage.login(username, password);
@@ -96,7 +93,7 @@ class NavigationPage {
96
93
  const now = new Date();
97
94
  const elapsed = Date.now() - startTime;
98
95
  if (attempt < maxRetries - 1) {
99
- await (0, sleep_1.sleep)(5000);
96
+ await (0, sleep_1.sleep)(2000);
100
97
  if (!this.page.isClosed()) {
101
98
  try {
102
99
  await this.page.waitForLoadState('load', { timeout: timeout });
@@ -50,7 +50,7 @@ class OperateProcessInstancePage {
50
50
  retryCount++;
51
51
  console.log(`Attempt ${retryCount} failed. Retrying...`);
52
52
  await this.page.reload();
53
- await (0, sleep_1.sleep)(10000);
53
+ await this.page.waitForLoadState('domcontentloaded');
54
54
  }
55
55
  }
56
56
  throw new Error(`Active icon not visible after ${maxRetries} attempts.`);
@@ -70,7 +70,7 @@ class OperateProcessInstancePage {
70
70
  retryCount++;
71
71
  console.log(`Attempt ${retryCount} failed. Retrying...`);
72
72
  await this.page.reload();
73
- await (0, sleep_1.sleep)(10000);
73
+ await this.page.waitForLoadState('domcontentloaded');
74
74
  }
75
75
  }
76
76
  throw new Error(`Active icon not visible after ${maxRetries} attempts.`);
@@ -90,7 +90,7 @@ class OperateProcessInstancePage {
90
90
  retryCount++;
91
91
  console.log(`Attempt ${retryCount} failed. Retrying...`);
92
92
  await this.page.reload();
93
- await (0, sleep_1.sleep)(10000);
93
+ await this.page.waitForLoadState('domcontentloaded');
94
94
  }
95
95
  }
96
96
  throw new Error(`Active icon not visible after ${maxRetries} attempts.`);
@@ -110,7 +110,7 @@ class OperateProcessInstancePage {
110
110
  retryCount++;
111
111
  console.log(`Attempt ${retryCount} failed. Retrying...`);
112
112
  await this.page.reload();
113
- await (0, sleep_1.sleep)(10000);
113
+ await this.page.waitForLoadState('domcontentloaded');
114
114
  }
115
115
  }
116
116
  throw new Error(`Active icon visible after ${maxRetries} attempts.`);
@@ -122,16 +122,18 @@ class OperateProcessInstancePage {
122
122
  await (0, test_1.expect)(this.incidentIcon).toBeVisible({ timeout: 90000 });
123
123
  }
124
124
  async assertEitherIncidentOrActiveIconVisible() {
125
- return Promise.race([
126
- this.incidentIcon.waitFor({ timeout: 90000 }).then(() => 'incident'),
127
- this.activeIcon.waitFor({ timeout: 90000 }).then(() => 'active'),
128
- ]);
125
+ const either = this.incidentIcon.or(this.activeIcon);
126
+ await (0, test_1.expect)(either).toBeVisible({ timeout: 90000 });
127
+ if (await this.incidentIcon.isVisible())
128
+ return 'incident';
129
+ return 'active';
129
130
  }
130
131
  async assertEitherIncidentOrCompletedIconVisible() {
131
- return Promise.race([
132
- this.incidentIcon.waitFor({ timeout: 90000 }).then(() => 'incident'),
133
- this.completedIcon.waitFor({ timeout: 90000 }).then(() => 'completed'),
134
- ]);
132
+ const either = this.incidentIcon.or(this.completedIcon);
133
+ await (0, test_1.expect)(either).toBeVisible({ timeout: 90000 });
134
+ if (await this.incidentIcon.isVisible())
135
+ return 'incident';
136
+ return 'completed';
135
137
  }
136
138
  async assertProcessCompleteStatusWithRetry(timeout = 60000, maxRetries = 10) {
137
139
  for (let attempt = 0; attempt < maxRetries; attempt++) {
@@ -145,7 +147,7 @@ class OperateProcessInstancePage {
145
147
  if (attempt < maxRetries - 1) {
146
148
  console.warn(`Process complete status attempt ${attempt + 1} failed. Retrying...`);
147
149
  await this.page.reload();
148
- await (0, sleep_1.sleep)(5000);
150
+ await this.page.waitForLoadState('domcontentloaded');
149
151
  }
150
152
  else {
151
153
  throw new Error(`Assertion failed after ${maxRetries} attempts`);
@@ -164,7 +166,7 @@ class OperateProcessInstancePage {
164
166
  console.log(`assertProcessVariableContainsText attempt ${attempt + 1}/${maxRetries} failed: ${error}`);
165
167
  if (attempt < maxRetries - 1) {
166
168
  await this.page.reload({ timeout: 10000 }).catch(() => { });
167
- await (0, sleep_1.sleep)(2000);
169
+ await this.page.waitForLoadState('domcontentloaded').catch(() => { });
168
170
  }
169
171
  }
170
172
  }
@@ -182,7 +184,7 @@ class OperateProcessInstancePage {
182
184
  console.log(`assertResultVariableVisibleWithRetry attempt ${attempt + 1}/${maxRetries} failed: ${error}`);
183
185
  if (attempt < maxRetries - 1) {
184
186
  await this.page.reload({ timeout: 10000 }).catch(() => { });
185
- await (0, sleep_1.sleep)(2000);
187
+ await this.page.waitForLoadState('domcontentloaded').catch(() => { });
186
188
  }
187
189
  }
188
190
  }
@@ -26,15 +26,11 @@ class OptimizeCollectionsPage {
26
26
  this.reportAuthor = page.getByRole('cell', { name: 'Demo User' });
27
27
  }
28
28
  async clickCreateNewButton() {
29
- try {
30
- await this.modalCloseButton.click({ timeout: 60000 });
31
- await this.collectionsLink.click({ timeout: 60000 });
32
- await this.createNewButton.click({ timeout: 90000 });
33
- }
34
- catch (error) {
35
- await this.collectionsLink.click({ timeout: 60000 });
36
- await this.createNewButton.click({ timeout: 90000 });
29
+ if (await this.modalCloseButton.isVisible({ timeout: 2000 })) {
30
+ await this.modalCloseButton.click();
37
31
  }
32
+ await this.collectionsLink.click({ timeout: 60000 });
33
+ await this.createNewButton.click({ timeout: 90000 });
38
34
  }
39
35
  async clickReportOption() {
40
36
  await this.reportOption.click();
@@ -30,22 +30,16 @@ class OptimizeHomePage {
30
30
  this.licenseKeyTagProduction = page.getByText('Production license').first();
31
31
  }
32
32
  async clickCollectionsLink() {
33
- try {
33
+ if (await this.modalCloseButton.isVisible({ timeout: 2000 })) {
34
34
  await this.modalCloseButton.click();
35
- await this.collectionsLink.click();
36
- }
37
- catch (error) {
38
- await this.collectionsLink.click();
39
35
  }
36
+ await this.collectionsLink.click();
40
37
  }
41
38
  async clickDashboardLink() {
42
- try {
39
+ if (await this.modalCloseButton.isVisible({ timeout: 2000 })) {
43
40
  await this.modalCloseButton.click();
44
- await this.dashboardLink.click();
45
- }
46
- catch (error) {
47
- await this.dashboardLink.click();
48
41
  }
42
+ await this.dashboardLink.click();
49
43
  }
50
44
  async assertProcessHasBeenImported(processId) {
51
45
  await this.clickDashboardLink();
@@ -75,7 +75,6 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
75
75
  .first();
76
76
  if (await toastCloseButton.isVisible({ timeout: 2000 })) {
77
77
  await toastCloseButton.click();
78
- await (0, sleep_1.sleep)(500);
79
78
  }
80
79
  }
81
80
  catch {
@@ -84,7 +83,6 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
84
83
  for (let attempt = 0; attempt < maxRetries; attempt++) {
85
84
  try {
86
85
  await page.waitForLoadState('networkidle');
87
- await (0, sleep_1.sleep)(500);
88
86
  const taskLocator = taskPanelPage.availableTasks
89
87
  .getByText(taskName, { exact: true })
90
88
  .first();
@@ -97,7 +95,6 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
97
95
  // Click the task directly instead of using openTask's 30-retry loop
98
96
  // (this outer loop already provides retry logic)
99
97
  await taskLocator.click({ timeout: 10000 });
100
- await (0, sleep_1.sleep)(1000);
101
98
  await (0, test_1.expect)(taskDetailsPage.detailsPanel).toBeVisible({ timeout: 30000 });
102
99
  // Verify the correct task is loaded by checking the task name appears
103
100
  // in the details-info section (the task name heading is outside the
@@ -109,9 +106,9 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
109
106
  await (0, test_1.expect)(taskDetailsPage.detailsPanel.getByText(taskPriority)).toBeVisible({ timeout: 30000 });
110
107
  await taskDetailsPage.completeTaskButton.click({ timeout: 30000 });
111
108
  await (0, test_1.expect)(taskDetailsPage.taskCompletedBanner).toBeVisible({
112
- timeout: 60000,
109
+ timeout: 30000,
113
110
  });
114
- await (0, test_1.expect)(taskPanelPage.availableTasks.getByText(taskName, { exact: true }).first()).not.toBeVisible({ timeout: 60000 });
111
+ await (0, test_1.expect)(taskPanelPage.availableTasks.getByText(taskName, { exact: true }).first()).not.toBeVisible({ timeout: 15000 });
115
112
  console.log(`Successfully completed task: ${taskName}`);
116
113
  return;
117
114
  }
@@ -126,7 +123,6 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
126
123
  .first();
127
124
  if (await toastCloseButton.isVisible({ timeout: 1000 })) {
128
125
  await toastCloseButton.click();
129
- await (0, sleep_1.sleep)(300);
130
126
  }
131
127
  }
132
128
  catch {
@@ -134,7 +130,6 @@ async function completeTaskWithRetry(page, taskPanelPage, taskDetailsPage, taskN
134
130
  }
135
131
  await page.reload();
136
132
  await page.waitForLoadState('networkidle');
137
- await (0, sleep_1.sleep)(500);
138
133
  }
139
134
  else {
140
135
  console.error(`All ${maxRetries} attempts failed for task ${taskName}`);
@@ -253,10 +248,11 @@ async function assertLocatorVisibleWithPaginated(page, locator, text) {
253
248
  }
254
249
  }
255
250
  exports.assertLocatorVisibleWithPaginated = assertLocatorVisibleWithPaginated;
256
- async function assertLocatorVisibleWithRetry(page, locator, text, timeout = 120000, notVisible, maxRetries = 3, clickLocator) {
251
+ async function assertLocatorVisibleWithRetry(page, locator, text, timeout = 30000, notVisible, maxRetries = 3, clickLocator) {
257
252
  for (let attempt = 0; attempt < maxRetries; attempt++) {
258
253
  try {
259
254
  await page.reload();
255
+ await page.waitForLoadState('domcontentloaded');
260
256
  if (clickLocator) {
261
257
  await (0, test_1.expect)(clickLocator).toBeVisible({
262
258
  timeout: 30000,
@@ -264,7 +260,6 @@ async function assertLocatorVisibleWithRetry(page, locator, text, timeout = 1200
264
260
  await clickLocator.click();
265
261
  }
266
262
  if (notVisible == true) {
267
- await (0, sleep_1.sleep)(10000);
268
263
  await (0, test_1.expect)(locator.first()).not.toBeVisible({
269
264
  timeout: timeout,
270
265
  });
@@ -287,12 +282,12 @@ async function assertLocatorVisibleWithRetry(page, locator, text, timeout = 1200
287
282
  }
288
283
  }
289
284
  exports.assertLocatorVisibleWithRetry = assertLocatorVisibleWithRetry;
290
- async function assertPageTextWithRetry(page, text, notVisible, timeout = 120000, maxRetries = 3) {
285
+ async function assertPageTextWithRetry(page, text, notVisible, timeout = 30000, maxRetries = 3) {
291
286
  for (let attempt = 0; attempt < maxRetries; attempt++) {
292
287
  try {
293
288
  await page.reload();
289
+ await page.waitForLoadState('domcontentloaded');
294
290
  if (notVisible == true) {
295
- await (0, sleep_1.sleep)(10000);
296
291
  await (0, test_1.expect)(page.getByText(text, { exact: true }).first()).not.toBeVisible({
297
292
  timeout: timeout,
298
293
  });
@@ -1,18 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.assertReportWithRefreshes = exports.createReportForProcess = void 0;
4
- const test_1 = require("@playwright/test");
5
4
  const UtilitiesPage_1 = require("../SM-8.10/UtilitiesPage");
6
5
  const UtilitiesPage_2 = require("../SM-8.10/UtilitiesPage");
7
6
  const createReportForProcess = async (optimizeCollectionsPage, optimizeReportPage, processName) => {
8
- let retries = 1000; // big number as this can struggle when many processes are running at once
9
- while (retries > 0) {
7
+ const maxRetries = 30;
8
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
10
9
  try {
11
10
  await optimizeCollectionsPage.clickCreateNewButton();
12
11
  await optimizeCollectionsPage.clickReportOption();
13
12
  await optimizeReportPage.clickProcessSelectionButton();
14
13
  await optimizeReportPage.waitUntilUserTaskProcessIsVisible(processName);
15
- break;
14
+ return;
16
15
  }
17
16
  catch (error) {
18
17
  try {
@@ -21,28 +20,26 @@ const createReportForProcess = async (optimizeCollectionsPage, optimizeReportPag
21
20
  catch (cancelError) {
22
21
  // Page may have been closed due to test timeout, ignore
23
22
  }
24
- await new Promise((resolve) => setTimeout(resolve, 5000));
23
+ await new Promise((resolve) => setTimeout(resolve, 2000));
25
24
  }
26
- retries--;
27
- (0, test_1.expect)(retries).toBeGreaterThan(0);
28
25
  }
26
+ throw new Error(`Failed to create report for process ${processName} after ${maxRetries} attempts`);
29
27
  };
30
28
  exports.createReportForProcess = createReportForProcess;
31
29
  const assertReportWithRefreshes = async (page, optimizeHomePage, optimizeCollectionsPage, optimizeReportPage, reportName, locator, text) => {
32
- let retries = 1000; // big number as this can struggle when many processes are running at once
33
- while (retries > 0) {
30
+ const maxRetries = 30;
31
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
34
32
  try {
35
33
  await optimizeHomePage.clickCollectionsLink();
36
34
  await (0, UtilitiesPage_1.assertPageTextWithRetry)(page, reportName, false);
37
35
  await optimizeCollectionsPage.clickMostRecentProcessReport(reportName);
38
36
  await (0, UtilitiesPage_2.assertLocatorVisibleWithRetry)(page, locator, text, 0);
39
- break;
37
+ return;
40
38
  }
41
39
  catch (error) {
42
40
  // nothing to do. Just loop back to the collections
43
41
  }
44
- retries--;
45
- (0, test_1.expect)(retries).toBeGreaterThan(0);
46
42
  }
43
+ throw new Error(`Failed to assert report ${reportName} after ${maxRetries} attempts`);
47
44
  };
48
45
  exports.assertReportWithRefreshes = assertReportWithRefreshes;
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IdentityTenantPage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  const sleep_1 = require("../../utils/sleep");
6
- const UtilitiesPage_1 = require("../SM-8.8/UtilitiesPage");
6
+ const expectLocatorWithPagination_1 = require("../../utils/assertionHelpers/expectLocatorWithPagination");
7
+ const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
7
8
  class IdentityTenantPage {
8
9
  page;
9
10
  createTenantMainButton;
@@ -43,7 +44,7 @@ class IdentityTenantPage {
43
44
  this.assignUsersButton = page.getByRole('button', { name: 'Assign users' });
44
45
  this.searchUsersInput = page.getByPlaceholder('Search users');
45
46
  this.assignUserFinalButton = page
46
- .getByLabel('Assign users')
47
+ .getByRole('dialog', { name: 'Assign users' })
47
48
  .getByRole('button', { name: 'Assign users' });
48
49
  this.removeUserButton = page.getByLabel('Remove user');
49
50
  this.removeButton = page.getByRole('button', { name: 'danger Remove' });
@@ -91,8 +92,11 @@ class IdentityTenantPage {
91
92
  await this.enterTenantIdInput.fill(tenantId);
92
93
  }
93
94
  async clickAssignedUsersTab() {
94
- await (0, test_1.expect)(this.assignedUsersTab).toBeVisible({ timeout: 60000 });
95
- await this.assignedUsersTab.click({ timeout: 60000 });
95
+ await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.assignedUsersTab, {
96
+ postAction: async () => {
97
+ await this.page.reload();
98
+ },
99
+ });
96
100
  }
97
101
  async clickAssignUsersButton() {
98
102
  await (0, test_1.expect)(this.assignUsersButton).toBeVisible({ timeout: 60000 });
@@ -108,13 +112,10 @@ class IdentityTenantPage {
108
112
  try {
109
113
  await (0, test_1.expect)(this.assignUserFinalButton).toBeVisible({ timeout: 60000 });
110
114
  await this.assignUserFinalButton.click();
111
- await (0, test_1.expect)(this.page.getByText('Users assigned')).toBeVisible();
115
+ await (0, test_1.expect)(this.page.getByText('Users assigned', { exact: true })).toBeVisible();
112
116
  }
113
117
  catch (e) {
114
- if (await this.page
115
- .getByText('ALREADY_EXISTS')
116
- .first()
117
- .isVisible({ timeout: 8000 })) {
118
+ if (await this.page.getByText('ALREADY_EXISTS').first().isVisible()) {
118
119
  console.log('Tenant is already assigned to tenant');
119
120
  await this.cancelButton.click();
120
121
  await (0, test_1.expect)(this.dialog).not.toBeVisible({ timeout: 15000 });
@@ -151,7 +152,7 @@ class IdentityTenantPage {
151
152
  try {
152
153
  await this.page.waitForLoadState('domcontentloaded').catch(() => { });
153
154
  const tenantRow = this.row(tenantName);
154
- await (0, UtilitiesPage_1.assertLocatorVisibleWithPaginated)(this.page, tenantRow, `Tenant with name ${tenantName} not found`);
155
+ await (0, expectLocatorWithPagination_1.expectLocatorWithPagination)(this.page, tenantRow);
155
156
  await tenantRow.locator('td').first().click({ timeout: 30000 });
156
157
  await this.usersTab.waitFor({ state: 'visible', timeout: 30000 });
157
158
  return;
@@ -185,7 +186,7 @@ class IdentityTenantPage {
185
186
  await this.clickSearchUsersInput();
186
187
  await this.fillSearchUsersInput(user);
187
188
  await (0, test_1.expect)(this.page.getByText(userEmail)).toBeVisible({ timeout: 30000 });
188
- await this.page.getByText(userEmail).click();
189
+ await this.page.getByText(userEmail).click({ timeout: 30000 });
189
190
  await this.clickAssignUserFinalButton();
190
191
  }
191
192
  async removeUserFromTenant(tenantName) {
@@ -29,6 +29,7 @@ class NavigationPage {
29
29
  this.optimizePageBanner = page.getByRole('link', {
30
30
  name: 'Camunda logo Optimize',
31
31
  });
32
+ // TODO: Drop support for Identity once we fully rename it to Admin
32
33
  this.identityPageBanner = page
33
34
  .locator('a')
34
35
  .filter({ hasText: /^Camunda logo\s*(Identity|Admin)$/ })
@@ -36,31 +37,39 @@ class NavigationPage {
36
37
  this.consolePageBanner = page.getByRole('link', {
37
38
  name: 'Camunda logo Console',
38
39
  });
39
- this.managementIdentityPageBanner = page.getByRole('link', {
40
- name: 'Camunda logo Management Identity',
41
- });
40
+ this.managementIdentityPageBanner = page
41
+ .locator('a')
42
+ .filter({ hasText: /^Camunda logo\s*Management Identity$/ })
43
+ .first();
42
44
  this.keyboardPageBanner = page.locator('#keycloak-bg');
43
45
  }
44
46
  async goTo(url, banner, sleepTimeout, { username = 'demo', password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD ??
45
47
  'demo', } = {}, maxRetries = 3) {
46
48
  const startTime = Date.now();
47
- let timeout = constants_1._1_SECOND_IN_MS * 1;
49
+ let timeout = constants_1._1_SECOND_IN_MS * 10;
48
50
  if (url === '/modeler') {
49
- timeout = constants_1._1_SECOND_IN_MS * 10;
51
+ timeout = constants_1._1_SECOND_IN_MS * 20;
50
52
  }
51
53
  for (let attempt = 0; attempt < maxRetries; attempt++) {
52
54
  try {
53
55
  if (sleepTimeout) {
54
56
  await (0, sleep_1.sleep)(sleepTimeout);
55
57
  }
56
- await this.page.goto(url, { timeout: 10000 });
58
+ await this.page.goto(url, {
59
+ timeout: 30000,
60
+ waitUntil: 'domcontentloaded',
61
+ });
57
62
  const loginPage = new LoginPage_1.LoginPage(this.page);
58
- const loginSelector = loginPage.usernameInput;
59
- await (0, test_1.expect)(banner.or(loginSelector)).toBeVisible();
60
- const isBannerVisible = await banner.isVisible();
63
+ const loginEntryPoint = banner
64
+ .or(loginPage.usernameInput)
65
+ .or(loginPage.coreUsernameInput)
66
+ .or(loginPage.keycloakBanner)
67
+ .first();
68
+ await (0, test_1.expect)(loginEntryPoint).toBeVisible({ timeout: 30000 });
69
+ const isBannerVisible = await banner.isVisible().catch(() => false);
61
70
  if (isBannerVisible) {
62
71
  try {
63
- await (0, test_1.expect)(loginSelector).toBeVisible({ timeout: 5000 });
72
+ await (0, test_1.expect)(loginPage.usernameInput).toBeVisible({ timeout: 5000 });
64
73
  await loginPage.login(username, password);
65
74
  }
66
75
  catch (error) {
@@ -71,6 +80,7 @@ class NavigationPage {
71
80
  else {
72
81
  await loginPage.login(username, password);
73
82
  }
83
+ await (0, test_1.expect)(banner).toBeVisible({ timeout: 60000 });
74
84
  return;
75
85
  }
76
86
  catch (error) {
@@ -160,7 +160,8 @@ class OCIdentityRolesPage {
160
160
  await this.clickAssignUserSubButton();
161
161
  }
162
162
  async clickAssignUserButton() {
163
- await this.assignUserButton.click();
163
+ await (0, test_1.expect)(this.assignUserButton).toBeVisible({ timeout: 60000 });
164
+ await this.assignUserButton.click({ timeout: 60000 });
164
165
  }
165
166
  async clickUsernameTextbox() {
166
167
  await this.usernameTextBox.click();
@@ -172,6 +173,7 @@ class OCIdentityRolesPage {
172
173
  await this.assignUserSubButton.click();
173
174
  }
174
175
  async clickAdminRole() {
176
+ await (0, test_1.expect)(this.adminRole).toBeVisible({ timeout: 60000 });
175
177
  await this.adminRole.click();
176
178
  }
177
179
  async clickClientsTab() {
@@ -24,6 +24,7 @@ declare class OCTenantPage {
24
24
  readonly roleIdSearchBox: Locator;
25
25
  readonly assignRoleSubButton: Locator;
26
26
  readonly cancelButton: Locator;
27
+ readonly gotItButton: Locator;
27
28
  readonly row: (name: string) => Locator;
28
29
  constructor(page: Page);
29
30
  clickCreateTenantMainButton(): Promise<void>;
@@ -44,6 +45,7 @@ declare class OCTenantPage {
44
45
  createTenant(tenantName: string): Promise<void>;
45
46
  assertTenantCreated(): Promise<void>;
46
47
  clickCancelButton(): Promise<void>;
48
+ clickGotItButton(): Promise<void>;
47
49
  clickTenant(tenantName: string): Promise<void>;
48
50
  assignUserToTenant(user: string): Promise<void>;
49
51
  removeUserFromTenant(tenantName: string): Promise<void>;
@@ -29,6 +29,7 @@ class OCTenantPage {
29
29
  roleIdSearchBox;
30
30
  assignRoleSubButton;
31
31
  cancelButton;
32
+ gotItButton;
32
33
  row;
33
34
  constructor(page) {
34
35
  this.page = page;
@@ -77,6 +78,7 @@ class OCTenantPage {
77
78
  this.cancelButton = page
78
79
  .getByRole('dialog')
79
80
  .getByRole('button', { name: 'Cancel' });
81
+ this.gotItButton = page.getByRole('button', { name: 'Got it' });
80
82
  this.row = (name) => this.page.getByRole('row').filter({ hasText: name }).first();
81
83
  }
82
84
  async clickCreateTenantMainButton() {
@@ -115,10 +117,7 @@ class OCTenantPage {
115
117
  await (0, test_1.expect)(this.page.getByRole('dialog')).not.toBeVisible();
116
118
  }
117
119
  catch (e) {
118
- if (await this.page
119
- .getByText('ALREADY_EXISTS')
120
- .first()
121
- .isVisible({ timeout: 10000 })) {
120
+ if (await this.page.getByText('ALREADY_EXISTS').first().isVisible()) {
122
121
  console.log('User is already assigned to tenant');
123
122
  await this.clickCancelButton();
124
123
  }
@@ -152,25 +151,32 @@ class OCTenantPage {
152
151
  }
153
152
  async assertTenantCreated() {
154
153
  try {
155
- await (0, test_1.expect)(this.page.getByText('Tenant created')).toBeVisible({
154
+ await (0, test_1.expect)(this.page.getByText('successfully created')).toBeVisible({
156
155
  timeout: 8000,
157
156
  });
157
+ // "Got it" button appears in some versions but not others
158
+ try {
159
+ await this.clickGotItButton();
160
+ }
161
+ catch {
162
+ // Button not present in this version, continue
163
+ }
158
164
  }
159
165
  catch (error) {
160
- if (await this.page
161
- .getByText('ALREADY_EXISTS')
162
- .first()
163
- .isVisible({ timeout: 8000 })) {
166
+ if (await this.page.getByText('ALREADY_EXISTS').first().isVisible()) {
164
167
  await this.clickCancelButton();
165
168
  }
166
169
  else {
167
- throw new Error('Assigning user to tenant failed' + error);
170
+ throw new Error('Creating tenant failed' + error);
168
171
  }
169
172
  }
170
173
  }
171
174
  async clickCancelButton() {
172
175
  await this.cancelButton.click({ timeout: 30000 });
173
176
  }
177
+ async clickGotItButton() {
178
+ await this.gotItButton.click({ timeout: 30000 });
179
+ }
174
180
  async clickTenant(tenantName) {
175
181
  const maxRetries = 10;
176
182
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
@@ -6,6 +6,7 @@ const _setup_1 = require("../../test-setup.js");
6
6
  const UtilitiesPage_1 = require("../../pages/SM-8.8/UtilitiesPage");
7
7
  const resetSession_1 = require("../../utils/resetSession");
8
8
  const expectTextWithRetry_1 = require("../../utils/assertionHelpers/expectTextWithRetry");
9
+ const expectLocatorWithRetry_1 = require("../../utils/assertionHelpers/expectLocatorWithRetry");
9
10
  const demoUserEmail = process.env.DEMO_USER_EMAIL || 'demo@example.org';
10
11
  const demoUserDisplayText = `Demo User${demoUserEmail}`;
11
12
  if (process.env.IS_MT === 'true') {
@@ -49,7 +50,7 @@ if (process.env.IS_MT === 'true') {
49
50
  });
50
51
  await SM_8_8_1.test.step('Open Cross Component Test Project', async () => {
51
52
  await navigationPage.goToModeler();
52
- await modelerHomePage.clickCrossComponentProjectFolder();
53
+ await modelerHomePage.createCrossComponentProjectFolder();
53
54
  await modelerHomePage.clickDiagramTypeDropdown();
54
55
  await modelerHomePage.clickBpmnTemplateOption();
55
56
  });
@@ -490,7 +491,7 @@ if (process.env.IS_MT === 'true') {
490
491
  });
491
492
  await SM_8_8_1.test.step('Open Cross Component Test Project', async () => {
492
493
  await navigationPage.goToModeler();
493
- await modelerHomePage.clickCrossComponentProjectFolder();
494
+ await modelerHomePage.createCrossComponentProjectFolder();
494
495
  await modelerHomePage.clickDiagramTypeDropdown();
495
496
  await modelerHomePage.clickBpmnTemplateOption();
496
497
  });
@@ -531,6 +532,11 @@ if (process.env.IS_MT === 'true') {
531
532
  }
532
533
  await SM_8_8_1.test.step('Delete Tenant Access For Demo User OC', async () => {
533
534
  await navigationPage.goToOCIdentity();
535
+ await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(page, ocIdentityHomePage.tenantsTab, {
536
+ postAction: async () => {
537
+ await navigationPage.goToOCIdentity();
538
+ },
539
+ });
534
540
  await ocIdentityHomePage.clickTenantsTab();
535
541
  await ocTenantPage.removeUserFromTenant(tenantName);
536
542
  });
@@ -12,13 +12,10 @@ const expectLocatorWithRetry = async (page, item, options) => {
12
12
  await options?.preAction();
13
13
  }
14
14
  await page.waitForLoadState('domcontentloaded');
15
- await Promise.race([
16
- item.waitFor({
17
- state: shouldBeVisible ? 'visible' : 'hidden',
18
- timeout: visibilityTimeout,
19
- }),
20
- new Promise((_, reject) => setTimeout(() => reject(new Error('Visibility timeout')), visibilityTimeout)),
21
- ]);
15
+ await item.waitFor({
16
+ state: shouldBeVisible ? 'visible' : 'hidden',
17
+ timeout: visibilityTimeout,
18
+ });
22
19
  return;
23
20
  }
24
21
  catch (err) {
@@ -4,11 +4,8 @@ exports.resetSessionAll = exports.resetSession = void 0;
4
4
  async function resetSession(browser, page) {
5
5
  const context = browser.contexts()[0];
6
6
  await context.clearCookies();
7
- await page.evaluate(() => {
8
- localStorage.clear();
9
- sessionStorage.clear();
10
- });
11
7
  await page.reload();
8
+ await page.waitForLoadState('domcontentloaded');
12
9
  await page.goto('/');
13
10
  }
14
11
  exports.resetSession = resetSession;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.478",
3
+ "version": "0.0.480",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",