@camunda/e2e-test-suite 0.0.451 → 0.0.452

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 (37) 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/mt-enabled-user-flows.spec.js +40 -38
  34. package/dist/tests/SM-8.9/connectors-user-flows.spec.js +15 -8
  35. package/dist/tests/SM-8.9/mt-enabled-user-flows.spec.js +40 -38
  36. package/dist/utils/resetSession.js +4 -2
  37. package/package.json +1 -1
@@ -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 {
@@ -613,29 +614,52 @@ class ModelerCreatePage {
613
614
  async clickCancelButton() {
614
615
  await this.cancelButton.click();
615
616
  }
617
+ async recoverModelerSession() {
618
+ // Reload can get stuck in auth redirects. Navigate back to the
619
+ // current diagram URL, handle login if Keycloak intercepts, then
620
+ // wait for the canvas to render.
621
+ const url = this.page.url().split('?')[0]; // strip query params
622
+ await this.page.context().clearCookies();
623
+ await this.page.goto(url, { timeout: 30000, waitUntil: 'domcontentloaded' });
624
+ // Handle login if redirected to Keycloak
625
+ const username = process.env.DEMO_USER_EMAIL || 'demo';
626
+ const password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD || 'demo';
627
+ const loginInput = this.page.locator('#username');
628
+ if (await loginInput.isVisible({ timeout: 5000 }).catch(() => false)) {
629
+ await loginInput.fill(username);
630
+ await this.page.locator('#password').fill(password);
631
+ await this.page.locator('#kc-login').click();
632
+ }
633
+ await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
634
+ }
616
635
  async clickRestConnectorOption() {
617
636
  const maxRetries = 4;
618
637
  for (let retries = 0; retries < maxRetries; retries++) {
619
638
  try {
620
639
  if (retries === 0) {
621
640
  // First attempt
622
- await this.restConnectorOption.click({ timeout: 90000 });
641
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 60000 });
642
+ await this.restConnectorOption.click({ timeout: 60000 });
623
643
  }
624
644
  else if (retries === 1 || retries === 2) {
625
- // Second or third attempt
626
- await this.page.reload();
645
+ // Recover session cleanly instead of page.reload()
646
+ await this.recoverModelerSession();
627
647
  await this.secondElement.click({ timeout: 60000 });
628
648
  await this.changeTypeButton.click({ force: true, timeout: 60000 });
649
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
629
650
  await this.restConnectorOption.click({ timeout: 90000 });
630
651
  }
631
652
  else {
632
- // Forth and subsequent attempts
653
+ // Fourth attempt: install via marketplace (real product flow)
654
+ await this.recoverModelerSession();
655
+ await this.secondElement.click({ timeout: 60000 });
656
+ await this.changeTypeButton.click({ force: true, timeout: 60000 });
633
657
  await this.clickMarketPlaceButton();
634
- const connectorMarketplacePage = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
635
- await connectorMarketplacePage.clickSearchForConnectorTextbox();
658
+ const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
659
+ await marketplace.clickSearchForConnectorTextbox();
636
660
  await (0, sleep_1.sleep)(5000);
637
- await connectorMarketplacePage.fillSearchForConnectorTextbox('REST Connector');
638
- await connectorMarketplacePage.downloadConnectorToProject();
661
+ await marketplace.fillSearchForConnectorTextbox('REST Connector');
662
+ await marketplace.downloadConnectorToProject();
639
663
  await this.restConnectorOption.click({ timeout: 120000 });
640
664
  }
641
665
  return;
@@ -868,18 +892,26 @@ class ModelerCreatePage {
868
892
  await this.intermediateBoundaryEvent.click({ timeout: 60000 });
869
893
  }
870
894
  async clickIntermediateWebhookConnectorOption() {
871
- try {
872
- await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
873
- timeout: 20000,
874
- });
875
- await this.intermediateWebhookConnectorOption.click();
876
- }
877
- catch (error) {
878
- await this.page.reload();
879
- await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 20000 });
880
- await this.secondElement.click();
881
- await this.changeTypeButton.click({ force: true });
882
- await this.intermediateWebhookConnectorOption.click();
895
+ const max = 3;
896
+ for (let i = 0; i < max; i++) {
897
+ try {
898
+ await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
899
+ timeout: 30000,
900
+ });
901
+ await this.intermediateWebhookConnectorOption.click({ timeout: 30000 });
902
+ return;
903
+ }
904
+ catch (err) {
905
+ console.error(`clickIntermediateWebhookConnectorOption attempt ${i + 1} failed: ${err}`);
906
+ if (i === max - 1)
907
+ throw err;
908
+ await this.page.reload();
909
+ await this.page.waitForLoadState('networkidle');
910
+ // Wait for modeler canvas to render after reload before re-selecting
911
+ await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
912
+ await this.secondElement.click({ force: true, timeout: 30000 });
913
+ await this.changeTypeButton.click({ force: true, timeout: 30000 });
914
+ }
883
915
  }
884
916
  }
885
917
  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 goToOCIdentity(sleepTimeout, credentials) {
126
- await this.goTo(`${ORCHESTRATION_CONTEXT_PATH}/identity`, this.identityPageBanner, sleepTimeout, credentials);
138
+ await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/identity`, 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;
@@ -29,7 +29,7 @@ class OperateHomePage {
29
29
  });
30
30
  this.editVariableButton = page.getByTestId('edit-variable-button');
31
31
  this.variableValueInput = page.getByTestId('edit-variable-value');
32
- this.saveVariableButton = page.getByLabel('Save variable');
32
+ this.saveVariableButton = page.locator('[aria-label="Save variable"]');
33
33
  this.editVariableSpinner = page
34
34
  .getByTestId('variable-operation-spinner')
35
35
  .locator('circle')
@@ -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 () => {
@@ -59,20 +59,45 @@ class OperateHomePage {
59
59
  await this.informationDialog.click();
60
60
  }
61
61
  async clickEditVariableButton(variableName) {
62
- const editVariableButton = 'Edit variable ' + variableName;
63
- await this.page.getByLabel(editVariableButton).click();
62
+ // Edit button is only visible on row hover
63
+ const varRow = this.page.getByTestId('variable-' + variableName);
64
+ await varRow.hover();
65
+ const button = this.page.locator(`[aria-label="Edit variable ${variableName}"]`);
66
+ await (0, test_1.expect)(button).toBeVisible({ timeout: 10000 });
67
+ await button.click({ force: true });
64
68
  }
65
69
  async clickVariableValueInput() {
66
- await this.variableValueInput.click();
70
+ const monacoLine = this.variableValueInput.locator('.view-line').first();
71
+ if (await monacoLine.isVisible({ timeout: 3000 }).catch(() => false)) {
72
+ await monacoLine.click();
73
+ }
74
+ else {
75
+ await this.variableValueInput.click();
76
+ }
67
77
  }
68
78
  async clearVariableValueInput() {
69
- await this.variableValueInput.clear();
79
+ const monacoLine = this.variableValueInput.locator('.view-line').first();
80
+ if (await monacoLine.isVisible({ timeout: 3000 }).catch(() => false)) {
81
+ await monacoLine.click();
82
+ await this.page.keyboard.press('Control+A');
83
+ await this.page.keyboard.press('Delete');
84
+ }
85
+ else {
86
+ await this.variableValueInput.clear();
87
+ }
70
88
  }
71
89
  async fillVariableValueInput(value) {
72
- await this.variableValueInput.fill(value);
90
+ const monacoLine = this.variableValueInput.locator('.view-line').first();
91
+ if (await monacoLine.isVisible({ timeout: 3000 }).catch(() => false)) {
92
+ await monacoLine.click();
93
+ await this.page.keyboard.insertText(value);
94
+ }
95
+ else {
96
+ await this.variableValueInput.fill(value);
97
+ }
73
98
  }
74
99
  async clickSaveVariableButton() {
75
- await this.saveVariableButton.click();
100
+ await this.saveVariableButton.click({ force: true });
76
101
  }
77
102
  async openProcess(processName) {
78
103
  await this.page.getByText(processName).click();
@@ -113,13 +113,15 @@ class OperateProcessesPage {
113
113
  try {
114
114
  const processTable = this.page.locator('[aria-label="Process Instances Panel"]');
115
115
  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;
116
+ const timeout = env_1.isOpenSearch
117
+ ? constants_1._1_SECOND_IN_MS * 10
118
+ : constants_1._1_SECOND_IN_MS * 2;
117
119
  const row = this.page.locator(`tr:has-text("${processName}")`).first();
118
120
  await (0, test_1.expect)(row).toBeVisible({ timeout });
119
121
  const link = row.locator('a').first();
120
- await (0, test_1.expect)(link).toBeVisible({ timeout: constants_1._100_MS * 2 });
122
+ await (0, test_1.expect)(link).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 2 });
121
123
  await link.scrollIntoViewIfNeeded();
122
- await link.click({ timeout: constants_1._100_MS * 2 });
124
+ await link.click({ timeout: constants_1._1_SECOND_IN_MS * 2 });
123
125
  await (0, test_1.expect)(this.page.getByText('Instance History').first()).toBeVisible({ timeout: constants_1._1_SECOND_IN_MS * 4 });
124
126
  if (await this.whatsNewPopUp.isVisible()) {
125
127
  await this.gotItButton.click();
@@ -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() {
@@ -215,14 +215,21 @@ SM_8_10_1.test.describe('Connectors User Flow Tests @tasklistV2', () => {
215
215
  await SM_8_10_1.test.step('Make Authorization Request', async () => {
216
216
  const baseURL = process.env.PLAYWRIGHT_BASE_URL ||
217
217
  `http://gke-${process.env.BASE_URL}.ci.distro.ultrawombat.com`;
218
- const response = await request.post(`${baseURL}/connectors/inbound/test-webhook-intermediate${randomString}`, {
219
- data: {
220
- test: 'test',
221
- },
222
- });
223
- if (response.status() !== 200) {
224
- console.error(`Authorization Request ${baseURL}/connectors/inbound/test-webhook-intermediate${randomString} failed with response ${response.status()}`);
225
- throw new Error(`Webhook request failed with status ${response.status()}`);
218
+ const url = `${baseURL}/connectors/inbound/test-webhook-intermediate${randomString}`;
219
+ // Poll for inbound endpoint readiness — connector deployment is async after PI start
220
+ const deadline = Date.now() + 180000;
221
+ let response;
222
+ let attempt = 0;
223
+ while (Date.now() < deadline) {
224
+ attempt++;
225
+ response = await request.post(url, { data: { test: 'test' } });
226
+ if (response.status() === 200)
227
+ break;
228
+ console.error(`Webhook readiness attempt ${attempt}: ${url} -> ${response.status()}`);
229
+ await (0, sleep_1.sleep)(10000);
230
+ }
231
+ if (!response || response.status() !== 200) {
232
+ throw new Error(`Webhook request failed with status ${response?.status()} after ${attempt} attempts`);
226
233
  }
227
234
  await (0, sleep_1.sleep)(60000);
228
235
  });
@@ -170,7 +170,6 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
170
170
  await navigationPage.goToOCAdmin();
171
171
  await (0, UtilitiesPage_1.createUserAndAssignToRole)(page, navigationPage, managementIdentityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityMappingRulesPage, ocIdentityRolesPage, testUser1, password);
172
172
  await (0, resetSession_1.resetSession)(browser, page);
173
- await (0, sleep_1.sleep)(10000);
174
173
  await navigationPage.goToOCAdmin();
175
174
  await (0, UtilitiesPage_1.createUserAndAssignToRole)(page, navigationPage, managementIdentityPage, keycloakLoginPage, keycloakAdminPage, ocIdentityHomePage, ocIdentityMappingRulesPage, ocIdentityRolesPage, testUser2, password);
176
175
  });
@@ -209,11 +208,12 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
209
208
  await modelerCreatePage.expandAssignmentSection();
210
209
  await modelerCreatePage.clickCandidateGroupsInput();
211
210
  await modelerCreatePage.fillCandidateGroupsInput(groupNameMultiple);
212
- await (0, sleep_1.sleep)(1000);
211
+ await modelerCreatePage.clickCanvas(); // blur to commit candidate group to BPMN model
213
212
  await modelerCreatePage.runProcessInstance('', mtTenant);
214
213
  });
215
214
  await SM_8_10_1.test.step('View User Tasks in Tasklist', async () => {
216
215
  await navigationPage.goToTasklist();
216
+ await page.waitForLoadState('networkidle');
217
217
  await (0, test_1.expect)(page.getByText(`${userTaskName}1`)).toBeVisible({
218
218
  timeout: 120000,
219
219
  });
@@ -223,10 +223,10 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
223
223
  });
224
224
  await SM_8_10_1.test.step('Clear cookies and reset session', async () => {
225
225
  await (0, resetSession_1.resetSession)(browser, page); //a workaround for https://github.com/camunda/camunda/issues/34513
226
- await (0, sleep_1.sleep)(10000);
227
226
  });
228
227
  await SM_8_10_1.test.step('Navigate to Tasklist and Assert User Tasks ', async () => {
229
228
  await navigationPage.goToTasklist(undefined, credentials1);
229
+ await page.waitForLoadState('networkidle');
230
230
  await (0, test_1.expect)(page.getByText(`${userTaskName}1`)).toBeVisible({
231
231
  timeout: 120000,
232
232
  });
@@ -236,10 +236,10 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
236
236
  });
237
237
  await SM_8_10_1.test.step('Clear cookies and reset session', async () => {
238
238
  await (0, resetSession_1.resetSession)(browser, page); //a workaround for https://github.com/camunda/camunda/issues/34513
239
- await (0, sleep_1.sleep)(10000);
240
239
  });
241
240
  await SM_8_10_1.test.step('Navigate to Tasklist and Assert User Tasks ', async () => {
242
241
  await navigationPage.goToTasklist(undefined, credentials2);
242
+ await page.waitForLoadState('networkidle');
243
243
  await (0, test_1.expect)(page.getByText(`${userTaskName}1`)).not.toBeVisible({
244
244
  timeout: 120000,
245
245
  });
@@ -314,11 +314,12 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
314
314
  await modelerCreatePage.expandAssignmentSection();
315
315
  await modelerCreatePage.clickCandidateUsersInput();
316
316
  await modelerCreatePage.fillCandidateUsersInput(testUser);
317
- await (0, sleep_1.sleep)(1000);
317
+ await modelerCreatePage.clickCanvas(); // blur to commit candidate user to BPMN model
318
318
  await modelerCreatePage.runProcessInstance('', mtTenant);
319
319
  });
320
320
  await SM_8_10_1.test.step('View User Tasks in Tasklist', async () => {
321
321
  await navigationPage.goToTasklist();
322
+ await page.waitForLoadState('networkidle');
322
323
  await (0, test_1.expect)(page.getByText(`${userTaskName}1`)).toBeVisible({
323
324
  timeout: 120000,
324
325
  });
@@ -331,10 +332,10 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
331
332
  });
332
333
  await SM_8_10_1.test.step('Clear cookies and reset session', async () => {
333
334
  await (0, resetSession_1.resetSession)(browser, page); //a workaround for https://github.com/camunda/camunda/issues/34513
334
- await (0, sleep_1.sleep)(10000);
335
335
  });
336
336
  await SM_8_10_1.test.step('Navigate to Tasklist and Assert User Tasks ', async () => {
337
337
  await navigationPage.goToTasklist(undefined, credentials);
338
+ await page.waitForLoadState('networkidle');
338
339
  await (0, test_1.expect)(page.getByText(`${userTaskName}1`)).toBeVisible({
339
340
  timeout: 120000,
340
341
  });