@camunda/e2e-test-suite 0.0.451 → 0.0.453

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.
Files changed (38) hide show
  1. package/dist/pages/SM-8.10/ClusterPage.js +1 -0
  2. package/dist/pages/SM-8.10/ManagementIdentityPage.js +4 -3
  3. package/dist/pages/SM-8.10/ModelerCreatePage.d.ts +1 -0
  4. package/dist/pages/SM-8.10/ModelerCreatePage.js +48 -20
  5. package/dist/pages/SM-8.10/NavigationPage.js +29 -17
  6. package/dist/pages/SM-8.10/OCIdentityHomePage.js +4 -3
  7. package/dist/pages/SM-8.10/OCTenantPage.js +3 -5
  8. package/dist/pages/SM-8.10/OperateHomePage.js +4 -2
  9. package/dist/pages/SM-8.10/OperateProcessesPage.d.ts +1 -0
  10. package/dist/pages/SM-8.10/OperateProcessesPage.js +18 -23
  11. package/dist/pages/SM-8.10/TaskPanelPage.js +2 -3
  12. package/dist/pages/SM-8.8/ModelerCreatePage.d.ts +1 -0
  13. package/dist/pages/SM-8.8/ModelerCreatePage.js +22 -20
  14. package/dist/pages/SM-8.8/OCTenantPage.js +3 -5
  15. package/dist/pages/SM-8.8/OperateHomePage.js +1 -1
  16. package/dist/pages/SM-8.8/OperateProcessesPage.js +3 -3
  17. package/dist/pages/SM-8.8/TaskPanelPage.js +2 -2
  18. package/dist/pages/SM-8.9/ClusterPage.js +1 -0
  19. package/dist/pages/SM-8.9/ManagementIdentityPage.js +4 -3
  20. package/dist/pages/SM-8.9/ModelerCreatePage.d.ts +1 -0
  21. package/dist/pages/SM-8.9/ModelerCreatePage.js +52 -20
  22. package/dist/pages/SM-8.9/NavigationPage.js +29 -17
  23. package/dist/pages/SM-8.9/OCIdentityHomePage.js +4 -3
  24. package/dist/pages/SM-8.9/OCTenantPage.js +3 -5
  25. package/dist/pages/SM-8.9/OperateHomePage.js +33 -8
  26. package/dist/pages/SM-8.9/OperateProcessesPage.js +5 -3
  27. package/dist/pages/SM-8.9/TaskPanelPage.js +2 -3
  28. package/dist/tests/SM-8.10/connectors-user-flows.spec.js +15 -8
  29. package/dist/tests/SM-8.10/hto-user-flows.spec.js +7 -6
  30. package/dist/tests/SM-8.10/mt-enabled-user-flows.spec.js +41 -38
  31. package/dist/tests/SM-8.10/rba-enabled-user-flows.spec.js +0 -7
  32. package/dist/tests/SM-8.8/connectors-user-flows.spec.js +14 -6
  33. package/dist/tests/SM-8.8/migration-path-user-flows.spec.js +3 -3
  34. package/dist/tests/SM-8.8/mt-enabled-user-flows.spec.js +40 -38
  35. package/dist/tests/SM-8.9/connectors-user-flows.spec.js +15 -8
  36. package/dist/tests/SM-8.9/mt-enabled-user-flows.spec.js +40 -38
  37. package/dist/utils/resetSession.js +4 -2
  38. package/package.json +1 -1
@@ -22,6 +22,7 @@ class ClusterPage {
22
22
  });
23
23
  }
24
24
  async assertCustomTagsAreVisible(tags) {
25
+ await this.page.waitForLoadState('networkidle');
25
26
  for (const tag of tags) {
26
27
  await (0, test_1.expect)(this.clustersList.getByText(tag, { exact: true })).toBeVisible({
27
28
  timeout: 60000,
@@ -28,9 +28,10 @@ class ManagementIdentityPage {
28
28
  orchestrationCheckbox;
29
29
  constructor(page) {
30
30
  this.page = page;
31
- this.identityBanner = page.getByRole('link', {
32
- name: 'Camunda logo Management Identity',
33
- });
31
+ this.identityBanner = page
32
+ .locator('a')
33
+ .filter({ hasText: /^Camunda logo\s*Management Identity$/ })
34
+ .first();
34
35
  this.usersLink = page.locator('a').filter({ hasText: 'Users' });
35
36
  this.tenantTab = page
36
37
  .getByRole('link', { name: 'Tenants' })
@@ -134,6 +134,7 @@ declare class ModelerCreatePage {
134
134
  clickDeployButton(): Promise<void>;
135
135
  clickDeploySubButton(): Promise<void>;
136
136
  clickCancelButton(): Promise<void>;
137
+ private recoverModelerSession;
137
138
  clickRestConnectorOption(): Promise<void>;
138
139
  clickMarketPlaceButton(): Promise<void>;
139
140
  completeDeploymentEndpointConfiguration(): Promise<void>;
@@ -334,6 +334,7 @@ class ModelerCreatePage {
334
334
  .click({ timeout: 90000 });
335
335
  }
336
336
  async runProcessInstance(variables = '', tenant = '') {
337
+ await this.page.waitForTimeout(2000); // the canvas autosaves. This can take a second to save.
337
338
  const maxRetries = 3;
338
339
  for (let attempt = 0; attempt < maxRetries; attempt++) {
339
340
  try {
@@ -608,29 +609,48 @@ class ModelerCreatePage {
608
609
  async clickCancelButton() {
609
610
  await this.cancelButton.click();
610
611
  }
612
+ async recoverModelerSession() {
613
+ const url = this.page.url().split('?')[0];
614
+ await this.page.context().clearCookies();
615
+ await this.page.goto(url, { timeout: 30000, waitUntil: 'domcontentloaded' });
616
+ const username = process.env.DEMO_USER_EMAIL || 'demo';
617
+ const password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD || 'demo';
618
+ const loginInput = this.page.locator('#username');
619
+ if (await loginInput.isVisible({ timeout: 5000 }).catch(() => false)) {
620
+ await loginInput.fill(username);
621
+ await this.page.locator('#password').fill(password);
622
+ await this.page.locator('#kc-login').click();
623
+ }
624
+ await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
625
+ }
611
626
  async clickRestConnectorOption() {
612
627
  const maxRetries = 4;
613
628
  for (let retries = 0; retries < maxRetries; retries++) {
614
629
  try {
615
630
  if (retries === 0) {
616
631
  // First attempt
617
- await this.restConnectorOption.click({ timeout: 90000 });
632
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 60000 });
633
+ await this.restConnectorOption.click({ timeout: 60000 });
618
634
  }
619
635
  else if (retries === 1 || retries === 2) {
620
- // Second or third attempt
621
- await this.page.reload();
636
+ // Recover session cleanly instead of page.reload()
637
+ await this.recoverModelerSession();
622
638
  await this.secondElement.click({ timeout: 60000 });
623
639
  await this.changeTypeButton.click({ force: true, timeout: 60000 });
640
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
624
641
  await this.restConnectorOption.click({ timeout: 90000 });
625
642
  }
626
643
  else {
627
- // Forth and subsequent attempts
644
+ // Fourth attempt: install via marketplace (real product flow)
645
+ await this.recoverModelerSession();
646
+ await this.secondElement.click({ timeout: 60000 });
647
+ await this.changeTypeButton.click({ force: true, timeout: 60000 });
628
648
  await this.clickMarketPlaceButton();
629
- const connectorMarketplacePage = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
630
- await connectorMarketplacePage.clickSearchForConnectorTextbox();
649
+ const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
650
+ await marketplace.clickSearchForConnectorTextbox();
631
651
  await (0, sleep_1.sleep)(5000);
632
- await connectorMarketplacePage.fillSearchForConnectorTextbox('REST Connector');
633
- await connectorMarketplacePage.downloadConnectorToProject();
652
+ await marketplace.fillSearchForConnectorTextbox('REST Connector');
653
+ await marketplace.downloadConnectorToProject();
634
654
  await this.restConnectorOption.click({ timeout: 120000 });
635
655
  }
636
656
  return;
@@ -863,18 +883,26 @@ class ModelerCreatePage {
863
883
  await this.intermediateBoundaryEvent.click({ timeout: 60000 });
864
884
  }
865
885
  async clickIntermediateWebhookConnectorOption() {
866
- try {
867
- await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
868
- timeout: 20000,
869
- });
870
- await this.intermediateWebhookConnectorOption.click();
871
- }
872
- catch (error) {
873
- await this.page.reload();
874
- await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 20000 });
875
- await this.secondElement.click();
876
- await this.changeTypeButton.click({ force: true });
877
- await this.intermediateWebhookConnectorOption.click();
886
+ const max = 3;
887
+ for (let i = 0; i < max; i++) {
888
+ try {
889
+ await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
890
+ timeout: 30000,
891
+ });
892
+ await this.intermediateWebhookConnectorOption.click({ timeout: 30000 });
893
+ return;
894
+ }
895
+ catch (err) {
896
+ console.error(`clickIntermediateWebhookConnectorOption attempt ${i + 1} failed: ${err}`);
897
+ if (i === max - 1)
898
+ throw err;
899
+ await this.page.reload();
900
+ await this.page.waitForLoadState('networkidle');
901
+ // Wait for modeler canvas to render after reload before re-selecting
902
+ await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
903
+ await this.secondElement.click({ force: true, timeout: 30000 });
904
+ await this.changeTypeButton.click({ force: true, timeout: 30000 });
905
+ }
878
906
  }
879
907
  }
880
908
  async clickCorrelationKeyProcessInput() {
@@ -6,6 +6,9 @@ const LoginPage_1 = require("./LoginPage");
6
6
  const sleep_1 = require("../../utils/sleep");
7
7
  const constants_1 = require("../../utils/constants");
8
8
  const ORCHESTRATION_CONTEXT_PATH = process.env.ORCHESTRATION_CONTEXT_PATH ?? '/orchestration';
9
+ const NORMALIZED_ORCHESTRATION_CONTEXT_PATH = ORCHESTRATION_CONTEXT_PATH.startsWith('/')
10
+ ? ORCHESTRATION_CONTEXT_PATH
11
+ : `/${ORCHESTRATION_CONTEXT_PATH}`;
9
12
  const MODELER_CONTEXT_PATH = process.env.MODELER_CONTEXT_PATH ?? '/modeler';
10
13
  const OPTIMIZE_CONTEXT_PATH = process.env.OPTIMIZE_CONTEXT_PATH ?? '/optimize';
11
14
  const CONSOLE_CONTEXT_PATH = process.env.CONSOLE_CONTEXT_PATH ?? '/console';
@@ -37,36 +40,45 @@ class NavigationPage {
37
40
  name: 'Camunda logo Optimize',
38
41
  });
39
42
  // TODO: Drop support for Identity once we fully rename it to Admin
40
- this.identityPageBanner = page.getByRole('link', {
41
- name: /Camunda logo (Identity|Admin)/,
42
- });
43
+ this.identityPageBanner = page
44
+ .locator('a')
45
+ .filter({ hasText: /^Camunda logo\s*(Identity|Admin)$/ })
46
+ .first();
43
47
  this.consolePageBanner = page.getByRole('link', {
44
48
  name: 'Camunda logo Console',
45
49
  });
46
- this.managementIdentityPageBanner = page.getByRole('link', {
47
- name: 'Camunda logo Management Identity',
48
- });
50
+ this.managementIdentityPageBanner = page
51
+ .locator('a')
52
+ .filter({ hasText: /^Camunda logo\s*Management Identity$/ })
53
+ .first();
49
54
  this.keyboardPageBanner = page.locator('#keycloak-bg');
50
55
  }
51
56
  async goTo(url, banner, sleepTimeout, { username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}, maxRetries = 3) {
52
57
  const startTime = Date.now();
53
- let timeout = constants_1._1_SECOND_IN_MS * 1;
58
+ let timeout = constants_1._1_SECOND_IN_MS * 10;
54
59
  if (url === '/modeler') {
55
- timeout = constants_1._1_SECOND_IN_MS * 10;
60
+ timeout = constants_1._1_SECOND_IN_MS * 20;
56
61
  }
57
62
  for (let attempt = 0; attempt < maxRetries; attempt++) {
58
63
  try {
59
64
  if (sleepTimeout) {
60
65
  await (0, sleep_1.sleep)(sleepTimeout);
61
66
  }
62
- await this.page.goto(url, { timeout: 10000 });
67
+ await this.page.goto(url, {
68
+ timeout: 30000,
69
+ waitUntil: 'domcontentloaded',
70
+ });
63
71
  const loginPage = new LoginPage_1.LoginPage(this.page);
64
- const loginSelector = loginPage.usernameInput;
65
- await (0, test_1.expect)(banner.or(loginSelector)).toBeVisible({ timeout: 15000 });
66
- const isBannerVisible = await banner.isVisible();
72
+ const loginEntryPoint = banner
73
+ .or(loginPage.usernameInput)
74
+ .or(loginPage.coreUsernameInput)
75
+ .or(loginPage.keycloakBanner)
76
+ .first();
77
+ await (0, test_1.expect)(loginEntryPoint).toBeVisible({ timeout: 30000 });
78
+ const isBannerVisible = await banner.isVisible().catch(() => false);
67
79
  if (isBannerVisible) {
68
80
  try {
69
- await (0, test_1.expect)(loginSelector).toBeVisible({ timeout: 5000 });
81
+ await (0, test_1.expect)(loginPage.usernameInput).toBeVisible({ timeout: 5000 });
70
82
  await loginPage.login(username, password);
71
83
  }
72
84
  catch (error) {
@@ -77,7 +89,7 @@ class NavigationPage {
77
89
  else {
78
90
  await loginPage.login(username, password);
79
91
  }
80
- await (0, test_1.expect)(banner).toBeVisible();
92
+ await (0, test_1.expect)(banner).toBeVisible({ timeout: 60000 });
81
93
  return;
82
94
  }
83
95
  catch (error) {
@@ -107,10 +119,10 @@ class NavigationPage {
107
119
  await this.goTo(MODELER_CONTEXT_PATH, this.modelerPageBanner, sleepTimeout, credentials);
108
120
  }
109
121
  async goToTasklist(sleepTimeout, credentials) {
110
- await this.goTo(`${ORCHESTRATION_CONTEXT_PATH}/tasklist`, this.tasklistPageBanner, sleepTimeout, credentials);
122
+ await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/tasklist`, this.tasklistPageBanner, sleepTimeout, credentials);
111
123
  }
112
124
  async goToOperate(sleepTimeout, credentials) {
113
- await this.goTo(`${ORCHESTRATION_CONTEXT_PATH}/operate`, this.operatePageBanner, sleepTimeout, credentials);
125
+ await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/operate`, this.operatePageBanner, sleepTimeout, credentials);
114
126
  }
115
127
  async goToOptimize(sleepTimeout, credentials) {
116
128
  await this.goTo(OPTIMIZE_CONTEXT_PATH, this.optimizePageBanner, sleepTimeout, credentials);
@@ -123,7 +135,7 @@ class NavigationPage {
123
135
  await (0, test_1.expect)(this.keyboardPageBanner).toBeVisible({ timeout: 30000 });
124
136
  }
125
137
  async goToOCAdmin(sleepTimeout, credentials) {
126
- await this.goTo(`${ORCHESTRATION_CONTEXT_PATH}/admin`, this.identityPageBanner, sleepTimeout, credentials);
138
+ await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/admin`, this.identityPageBanner, sleepTimeout, credentials);
127
139
  }
128
140
  async goToConsole(sleepTimeout, credentials) {
129
141
  await this.goTo(CONSOLE_CONTEXT_PATH, this.consolePageBanner, sleepTimeout, credentials);
@@ -18,9 +18,10 @@ class OCIdentityHomePage {
18
18
  licenseKeyTagCommercial;
19
19
  constructor(page) {
20
20
  this.page = page;
21
- this.adminBanner = page.getByRole('link', {
22
- name: 'Camunda logo Admin',
23
- });
21
+ this.adminBanner = page
22
+ .locator('a')
23
+ .filter({ hasText: /^Camunda logo\s*Admin$/ })
24
+ .first();
24
25
  this.groupsTab = page
25
26
  .getByRole('banner')
26
27
  .locator('a')
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OCTenantPage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- const sleep_1 = require("../../utils/sleep");
6
5
  const findLocatorInPaginatedList_1 = require("../../utils/findLocatorInPaginatedList");
7
6
  const expectTextWithPagination_1 = require("../../utils/assertionHelpers/expectTextWithPagination");
8
7
  class OCTenantPage {
@@ -149,7 +148,6 @@ class OCTenantPage {
149
148
  await this.fillTenantDescriptionInput('This is a test');
150
149
  await this.clickCreateTenantSubButton();
151
150
  await this.assertTenantCreated();
152
- await (0, sleep_1.sleep)(30000);
153
151
  }
154
152
  async assertTenantCreated() {
155
153
  try {
@@ -178,7 +176,7 @@ class OCTenantPage {
178
176
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
179
177
  try {
180
178
  await this.page.reload();
181
- await (0, sleep_1.sleep)(10000);
179
+ await this.page.waitForLoadState('networkidle');
182
180
  const tenant = this.page.getByText(tenantName).first();
183
181
  await (0, findLocatorInPaginatedList_1.findLocatorInPaginatedList)(this.page, tenant);
184
182
  await tenant.click({
@@ -259,14 +257,14 @@ class OCTenantPage {
259
257
  }
260
258
  async fillRoleIdSearchBox(roleId, roleIdentifier) {
261
259
  await this.roleIdSearchBox.fill(roleId);
262
- await this.page.getByText(roleIdentifier).click();
260
+ await this.page.getByText(roleIdentifier).click({ force: true });
263
261
  }
264
262
  async clickAssignRoleSubButton() {
265
263
  await this.assignRoleSubButton.click();
266
264
  }
267
265
  async assignRoleToTenant(roleId, roleIdentifier) {
268
266
  await this.clickRolesTab();
269
- await (0, sleep_1.sleep)(1000);
267
+ await this.page.waitForLoadState('networkidle');
270
268
  if (await this.row(roleId).isVisible()) {
271
269
  console.log(`Role ${roleId} is already assigned to tenant`);
272
270
  return;
@@ -50,7 +50,7 @@ class OperateHomePage {
50
50
  }
51
51
  async clickProcessesTab() {
52
52
  await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.processesTab, {
53
- totalTimeout: 20000,
53
+ totalTimeout: 60000,
54
54
  });
55
55
  await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.processPageHeading, {
56
56
  preAction: async () => {
@@ -66,7 +66,9 @@ class OperateHomePage {
66
66
  }
67
67
  async clickEditVariableButton(variableName) {
68
68
  const editVariableButton = 'variable-' + variableName;
69
- await this.page.getByTestId(editVariableButton).getByLabel('Edit').click();
69
+ const button = this.page.getByTestId(editVariableButton).getByLabel('Edit');
70
+ await (0, test_1.expect)(button).toBeVisible({ timeout: 30000 });
71
+ await button.click();
70
72
  }
71
73
  async clickVariableValueInput() {
72
74
  await this.variableValueInput.click();
@@ -20,6 +20,7 @@ declare class OperateProcessesPage {
20
20
  private uncheckActiveCheckbox;
21
21
  private toggleActiveCheckboxOn;
22
22
  private toggleCompletedCheckbox;
23
+ private applyProcessStateFilter;
23
24
  private checkTableForProcess;
24
25
  clickProcessActiveCheckbox(): Promise<void>;
25
26
  clickProcessCompletedCheckbox(): Promise<void>;
@@ -109,18 +109,26 @@ class OperateProcessesPage {
109
109
  await (0, sleep_1.sleep)(200);
110
110
  }
111
111
  }
112
+ async applyProcessStateFilter(type) {
113
+ if (type === 'active') {
114
+ await this.toggleActiveCheckboxOn();
115
+ }
116
+ else {
117
+ await this.toggleCompletedCheckbox();
118
+ }
119
+ }
112
120
  async checkTableForProcess(processName) {
113
121
  try {
114
122
  const processTable = this.page.locator('[aria-label="Process Instances Panel"]');
115
123
  await (0, test_1.expect)(processTable).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 4 });
116
- const timeout = env_1.isOpenSearch ? constants_1._1_SECOND_IN_MS * 10 : constants_1._100_MS * 2;
124
+ const timeout = env_1.isOpenSearch ? constants_1._1_MINUTE_IN_MS : constants_1._1_SECOND_IN_MS * 20;
117
125
  const row = this.page.locator(`tr:has-text("${processName}")`).first();
118
126
  await (0, test_1.expect)(row).toBeVisible({ timeout });
119
127
  const link = row.locator('a').first();
120
- await (0, test_1.expect)(link).toBeVisible({ timeout: constants_1._100_MS * 2 });
128
+ await (0, test_1.expect)(link).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 2 });
121
129
  await link.scrollIntoViewIfNeeded();
122
- await link.click({ timeout: constants_1._100_MS * 2 });
123
- await (0, test_1.expect)(this.page.getByText('Instance History').first()).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 4 });
130
+ await link.click({ timeout: constants_1._1_SECOND_IN_MS * 2 });
131
+ await (0, test_1.expect)(this.page.getByText('Instance History').first()).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 10 });
124
132
  if (await this.whatsNewPopUp.isVisible()) {
125
133
  await this.gotItButton.click();
126
134
  }
@@ -193,22 +201,15 @@ class OperateProcessesPage {
193
201
  });
194
202
  }
195
203
  async clickProcessInstanceLink(processName, type = 'active') {
204
+ await this.applyProcessStateFilter(type);
196
205
  if (await this.checkTableForProcess(processName)) {
197
206
  return;
198
207
  }
199
- const MAX_ATTEMPTS = 100;
200
- const TOTAL_TIMEOUT_MS = constants_1._1_MINUTE_IN_MS * 4;
208
+ const MAX_ATTEMPTS = 30;
209
+ const TOTAL_TIMEOUT_MS = constants_1._1_MINUTE_IN_MS * 6;
201
210
  let attempt = 0;
202
211
  let lastError;
203
212
  const startTime = Date.now();
204
- if (type === 'active') {
205
- await this.toggleActiveCheckboxOn();
206
- }
207
- else {
208
- await this.toggleCompletedCheckbox();
209
- }
210
- // Capture URL after filters are applied so we can navigate back here
211
- // if a reload redirects away from Operate.
212
213
  const operateUrl = this.page.url();
213
214
  while (Date.now() - startTime < TOTAL_TIMEOUT_MS &&
214
215
  attempt < MAX_ATTEMPTS) {
@@ -222,15 +223,14 @@ class OperateProcessesPage {
222
223
  catch (err) {
223
224
  lastError = err instanceof Error ? err.message : err;
224
225
  console.log(`clickProcessInstanceLink attempt ${attempt}: ${String(lastError)}`);
226
+ await (0, sleep_1.sleep)(constants_1._1_SECOND_IN_MS * 3);
225
227
  await this.page
226
228
  .reload({ timeout: 30000 })
227
229
  .catch(() => console.log('Page reload timed out, continuing...'));
228
230
  await this.page
229
231
  .waitForLoadState('networkidle', { timeout: 30000 })
230
232
  .catch(() => console.log('waitForLoadState networkidle timed out, continuing...'));
231
- // After reload, the page may redirect away from Operate (e.g. to
232
- // Tasklist). Navigate back to the original Operate URL if that
233
- // happens.
233
+ // After reload, the page may redirect away from Operate
234
234
  if (!this.page.url().includes('/operate')) {
235
235
  await this.page
236
236
  .goto(operateUrl, { timeout: 30000 })
@@ -241,12 +241,7 @@ class OperateProcessesPage {
241
241
  }
242
242
  // Re-apply checkbox filter lost after reload
243
243
  try {
244
- if (type === 'active') {
245
- await this.toggleActiveCheckboxOn();
246
- }
247
- else {
248
- await this.toggleCompletedCheckbox();
249
- }
244
+ await this.applyProcessStateFilter(type);
250
245
  }
251
246
  catch (toggleErr) {
252
247
  console.log(`Checkbox toggle failed after reload: ${String(toggleErr)}`);
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TaskPanelPage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- const sleep_1 = require("../../utils/sleep");
6
5
  const constants_1 = require("../../utils/constants");
7
6
  class TaskPanelPage {
8
7
  page;
@@ -56,7 +55,7 @@ class TaskPanelPage {
56
55
  if (attempt < 30) {
57
56
  console.warn(`Attempt ${attempt} failed. Reloading page...`);
58
57
  await this.page.reload();
59
- await (0, sleep_1.sleep)(2000);
58
+ await this.page.waitForLoadState('networkidle');
60
59
  }
61
60
  else {
62
61
  throw new Error(`Failed to open task "${name}" after ${attempt} attempts: ${error}`);
@@ -85,7 +84,7 @@ class TaskPanelPage {
85
84
  await this.processesPageTab.click();
86
85
  }
87
86
  async taskCount(name) {
88
- await (0, sleep_1.sleep)(50000);
87
+ await this.page.waitForLoadState('networkidle');
89
88
  return this.availableTasks.getByText(name, { exact: true }).count();
90
89
  }
91
90
  async clickTasksTab() {
@@ -134,6 +134,7 @@ declare class ModelerCreatePage {
134
134
  clickDeployButton(): Promise<void>;
135
135
  clickDeploySubButton(): Promise<void>;
136
136
  clickCancelButton(): Promise<void>;
137
+ private recoverModelerSession;
137
138
  clickRestConnectorOption(): Promise<void>;
138
139
  clickMarketPlaceButton(): Promise<void>;
139
140
  completeDeploymentEndpointConfiguration(): Promise<void>;
@@ -601,36 +601,38 @@ class ModelerCreatePage {
601
601
  async clickCancelButton() {
602
602
  await this.cancelButton.click();
603
603
  }
604
+ async recoverModelerSession() {
605
+ const url = this.page.url().split('?')[0];
606
+ await this.page.context().clearCookies();
607
+ await this.page.goto(url, { timeout: 30000, waitUntil: 'domcontentloaded' });
608
+ const username = process.env.DEMO_USER_EMAIL || 'demo';
609
+ const password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD || 'demo';
610
+ const loginInput = this.page.locator('#username');
611
+ if (await loginInput.isVisible({ timeout: 5000 }).catch(() => false)) {
612
+ await loginInput.fill(username);
613
+ await this.page.locator('#password').fill(password);
614
+ await this.page.locator('#kc-login').click();
615
+ }
616
+ await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
617
+ }
604
618
  async clickRestConnectorOption() {
605
619
  const maxRetries = 4;
606
620
  for (let retries = 0; retries < maxRetries; retries++) {
607
621
  try {
608
622
  if (retries === 0) {
609
- // If the change type panel is not showing the connector (e.g. after
610
- // visiting the marketplace), reopen it before waiting for the option.
611
- const isAlreadyVisible = await this.restConnectorOption.isVisible();
612
- if (!isAlreadyVisible) {
613
- await this.changeTypeButton.click({ force: true, timeout: 30000 });
614
- }
623
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 60000 });
624
+ await this.restConnectorOption.scrollIntoViewIfNeeded();
625
+ await this.restConnectorOption.click({ timeout: 60000, force: true });
615
626
  }
616
627
  else {
617
- // Reload to pick up newly-downloaded connector templates, then
618
- // re-select the task element and open the type picker.
619
- await this.page.reload();
628
+ // Recover session cleanly instead of page.reload()
629
+ await this.recoverModelerSession();
620
630
  await this.secondElement.click({ force: true, timeout: 60000 });
621
631
  await this.changeTypeButton.click({ force: true, timeout: 60000 });
632
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
633
+ await this.restConnectorOption.scrollIntoViewIfNeeded();
634
+ await this.restConnectorOption.click({ timeout: 90000, force: true });
622
635
  }
623
- // Use a longer timeout to allow the connector to finish registering
624
- // after a marketplace download before giving up.
625
- await (0, test_1.expect)(this.restConnectorOption).toBeVisible({
626
- timeout: 60000,
627
- });
628
- await this.restConnectorOption.scrollIntoViewIfNeeded();
629
- // force: true bypasses context-pad overlays that can intercept clicks
630
- await this.restConnectorOption.click({
631
- timeout: 60000,
632
- force: true,
633
- });
634
636
  return;
635
637
  }
636
638
  catch (error) {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OCTenantPage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- const sleep_1 = require("../../utils/sleep");
6
5
  const findLocatorInPaginatedList_1 = require("../../utils/findLocatorInPaginatedList");
7
6
  const expectTextWithPagination_1 = require("../../utils/assertionHelpers/expectTextWithPagination");
8
7
  class OCTenantPage {
@@ -150,7 +149,6 @@ class OCTenantPage {
150
149
  await this.fillTenantDescriptionInput('This is a test');
151
150
  await this.clickCreateTenantSubButton();
152
151
  await this.assertTenantCreated();
153
- await (0, sleep_1.sleep)(30000);
154
152
  }
155
153
  async assertTenantCreated() {
156
154
  try {
@@ -178,7 +176,7 @@ class OCTenantPage {
178
176
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
179
177
  try {
180
178
  await this.page.reload();
181
- await (0, sleep_1.sleep)(10000);
179
+ await this.page.waitForLoadState('networkidle');
182
180
  const tenant = this.page.getByText(tenantName).first();
183
181
  await (0, findLocatorInPaginatedList_1.findLocatorInPaginatedList)(this.page, tenant);
184
182
  await tenant.click({
@@ -259,14 +257,14 @@ class OCTenantPage {
259
257
  }
260
258
  async fillRoleIdSearchBox(roleId, roleIdentifier) {
261
259
  await this.roleIdSearchBox.fill(roleId);
262
- await this.page.getByText(roleIdentifier).click();
260
+ await this.page.getByText(roleIdentifier).click({ force: true });
263
261
  }
264
262
  async clickAssignRoleSubButton() {
265
263
  await this.assignRoleSubButton.click();
266
264
  }
267
265
  async assignRoleToTenant(roleId, roleIdentifier) {
268
266
  await this.clickRolesTab();
269
- await (0, sleep_1.sleep)(1000);
267
+ await this.page.waitForLoadState('networkidle');
270
268
  if (await this.row(roleId).isVisible()) {
271
269
  console.log(`Role ${roleId} is already assigned to tenant`);
272
270
  return;
@@ -44,7 +44,7 @@ class OperateHomePage {
44
44
  }
45
45
  async clickProcessesTab() {
46
46
  await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.processesTab, {
47
- totalTimeout: 20000,
47
+ totalTimeout: 60000,
48
48
  });
49
49
  await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.processPageHeading, {
50
50
  preAction: async () => {
@@ -155,8 +155,8 @@ class OperateProcessesPage {
155
155
  if (await this.checkTableForProcess(processName)) {
156
156
  return;
157
157
  }
158
- const MAX_ATTEMPTS = 100;
159
- const TOTAL_TIMEOUT_MS = constants_1._1_MINUTE_IN_MS * 2;
158
+ const MAX_ATTEMPTS = 30;
159
+ const TOTAL_TIMEOUT_MS = constants_1._1_MINUTE_IN_MS * 6;
160
160
  let attempt = 0;
161
161
  let lastError;
162
162
  const startTime = Date.now();
@@ -180,7 +180,7 @@ class OperateProcessesPage {
180
180
  lastError = err instanceof Error ? err.message : err;
181
181
  console.log(`Attempt ${attempt} failed for "${processName}". URL: ${this.page.url()}. Error: ${String(lastError)}. Reloading...`);
182
182
  await this.page.reload();
183
- await (0, sleep_1.sleep)(5000);
183
+ await this.page.waitForLoadState('networkidle');
184
184
  }
185
185
  }
186
186
  throw new Error(`Failed to open instance "${processName}" after ${MAX_ATTEMPTS} attempts. Last error: ${String(lastError)}`);
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TaskPanelPage = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- const sleep_1 = require("../../utils/sleep");
6
5
  const constants_1 = require("../../utils/constants");
7
6
  class TaskPanelPage {
8
7
  page;
@@ -55,6 +54,7 @@ class TaskPanelPage {
55
54
  if (attempt < 30) {
56
55
  console.warn(`Attempt ${attempt} failed. Reloading page...`);
57
56
  await this.page.reload();
57
+ await this.page.waitForLoadState('networkidle');
58
58
  }
59
59
  else {
60
60
  throw new Error(`Failed to open task "${name}" after 3 attempts: ${error}`);
@@ -83,7 +83,7 @@ class TaskPanelPage {
83
83
  await this.processesPageTab.click();
84
84
  }
85
85
  async taskCount(name) {
86
- await (0, sleep_1.sleep)(50000);
86
+ await this.page.waitForLoadState('networkidle');
87
87
  return this.availableTasks.getByText(name, { exact: true }).count();
88
88
  }
89
89
  async clickTasksTab() {
@@ -22,6 +22,7 @@ class ClusterPage {
22
22
  });
23
23
  }
24
24
  async assertCustomTagsAreVisible(tags) {
25
+ await this.page.waitForLoadState('networkidle');
25
26
  for (const tag of tags) {
26
27
  await (0, test_1.expect)(this.clustersList.getByText(tag, { exact: true })).toBeVisible({
27
28
  timeout: 60000,
@@ -28,9 +28,10 @@ class ManagementIdentityPage {
28
28
  orchestrationCheckbox;
29
29
  constructor(page) {
30
30
  this.page = page;
31
- this.identityBanner = page.getByRole('link', {
32
- name: 'Camunda logo Management Identity',
33
- });
31
+ this.identityBanner = page
32
+ .locator('a')
33
+ .filter({ hasText: /^Camunda logo\s*Management Identity$/ })
34
+ .first();
34
35
  this.usersLink = page.locator('a').filter({ hasText: 'Users' });
35
36
  this.tenantTab = page
36
37
  .getByRole('link', { name: 'Tenants' })
@@ -134,6 +134,7 @@ declare class ModelerCreatePage {
134
134
  clickDeployButton(): Promise<void>;
135
135
  clickDeploySubButton(): Promise<void>;
136
136
  clickCancelButton(): Promise<void>;
137
+ private recoverModelerSession;
137
138
  clickRestConnectorOption(): Promise<void>;
138
139
  clickMarketPlaceButton(): Promise<void>;
139
140
  completeDeploymentEndpointConfiguration(): Promise<void>;