@camunda/e2e-test-suite 0.0.1262 → 0.0.1263

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.
@@ -77,12 +77,14 @@ class ModelerHomePage {
77
77
  await this.enterNewProjectName(this.defaultFolderName);
78
78
  }
79
79
  async clickCrossComponentProjectFolder() {
80
- await this.page
81
- .getByTitle(this.defaultFolderName, {
82
- exact: true,
83
- })
84
- .first()
85
- .click({ timeout: 4000 });
80
+ // Coming back to the Modeler home page mid-flow re-fetches and re-renders
81
+ // the project list, so the tile is not on screen the moment navigation
82
+ // resolves. A bare 4s click raced that render; wait for the tile first,
83
+ // the way every other version of this page object already does.
84
+ await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.crossComponentProjectFolder, {
85
+ visibilityTimeout: 30000,
86
+ });
87
+ await this.crossComponentProjectFolder.click({ timeout: 30000 });
86
88
  }
87
89
  async clickProcessDiagram(name) {
88
90
  const process = this.rows.filter({ hasText: name }).getByTitle(name).first();
@@ -16,7 +16,11 @@ class KeycloakAdminPage {
16
16
  async switchToCamundaPlatform() {
17
17
  const realmSelector = this.page.getByTestId('nav-item-realms');
18
18
  await realmSelector.click();
19
+ // The realm dropdown is rendered by the admin console after an async
20
+ // realm lookup, so a bare click races Playwright's default 10s action
21
+ // timeout on a loaded cluster. Wait for it explicitly instead.
19
22
  const searchField = this.page.getByTestId('selectRealminput');
23
+ await (0, test_1.expect)(searchField).toBeVisible({ timeout: 30000 });
20
24
  await searchField.click();
21
25
  await this.page
22
26
  .getByPlaceholder('Search')
@@ -45,10 +45,16 @@ async function loginToKeycloakAdmin(navigationPage, keycloakLoginPage, keycloakA
45
45
  for (let attempt = 0; attempt < maxRetries; attempt++) {
46
46
  try {
47
47
  await navigationPage.goToKeycloak();
48
- await keycloakLoginPage.toBeVisible();
49
- await keycloakLoginPage.fillUsername((0, exports.keycloakAdminCredentials)().username);
50
- await keycloakLoginPage.fillPassword((0, exports.keycloakAdminCredentials)().password);
51
- await keycloakLoginPage.clickLogin();
48
+ // A failed attempt can still have authenticated: the submit click lands
49
+ // but its navigation outruns the action timeout, so the attempt throws
50
+ // while Keycloak keeps the master-realm session. Keycloak then serves
51
+ // the admin console straight away, and re-filling a login form that is
52
+ // no longer rendered makes every remaining attempt fail.
53
+ if (await keycloakLoginPage.keycloakBanner.isVisible()) {
54
+ await keycloakLoginPage.fillUsername((0, exports.keycloakAdminCredentials)().username);
55
+ await keycloakLoginPage.fillPassword((0, exports.keycloakAdminCredentials)().password);
56
+ await keycloakLoginPage.clickLogin();
57
+ }
52
58
  await keycloakAdminPage.toBeVisible();
53
59
  return;
54
60
  }
@@ -8,6 +8,7 @@ declare class NavigationPage {
8
8
  readonly identityPageBanner: Locator;
9
9
  readonly consolePageBanner: Locator;
10
10
  readonly keyboardPageBanner: Locator;
11
+ readonly keycloakAdminPageBanner: Locator;
11
12
  readonly managementIdentityPageBanner: Locator;
12
13
  constructor(page: Page);
13
14
  private isRetriableNavigationNetworkError;
@@ -48,6 +48,7 @@ class NavigationPage {
48
48
  identityPageBanner;
49
49
  consolePageBanner;
50
50
  keyboardPageBanner;
51
+ keycloakAdminPageBanner;
51
52
  managementIdentityPageBanner;
52
53
  constructor(page) {
53
54
  this.page = page;
@@ -76,6 +77,7 @@ class NavigationPage {
76
77
  .filter({ hasText: /^Camunda logo\s*Management Identity$/ })
77
78
  .first();
78
79
  this.keyboardPageBanner = page.locator('#keycloak-bg');
80
+ this.keycloakAdminPageBanner = page.locator('#kc-main-content-page-container');
79
81
  }
80
82
  isRetriableNavigationNetworkError(error) {
81
83
  const message = error instanceof Error ? error.message : String(error);
@@ -215,12 +217,19 @@ class NavigationPage {
215
217
  async goToModelerWithoutAccess({ username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}) {
216
218
  await this.goToWithoutAccess(MODELER_CONTEXT_PATH, username, password);
217
219
  }
220
+ // Resolves once Keycloak has settled on either its login form or, when the
221
+ // master-realm SSO session is still valid, the admin console it serves
222
+ // instead. Asserting the login form alone makes every retry of an already
223
+ // authenticated session time out on a form Keycloak will never render.
218
224
  async goToKeycloak() {
219
225
  const keycloakUrl = process.env.KEYCLOAK_URL
220
226
  ? `${process.env.KEYCLOAK_URL}/auth`
221
227
  : '/auth';
222
228
  await this.page.goto(keycloakUrl);
223
- await (0, test_1.expect)(this.keyboardPageBanner).toBeVisible({ timeout: 60000 });
229
+ await test_1.expect
230
+ .poll(async () => (await this.keyboardPageBanner.isVisible()) ||
231
+ (await this.keycloakAdminPageBanner.isVisible()), { timeout: 60000 })
232
+ .toBe(true);
224
233
  }
225
234
  async goToOCIdentity(sleepTimeout, credentials) {
226
235
  await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/identity`, this.identityPageBanner, sleepTimeout, credentials);
@@ -19,6 +19,7 @@ SM_8_7_1.test.describe.parallel('Console User Flow Tests', () => {
19
19
  (0, loggingUtils_1.cleanupTestLogging)();
20
20
  });
21
21
  (0, SM_8_7_1.test)('Custom Tags', async ({ consoleHomePage, clusterPage, navigationPage, context, }) => {
22
+ SM_8_7_1.test.slow();
22
23
  await SM_8_7_1.test.step('Navigate to Clusters', async () => {
23
24
  await context.clearCookies();
24
25
  await navigationPage.goToConsole();
@@ -33,6 +34,7 @@ SM_8_7_1.test.describe.parallel('Console User Flow Tests', () => {
33
34
  });
34
35
  });
35
36
  (0, SM_8_7_1.test)('Custom Properties', async ({ consoleHomePage, clusterPage, clusterDetailsPage, page, navigationPage, context, }) => {
37
+ SM_8_7_1.test.slow();
36
38
  await SM_8_7_1.test.step('Navigate to Cluster Details', async () => {
37
39
  await context.clearCookies();
38
40
  await navigationPage.goToConsole();
@@ -23,6 +23,7 @@ SM_8_7_1.test.describe.parallel('Optimize User Flow Tests', () => {
23
23
  (0, loggingUtils_1.cleanupTestLogging)();
24
24
  });
25
25
  (0, SM_8_7_1.test)('Process Import Flow', async ({ page, context, operateHomePage, modelerHomePage, navigationPage, modelerCreatePage, operateProcessesPage, operateProcessInstancePage, optimizeHomePage, optimizeDashboardPage, }) => {
26
+ SM_8_7_1.test.slow();
26
27
  const processName = 'Optimize_Job_Worker_User_Task_Flow' +
27
28
  (await (0, _setup_1.generateRandomStringAsync)(3));
28
29
  await SM_8_7_1.test.step('Open Cross Component Test Project and Create a BPMN Diagram Template', async () => {
@@ -122,6 +123,7 @@ SM_8_7_1.test.describe.parallel('Optimize User Flow Tests', () => {
122
123
  });
123
124
  });
124
125
  (0, SM_8_7_1.test)('New Instances Updated Flow', async ({ page, context, modelerHomePage, navigationPage, modelerCreatePage, operateHomePage, operateProcessesPage, operateProcessInstancePage, optimizeHomePage, optimizeCollectionsPage, optimizeReportPage, }) => {
126
+ SM_8_7_1.test.slow();
125
127
  const reportName = await (0, _setup_1.generateRandomStringAsync)(5);
126
128
  const processName = 'Optimize_Job_Worker_User_Task_Flow_Updated' +
127
129
  (await (0, _setup_1.generateRandomStringAsync)(3));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1262",
3
+ "version": "0.0.1263",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",