@camunda/e2e-test-suite 0.0.538 → 0.0.540

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.
@@ -694,18 +694,20 @@ class ModelerCreatePage {
694
694
  await (0, test_1.expect)(this.page.getByTestId('instance-header').getByText(scenarioName)).toBeVisible();
695
695
  }
696
696
  async instanceStartedAssertion() {
697
- try {
698
- await (0, test_1.expect)(this.page.getByText('Instance started!')).toBeVisible({
699
- timeout: 180000,
700
- });
701
- }
702
- catch {
697
+ const success = this.page.getByText('Instance started!');
698
+ const failure = this.page.getByText('Instance could not be started');
699
+ // Race success against the error banner so we don't burn 180 s waiting
700
+ // for a toast that will never appear when Zeebe rejects the start request.
701
+ for (let attempt = 1; attempt <= 2; attempt++) {
702
+ await (0, test_1.expect)(success.or(failure)).toBeVisible({ timeout: 60000 });
703
+ if (await success.isVisible())
704
+ return;
705
+ if (attempt === 2) {
706
+ throw new Error('Process instance could not be started after 2 attempts');
707
+ }
703
708
  await this.clickStartInstanceMainButton();
704
709
  await this.completeDeploymentEndpointConfiguration();
705
710
  await this.clickStartInstanceSubButton();
706
- await (0, test_1.expect)(this.page.getByText('Instance started!')).toBeVisible({
707
- timeout: 180000,
708
- });
709
711
  }
710
712
  }
711
713
  async assertImplementationOption(implementationType) {
@@ -70,12 +70,12 @@ class OptimizeReportPage {
70
70
  }
71
71
  async waitUntilUserTaskProcessIsVisible(processName) {
72
72
  await (0, test_1.expect)(this.page.getByText(processName, { exact: true })).toBeVisible({
73
- timeout: 1000,
73
+ timeout: 30000,
74
74
  });
75
75
  }
76
76
  async clickUserTaskProcess(processName) {
77
77
  await this.page.getByText(processName, { exact: true }).first().click();
78
- await (0, sleep_1.sleep)(8000); // If we click the report and navigate away too fast after this, the report will not be generated as we expect
78
+ await (0, test_1.expect)(this.versionSelection).toBeEnabled({ timeout: 30000 });
79
79
  }
80
80
  async clickVersionSelection() {
81
81
  await this.versionSelection.click();
@@ -134,7 +134,6 @@ declare class ModelerCreatePage {
134
134
  clickDeployButton(): Promise<void>;
135
135
  clickDeploySubButton(): Promise<void>;
136
136
  clickCancelButton(): Promise<void>;
137
- private recoverModelerSession;
138
137
  clickRestConnectorOption(): Promise<void>;
139
138
  clickMarketPlaceButton(): Promise<void>;
140
139
  completeDeploymentEndpointConfiguration(): Promise<void>;
@@ -156,9 +156,9 @@ class ModelerCreatePage {
156
156
  exact: true,
157
157
  });
158
158
  this.webhookIdInput = page.getByLabel('Webhook ID');
159
- this.firstElement = page.locator('[class="djs-element djs-shape"]').nth(0);
160
- this.secondElement = page.locator('[class="djs-element djs-shape"]').nth(1);
161
- this.thirdElement = page.locator('[class="djs-element djs-shape"]').nth(2);
159
+ this.firstElement = page.locator('.djs-element.djs-shape').nth(0);
160
+ this.secondElement = page.locator('.djs-element.djs-shape').nth(1);
161
+ this.thirdElement = page.locator('.djs-element.djs-shape').nth(2);
162
162
  this.implementationSection = page.locator('[data-group-id="group-userTaskImplementation"]');
163
163
  this.implementationOptions = page.locator('#bio-properties-panel-userTaskImplementation');
164
164
  this.assignmentSection = page.locator('[data-group-id="group-assignmentDefinition"]');
@@ -172,9 +172,7 @@ class ModelerCreatePage {
172
172
  this.secondPlacedGateway = page
173
173
  .locator('[data-element-id*="Gateway"]')
174
174
  .last();
175
- this.secondPlacedElement = page
176
- .locator('[class= "djs-element djs-shape"]')
177
- .last();
175
+ this.secondPlacedElement = page.locator('.djs-element.djs-shape').last();
178
176
  this.connectToOtherElementButton = page
179
177
  .getByLabel('Connect to other element')
180
178
  .locator('path');
@@ -423,24 +421,12 @@ class ModelerCreatePage {
423
421
  await this.appendTaskButton.click({ timeout: 90000 });
424
422
  }
425
423
  async hoverOnLocator(locator, selector = '.djs-create-pad-entry') {
426
- const canvasState = await Promise.race([
427
- this.page
428
- .waitForSelector(selector, { state: 'visible' })
429
- .then(() => 'pad')
430
- .catch(() => {
431
- throw new Error('Canvas not visible');
432
- }),
433
- locator
434
- .waitFor({ state: 'visible' })
435
- .then(() => 'hover')
436
- .catch(() => {
437
- throw new Error('Locator not visible');
438
- }),
439
- ]);
440
- if (canvasState === 'hover') {
441
- await locator.hover({ timeout: 5000 });
442
- await this.page.waitForSelector(selector, { state: 'visible' });
424
+ if (await this.page.locator(selector).first().isVisible()) {
425
+ return;
443
426
  }
427
+ await locator.waitFor({ state: 'visible' });
428
+ await locator.hover({ timeout: 5000 });
429
+ await this.page.waitForSelector(selector, { state: 'visible' });
444
430
  }
445
431
  async clickAppendGatewayButton() {
446
432
  await this.appendGatewayButton.click({ timeout: 90000 });
@@ -614,58 +600,27 @@ class ModelerCreatePage {
614
600
  async clickCancelButton() {
615
601
  await this.cancelButton.click();
616
602
  }
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
- }
635
603
  async clickRestConnectorOption() {
636
604
  const maxRetries = 4;
637
605
  for (let retries = 0; retries < maxRetries; retries++) {
638
606
  try {
639
- if (retries === 0) {
640
- // First attempt
641
- await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 60000 });
642
- await this.restConnectorOption.click({ timeout: 60000 });
643
- }
644
- else if (retries === 1 || retries === 2) {
645
- // Recover session cleanly instead of page.reload()
646
- await this.recoverModelerSession();
607
+ if (retries > 0) {
608
+ // The change-type panel may have closed; re-select the element and reopen it
647
609
  await this.secondElement.click({ timeout: 60000 });
648
610
  await this.changeTypeButton.click({ force: true, timeout: 60000 });
649
- await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
650
- await this.restConnectorOption.click({ timeout: 90000 });
651
- }
652
- else {
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 });
657
- await this.clickMarketPlaceButton();
658
- const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
659
- await marketplace.clickSearchForConnectorTextbox();
660
- await (0, sleep_1.sleep)(5000);
661
- await marketplace.fillSearchForConnectorTextbox('REST Connector');
662
- await marketplace.downloadConnectorToProject();
663
- // Marketplace closes the change-type panel; reopen it so the
664
- // newly installed connector appears before clicking.
665
- await this.changeTypeButton.click({ force: true, timeout: 60000 });
666
- await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
667
- await this.restConnectorOption.click({ timeout: 60000 });
611
+ if (retries === 3) {
612
+ // Last attempt: install from marketplace in case connector is missing
613
+ await this.clickMarketPlaceButton();
614
+ const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
615
+ await marketplace.clickSearchForConnectorTextbox();
616
+ await (0, sleep_1.sleep)(5000);
617
+ await marketplace.fillSearchForConnectorTextbox('REST Connector');
618
+ await marketplace.downloadConnectorToProject();
619
+ await this.changeTypeButton.click({ force: true, timeout: 60000 });
620
+ }
668
621
  }
622
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
623
+ await this.restConnectorOption.click({ timeout: 90000 });
669
624
  return;
670
625
  }
671
626
  catch (error) {
@@ -182,6 +182,7 @@ class OCTenantPage {
182
182
  await tenant.click({
183
183
  timeout: 30000,
184
184
  });
185
+ await this.page.waitForLoadState('networkidle', { timeout: 30000 });
185
186
  return;
186
187
  }
187
188
  catch (error) {
@@ -2,5 +2,5 @@ import { Locator, Page } from '@playwright/test';
2
2
  import { OptimizeCollectionsPage } from '../SM-8.9/OptimizeCollectionsPage';
3
3
  import { OptimizeReportPage } from '../SM-8.9/OptimizeReportPage';
4
4
  import { OptimizeHomePage } from '../SM-8.9/OptimizeHomePage';
5
- export declare const createReportForProcess: (optimizeCollectionsPage: OptimizeCollectionsPage, optimizeReportPage: OptimizeReportPage, processName: string) => Promise<void>;
5
+ export declare const createReportForProcess: (page: Page, optimizeCollectionsPage: OptimizeCollectionsPage, optimizeReportPage: OptimizeReportPage, processName: string) => Promise<void>;
6
6
  export declare const assertReportWithRefreshes: (page: Page, optimizeHomePage: OptimizeHomePage, optimizeCollectionsPage: OptimizeCollectionsPage, optimizeReportPage: OptimizeReportPage, reportName: string, locator: Locator, text: string) => Promise<void>;
@@ -4,14 +4,16 @@ exports.assertReportWithRefreshes = exports.createReportForProcess = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  const UtilitiesPage_1 = require("../SM-8.9/UtilitiesPage");
6
6
  const UtilitiesPage_2 = require("../SM-8.9/UtilitiesPage");
7
- const createReportForProcess = async (optimizeCollectionsPage, optimizeReportPage, processName) => {
7
+ const createReportForProcess = async (page, optimizeCollectionsPage, optimizeReportPage, processName) => {
8
8
  let retries = 1000; // big number as this can struggle when many processes are running at once
9
9
  while (retries > 0) {
10
10
  try {
11
11
  await optimizeCollectionsPage.clickCreateNewButton();
12
12
  await optimizeCollectionsPage.clickReportOption();
13
13
  await optimizeReportPage.clickProcessSelectionButton();
14
- await optimizeReportPage.waitUntilUserTaskProcessIsVisible(processName);
14
+ await (0, test_1.expect)(page.getByText(processName, { exact: true })).toBeVisible({
15
+ timeout: 30000,
16
+ });
15
17
  break;
16
18
  }
17
19
  catch (error) {
@@ -21,7 +23,9 @@ const createReportForProcess = async (optimizeCollectionsPage, optimizeReportPag
21
23
  catch (cancelError) {
22
24
  // Page may have been closed due to test timeout, ignore
23
25
  }
24
- await new Promise((resolve) => setTimeout(resolve, 5000));
26
+ await page.reload();
27
+ await page.waitForLoadState('load', { timeout: 10000 }).catch(() => { });
28
+ await new Promise((resolve) => setTimeout(resolve, 3000));
25
29
  }
26
30
  retries--;
27
31
  (0, test_1.expect)(retries).toBeGreaterThan(0);
@@ -39,7 +43,14 @@ const assertReportWithRefreshes = async (page, optimizeHomePage, optimizeCollect
39
43
  break;
40
44
  }
41
45
  catch (error) {
42
- // nothing to do. Just loop back to the collections
46
+ try {
47
+ await page.reload();
48
+ await page.waitForLoadState('load', { timeout: 10000 }).catch(() => { });
49
+ }
50
+ catch (reloadError) {
51
+ // Page may have been detached, ignore and retry
52
+ }
53
+ await new Promise((resolve) => setTimeout(resolve, 3000));
43
54
  }
44
55
  retries--;
45
56
  (0, test_1.expect)(retries).toBeGreaterThan(0);
@@ -107,7 +107,7 @@ SM_8_9_1.test.describe.parallel('Smoke Tests', () => {
107
107
  if (process.env.IS_OPTIMIZE !== 'false') {
108
108
  await navigationPage.goToOptimize();
109
109
  await optimizeHomePage.clickCollectionsLink();
110
- await (0, optimizeReportUtils_1.createReportForProcess)(optimizeCollectionsPage, optimizeReportPage, processName);
110
+ await (0, optimizeReportUtils_1.createReportForProcess)(page, optimizeCollectionsPage, optimizeReportPage, processName);
111
111
  await optimizeReportPage.clickUserTaskProcess(processName);
112
112
  await (0, test_1.expect)(optimizeReportPage.versionSelection).toBeEnabled({
113
113
  timeout: 30000,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.538",
3
+ "version": "0.0.540",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",