@camunda/e2e-test-suite 0.0.1140 → 0.0.1142

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.
@@ -30,6 +30,7 @@ declare class LoginPage {
30
30
  username?: string;
31
31
  password?: string;
32
32
  }): Promise<void>;
33
+ private submitUsernameStep;
33
34
  loginWithTestUser(credentials?: {
34
35
  username?: string;
35
36
  password?: string;
@@ -79,6 +79,50 @@ class LoginPage {
79
79
  await this.clickLoginButton();
80
80
  await (0, UtilitiesPage_1.assertTestUsesCorrectOrganization)(this.page);
81
81
  }
82
+ // The identity provider's email step submits through client-side JS, so a
83
+ // `Continue` click that lands while the form is still hydrating is swallowed:
84
+ // the click resolves, nothing navigates, and the page silently stays on the
85
+ // email step. `fillPassword` then waits out its whole 120s budget for a
86
+ // password field that will never render, and because every one of
87
+ // loginWithRetry's 5 attempts loses the click the same way the only symptom
88
+ // is "Login failed after 5 attempts: ... waiting for getByLabel(/^Password/)
89
+ // to be visible" -- the nightly failure in run 34319318325.
90
+ //
91
+ // Re-submitting the email is idempotent, so spend the same overall budget on
92
+ // three attempts instead of one, and only re-click while the email step is
93
+ // still on screen: that proves the previous click did not advance the flow.
94
+ async submitUsernameStep(username) {
95
+ const maxAttempts = 3;
96
+ const passwordStepTimeout = 40000;
97
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
98
+ await this.fillUsername(username);
99
+ await this.clickContinueButton();
100
+ const reachedPasswordStep = await this.passwordInput
101
+ .waitFor({ state: 'visible', timeout: passwordStepTimeout })
102
+ .then(() => true)
103
+ .catch(() => false);
104
+ if (reachedPasswordStep) {
105
+ return;
106
+ }
107
+ // Surface a rate-limit page with the marker loginWithRetry keys its
108
+ // 60-90s backoff on, rather than burning the remaining attempts on a
109
+ // form the provider is not going to serve.
110
+ if (await this.rateLimitError
111
+ .first()
112
+ .isVisible()
113
+ .catch(() => false)) {
114
+ throw new Error('AUTH0_RATE_LIMIT: identity provider returned an error page');
115
+ }
116
+ // Neither the password step nor the email step is on screen: some
117
+ // interstitial we do not model. Hand back to fillPassword's own wait
118
+ // instead of re-typing blindly into a page we cannot identify.
119
+ if (!(await this.usernameInput.locator.isVisible().catch(() => false))) {
120
+ return;
121
+ }
122
+ console.warn(`Email step did not advance to the password step (attempt ${attempt}/${maxAttempts}); re-submitting`);
123
+ }
124
+ throw new Error(`Login form stayed on the email step after ${maxAttempts} submissions`);
125
+ }
82
126
  async loginWithTestUser(credentials = {}) {
83
127
  const { username = process.env.C8_USERNAME_TEST, password = process.env.C8_PASSWORD_TEST, } = credentials;
84
128
  // Skip navigation if the auth0 login page is already loaded — re-navigating
@@ -106,8 +150,7 @@ class LoginPage {
106
150
  (await this.passwordInput.isVisible({ timeout: 5000 }).catch(() => false));
107
151
  if (!onPasswordStep) {
108
152
  await (0, test_1.expect)(this.usernameInput.locator).toBeVisible({ timeout: 120000 });
109
- await this.fillUsername(username);
110
- await this.clickContinueButton();
153
+ await this.submitUsernameStep(username);
111
154
  }
112
155
  await this.fillPassword(password);
113
156
  await (0, test_1.expect)(this.loginButton).toBeVisible({ timeout: 120000 });
@@ -36,9 +36,29 @@ class PlayPage {
36
36
  await (0, test_1.expect)(this.completeJobButton).toBeVisible({
37
37
  timeout: maxWaitTimeSeconds,
38
38
  });
39
+ // Modeler keeps the overlay mounted but disabled while a previous job
40
+ // action is still in flight or waiting for the polled statistics to catch
41
+ // up (camunda-hub test-studio JobCompleteButton -> useAsyncActionState), so
42
+ // "visible" alone does not mean "ready to click". Wait for enabled too.
43
+ await (0, test_1.expect)(this.completeJobButton).toBeEnabled({
44
+ timeout: maxWaitTimeSeconds,
45
+ });
39
46
  }
40
47
  async clickCompleteJobButton() {
41
- await this.completeJobButton.click();
48
+ // The complete-job action is a bpmn-js canvas overlay pinned to the active
49
+ // element, so it is re-laid-out (and briefly detached) whenever the diagram
50
+ // re-renders -- which it does on every job/instance update arriving from
51
+ // the cluster. A bare click that lands in that window silently resolves
52
+ // against a stale node, the job is never completed, and the failure only
53
+ // surfaces one call later as waitForNextElementToBeActive timing out on the
54
+ // next element that consequently never became active. Retry the click
55
+ // against a fresh visibility + clickability check instead.
56
+ await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.completeJobButton, {
57
+ totalTimeout: maxWaitTimeSeconds,
58
+ visibilityTimeout: 30000,
59
+ maxRetries: 3,
60
+ retryDelayMs: 3000,
61
+ });
42
62
  }
43
63
  async clickStartInstanceButton() {
44
64
  const startTrigger = this.configureTestPanelStartButton
@@ -88,8 +108,38 @@ class PlayPage {
88
108
  }
89
109
  }
90
110
  async waitForNextElementToBeActive(historyItem) {
91
- await (0, test_1.expect)(this.page.getByText(new RegExp(`^${historyItem}`, 'i'))).toBeVisible({
111
+ // clickCompleteJobButton now retries a click that *throws*, but a click
112
+ // swallowed by a re-laid-out overlay resolves successfully without
113
+ // completing anything, so the retry helper alone cannot catch it. The only
114
+ // symptom is this locator timing out on an element that never became
115
+ // active -- exactly the nightly failure on 'service-task*'.
116
+ //
117
+ // Once the next element has stayed absent well past any normal Play advance
118
+ // latency AND a complete-job overlay is still sitting enabled on the
119
+ // canvas, the previous click demonstrably did not land, so re-issue it. The
120
+ // grace period matters: it keeps us from completing the job of the very
121
+ // element we are waiting for during the brief window where its overlay has
122
+ // rendered but its history entry has not. The assertion is unchanged --
123
+ // this still only passes on a visible history entry.
124
+ const element = this.page.getByText(new RegExp(`^${historyItem}`, 'i'));
125
+ const recoveryGraceMs = 60000;
126
+ const startedAt = Date.now();
127
+ await (0, test_1.expect)(async () => {
128
+ if (Date.now() - startedAt > recoveryGraceMs) {
129
+ const isPreviousJobStillPending = (await this.completeJobButton.isVisible().catch(() => false)) &&
130
+ (await this.completeJobButton.isEnabled().catch(() => false));
131
+ // Re-check immediately before clicking: if the element became active
132
+ // in the meantime, the pending overlay is its own and must be left
133
+ // alone for the caller's next step.
134
+ if (isPreviousJobStillPending &&
135
+ !(await element.isVisible().catch(() => false))) {
136
+ await this.completeJobButton.click({ timeout: 30000 });
137
+ }
138
+ }
139
+ await (0, test_1.expect)(element).toBeVisible({ timeout: 15000 });
140
+ }).toPass({
92
141
  timeout: maxWaitTimeSeconds,
142
+ intervals: [5000, 10000, 15000],
93
143
  });
94
144
  }
95
145
  async waitForProcessToBeCompleted() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1140",
3
+ "version": "0.0.1142",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",