@camunda/e2e-test-suite 0.0.924 → 0.0.925

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.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.updateClusterDataFilters = exports.getClusterDataFilters = exports.getTestClusterUuid = exports.authConsoleManagementAPI = exports.updateCollectionScope = exports.createSingleProcessReport = exports.createDashboard = exports.createCollection = exports.getOptimizeCookieSm = exports.getOptimizeCoockie = exports.createStringClusterVariable = exports.createJsonClusterVariable = exports.waitForProcessInstanceVisible = exports.createProcessInstance = exports.deployProcess = exports.waitForInboundWebhookRegistered = exports.waitForConnectorsReady = exports.validateMcpServerHealth = exports.authC8runAPI = exports.authSmAPI = exports.authSaasAPI = exports.authAPI = exports.buildZeebeApiUrl = exports.retryOn500 = exports.sendRequestAndAssertResponse = exports.assertUnauthorizedResponseBody = exports.expectUnauthorizedErrorBody = exports.assertResponseStatus = exports.getApiRequestContext = void 0;
7
7
  const test_1 = require("@playwright/test");
8
8
  const sleep_1 = require("./sleep");
9
+ const randomSleep_1 = require("./randomSleep");
9
10
  const fs_1 = __importDefault(require("fs"));
10
11
  const path_1 = __importDefault(require("path"));
11
12
  const os_1 = __importDefault(require("os"));
@@ -604,7 +605,14 @@ async function createStringClusterVariable(authToken, environment = 'saas', cust
604
605
  exports.createStringClusterVariable = createStringClusterVariable;
605
606
  async function getOptimizeCoockie(page) {
606
607
  const optimizeUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
607
- const maxLoginAttempts = 3;
608
+ const maxLoginAttempts = 4;
609
+ // This hook runs once per worker that picks up any test from an Optimize
610
+ // describe, so with 37 workers dozens of full interactive Auth0 logins for
611
+ // the same user fire within the same second. Stagger the first navigation to
612
+ // spread that burst -- it is enough on its own to trip Auth0's tenant-wide
613
+ // rate limit, which then fails every worker at once. Retries back off via
614
+ // randomSleep below, so this only needs to run once.
615
+ await (0, randomSleep_1.randomSleep)(0, 15000);
608
616
  // Auth0 can fail or rate-limit concurrent logins. Retry the whole flow if
609
617
  // loginToApp throws (e.g. waitForURL times out after a bad Auth0 redirect).
610
618
  for (let loginAttempt = 0; loginAttempt < maxLoginAttempts; loginAttempt++) {
@@ -616,9 +624,18 @@ async function getOptimizeCoockie(page) {
616
624
  }
617
625
  catch (error) {
618
626
  if (loginAttempt < maxLoginAttempts - 1) {
627
+ const rateLimited = String(error).includes(utils_1.AUTH0_RATE_LIMIT);
619
628
  console.warn(`getOptimizeCoockie: login attempt ${loginAttempt + 1} failed, retrying after backoff...`, error);
620
629
  await page.goto('about:blank');
621
- await page.waitForTimeout(5000 * (loginAttempt + 1));
630
+ if (rateLimited) {
631
+ // Auth0 rate-limit windows commonly last 30-90s. Back off long
632
+ // enough to outlast the window; a 5-10s backoff just retries inside
633
+ // the same window and burns the attempt budget for nothing.
634
+ await (0, randomSleep_1.randomSleep)(60000, 90000);
635
+ }
636
+ else {
637
+ await (0, randomSleep_1.randomSleep)(10000, 20000);
638
+ }
622
639
  }
623
640
  else {
624
641
  throw error;
@@ -1,2 +1,3 @@
1
1
  import { Page } from '@playwright/test';
2
+ export declare const AUTH0_RATE_LIMIT = "AUTH0_RATE_LIMIT";
2
3
  export declare function loginToApp(appName: string, page: Page): Promise<void>;
@@ -1,25 +1,50 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loginToApp = void 0;
3
+ exports.loginToApp = exports.AUTH0_RATE_LIMIT = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  const LoginPage_1 = require("../pages/8.8/LoginPage");
6
+ exports.AUTH0_RATE_LIMIT = 'AUTH0_RATE_LIMIT';
7
+ async function throwIfRateLimited(loginPage) {
8
+ const rateLimited = await loginPage.rateLimitError
9
+ .first()
10
+ .isVisible()
11
+ .catch(() => false);
12
+ if (rateLimited) {
13
+ throw new Error(`${exports.AUTH0_RATE_LIMIT}: identity provider returned an error page`);
14
+ }
15
+ }
6
16
  async function loginToApp(appName, page) {
7
17
  await page.goto(appName, { waitUntil: 'domcontentloaded', timeout: 60000 });
8
18
  await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => { });
9
19
  const loginPage = new LoginPage_1.LoginPage(page);
10
- await (0, test_1.expect)(loginPage.usernameInput).toBeVisible({ timeout: 60000 });
20
+ // Auth0 serves a tenant-wide rate-limit error page that carries none of the
21
+ // usual auth controls. Settle on whichever of the two actually renders, then
22
+ // classify: waiting on usernameInput alone burns the full 60s before the
23
+ // caller can tell a rate limit apart from a slow login form, and the caller
24
+ // needs that distinction to pick a backoff long enough to outlast the window.
25
+ await (0, test_1.expect)(loginPage.usernameInput.or(loginPage.rateLimitError.first())).toBeVisible({ timeout: 60000 });
26
+ await throwIfRateLimited(loginPage);
11
27
  await loginPage.fillUsername(process.env.C8_USERNAME);
12
28
  await (0, test_1.expect)(loginPage.usernameInput).toHaveValue(process.env.C8_USERNAME);
13
29
  await (0, test_1.expect)(loginPage.loginMessage).toBeVisible();
14
30
  await loginPage.clickContinueButton();
15
- await (0, test_1.expect)(loginPage.passwordInput).toBeVisible({ timeout: 90000 });
31
+ await (0, test_1.expect)(loginPage.passwordInput.or(loginPage.rateLimitError.first())).toBeVisible({ timeout: 90000 });
32
+ await throwIfRateLimited(loginPage);
16
33
  await loginPage.fillPassword(process.env.C8_PASSWORD);
17
34
  await (0, test_1.expect)(loginPage.passwordHeading).toBeVisible({ timeout: 90000 });
18
35
  await loginPage.clickLoginButton();
19
- await page.waitForURL((url) => url.toString().startsWith(appName), {
20
- timeout: 60000,
21
- waitUntil: 'commit',
22
- });
36
+ try {
37
+ await page.waitForURL((url) => url.toString().startsWith(appName), {
38
+ timeout: 60000,
39
+ waitUntil: 'commit',
40
+ });
41
+ }
42
+ catch (error) {
43
+ // Auth0 can also serve the rate-limit page as the response to the password
44
+ // submit, in which case the redirect back to appName never happens.
45
+ await throwIfRateLimited(loginPage);
46
+ throw error;
47
+ }
23
48
  await page
24
49
  .waitForLoadState('domcontentloaded', { timeout: 30000 })
25
50
  .catch(() => { });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.924",
3
+ "version": "0.0.925",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",