@camunda/e2e-test-suite 0.0.1238 → 0.0.1240

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.
@@ -31,7 +31,7 @@ declare class AppsPage {
31
31
  clickCluster(component: Locator, name: string): Promise<void>;
32
32
  clickModeler(): Promise<void>;
33
33
  private isModelerAuthTransit;
34
- openModelerWithRetry(banner: Locator, timeout?: number, maxRetries?: number, ready?: Locator): Promise<void>;
34
+ openModelerWithRetry(banner: Locator, timeout?: number, maxRetries?: number, ready?: Locator, beforeReady?: () => Promise<void>): Promise<void>;
35
35
  openOperateWithRetry(banner: Locator, clusterName: string, timeout?: number, maxRetries?: number): Promise<void>;
36
36
  clickTasklist(clusterName: string): Promise<void>;
37
37
  openTasklistWithRetry(banner: Locator, clusterName: string, timeout?: number, maxRetries?: number): Promise<void>;
@@ -236,8 +236,25 @@ class AppsPage {
236
236
  // something only an authenticated Modeler renders -- the projects list's
237
237
  // create button -- and a logged-out tab is caught here instead, where the
238
238
  // retry re-runs the handshake and with it the internal login.
239
- async openModelerWithRetry(banner, timeout = 60000, maxRetries = 3, ready) {
239
+ async openModelerWithRetry(banner, timeout = 60000, maxRetries = 3, ready, beforeReady) {
240
240
  const modelerReady = async () => {
241
+ if (beforeReady) {
242
+ // After the Camunda Hub rebrand the Modeler home greets a first visit
243
+ // with a "Welcome to Camunda Hub" onboarding dialog that mounts a beat
244
+ // after routing and marks the app shell inert, so the banner leaves the
245
+ // accessibility tree until the dialog is dismissed. Run beforeReady
246
+ // (the dialog dismissal) each interval so a dialog that mounts after the
247
+ // first pass is still cleared, instead of burning the whole timeout on a
248
+ // banner the overlay is holding out of reach.
249
+ await (0, test_1.expect)(async () => {
250
+ await beforeReady();
251
+ await (0, test_1.expect)(banner).toBeVisible({ timeout: 15000 });
252
+ if (ready) {
253
+ await (0, test_1.expect)(ready).toBeVisible({ timeout: 15000 });
254
+ }
255
+ }).toPass({ timeout, intervals: [1000, 2000, 5000] });
256
+ return;
257
+ }
241
258
  await (0, test_1.expect)(banner).toBeVisible({ timeout });
242
259
  if (ready) {
243
260
  await (0, test_1.expect)(ready).toBeVisible({ timeout });
@@ -58,9 +58,19 @@ class ModelerHomePage {
58
58
  constructor(page) {
59
59
  this.page = page;
60
60
  this.processApplicationPage = new ProcessApplicationPage_1.ProcessApplicationPage(page);
61
- this.modelerPageBanner = page.getByRole('banner', {
61
+ // Hub's design-system shell renders the app header as a role=banner with no
62
+ // accessible name after the Camunda Hub rebrand, so the classic
63
+ // name-matched banner no longer resolves; the Modeler logo link inside it
64
+ // still carries "Camunda Modeler home". Keep the legacy named-banner branch
65
+ // for shells where the rename has not shipped yet.
66
+ this.modelerPageBanner = page
67
+ .getByRole('banner', {
62
68
  name: 'Camunda Modeler',
63
- });
69
+ })
70
+ .or(page
71
+ .getByRole('link', { name: 'Camunda Modeler home' })
72
+ .and(page.locator(':not([href$="/login"])')))
73
+ .first();
64
74
  // Hub renamed this button to "Create project" on both the classic and the
65
75
  // design-system shell. The legacy label is kept so the flow still works
66
76
  // against Modeler builds where the rename has not shipped yet. exact:true
@@ -14,11 +14,12 @@ declare class NavigationPage {
14
14
  goTo(url: string, banner: Locator, sleepTimeout?: number, { username, password, }?: {
15
15
  username?: string;
16
16
  password?: string;
17
- }, maxRetries?: number): Promise<void>;
17
+ }, maxRetries?: number, beforeBannerCheck?: () => Promise<void>): Promise<void>;
18
18
  goToModeler(sleepTimeout?: number, credentials?: {
19
19
  username: string;
20
20
  password: string;
21
21
  }): Promise<void>;
22
+ private dismissOnboardingDialog;
22
23
  goToTasklist(sleepTimeout?: number, credentials?: {
23
24
  username: string;
24
25
  password: string;
@@ -112,12 +112,15 @@ class NavigationPage {
112
112
  // that is exactly the reported "Login (/modeler) failed after 8 attempts".
113
113
  // The 60s budget is unchanged: a genuinely slow shell still gets all of it,
114
114
  // and a sustained outage still fails.
115
- async waitForBanner(url, banner, submitted) {
115
+ async waitForBanner(url, banner, submitted, beforeBannerCheck) {
116
116
  const totalTimeout = constants_1._1_SECOND_IN_MS * 60;
117
117
  const deadline = Date.now() + totalTimeout;
118
118
  let lastState = 'no banner';
119
119
  while (Date.now() < deadline) {
120
120
  const round = Math.min(constants_1._1_SECOND_IN_MS * 20, deadline - Date.now());
121
+ if (beforeBannerCheck) {
122
+ await beforeBannerCheck();
123
+ }
121
124
  try {
122
125
  await (0, test_1.expect)(banner).toBeVisible({ timeout: round });
123
126
  return;
@@ -145,7 +148,7 @@ class NavigationPage {
145
148
  }
146
149
  throw new Error(`${url} did not render its banner within ${totalTimeout}ms: ${lastState}`);
147
150
  }
148
- async goTo(url, banner, sleepTimeout, { username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}, maxRetries = 8) {
151
+ async goTo(url, banner, sleepTimeout, { username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}, maxRetries = 8, beforeBannerCheck) {
149
152
  const startTime = Date.now();
150
153
  let timeout = constants_1._1_SECOND_IN_MS * 10;
151
154
  if (url === '/modeler') {
@@ -214,7 +217,7 @@ class NavigationPage {
214
217
  else {
215
218
  submitted = await loginPage.login(username, password);
216
219
  }
217
- await this.waitForBanner(url, banner, submitted);
220
+ await this.waitForBanner(url, banner, submitted, beforeBannerCheck);
218
221
  return;
219
222
  }
220
223
  catch (error) {
@@ -261,7 +264,25 @@ class NavigationPage {
261
264
  }
262
265
  }
263
266
  async goToModeler(sleepTimeout, credentials) {
264
- await this.goTo(MODELER_CONTEXT_PATH, this.modelerPageBanner, sleepTimeout, credentials);
267
+ await this.goTo(MODELER_CONTEXT_PATH, this.modelerPageBanner, sleepTimeout, credentials, 8, () => this.dismissOnboardingDialog());
268
+ }
269
+ // After the Camunda Hub rebrand a first visit to Modeler home greets the user
270
+ // with a multi-step "Welcome to Camunda Hub" onboarding dialog. It mounts over
271
+ // the home and marks the app shell inert, so the "Camunda Modeler home" banner
272
+ // link leaves the accessibility tree until the dialog is dismissed -- gating on
273
+ // the banner alone then loops until the whole login budget is spent. Close it
274
+ // through the dialog's own control before each banner check so the banner can
275
+ // resolve; only unambiguous dismissals are matched (never "Cancel", which is a
276
+ // form action on the dialogs other flows open on purpose).
277
+ async dismissOnboardingDialog() {
278
+ const dismiss = this.page
279
+ .locator('[role="dialog"]')
280
+ .getByRole('button', { name: /^(Got it|Close|Dismiss)/i })
281
+ .first();
282
+ await dismiss
283
+ .waitFor({ state: 'visible', timeout: 3000 })
284
+ .then(() => dismiss.click())
285
+ .catch(() => { });
265
286
  }
266
287
  async goToTasklist(sleepTimeout, credentials) {
267
288
  await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/tasklist`, this.tasklistPageBanner, sleepTimeout, credentials);
@@ -168,7 +168,7 @@ _8_10_1.test.describe('Cluster Setup Tests', () => {
168
168
  await (0, test_1.expect)(homePage.camundaComponentsButton).toBeVisible({
169
169
  timeout: 120000,
170
170
  });
171
- await appsPage.openModelerWithRetry(modelerHomePage.modelerPageBanner, 180000);
171
+ await appsPage.openModelerWithRetry(modelerHomePage.modelerPageBanner, 180000, 3, undefined, () => modelerHomePage.dismissBlockingDialog());
172
172
  });
173
173
  await _8_10_1.test.step('Create Cross Component Project Folder', async () => {
174
174
  await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, user, Math.min((testInfo.workerIndex + 1) * 5000, 60000), async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1238",
3
+ "version": "0.0.1240",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",