@camunda/e2e-test-suite 0.0.984 → 0.0.986

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.
@@ -589,8 +589,42 @@ class ModelerCreatePage {
589
589
  async fillNamedInput(name) {
590
590
  await this.nameInput.fill(name, { timeout: 60000 });
591
591
  }
592
+ // The breadcrumb is clicked one second after the just-uploaded diagram is
593
+ // opened, while the hub is still importing the BPMN - the canvas shows a
594
+ // spinner and the properties panel is empty. Clicking into that still-loading
595
+ // editor either hangs Playwright's actionability/scroll step for the whole
596
+ // timeout (seen locally) or lands without opening the dropdown, so the
597
+ // follow-up "Rename" lookup times out instead (seen in the nightly). Wait for
598
+ // the properties panel to finish mounting, then retry until the dropdown is
599
+ // really open.
592
600
  async clickDiagramBreadcrumb() {
593
- await this.diagramBreadcrumb.click({ timeout: 30000 });
601
+ await (0, test_1.expect)(this.generalPanel).toBeVisible({ timeout: 120000 });
602
+ const maxAttempts = 3;
603
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
604
+ // A second click would toggle an already-open dropdown shut, so never
605
+ // re-click when the previous attempt did open it.
606
+ const isOpen = await this.renameDiagramNameButton
607
+ .isVisible()
608
+ .catch(() => false);
609
+ if (isOpen) {
610
+ return;
611
+ }
612
+ try {
613
+ await this.diagramBreadcrumb.click({ timeout: 20000 });
614
+ await this.renameDiagramNameButton.waitFor({
615
+ state: 'visible',
616
+ timeout: 20000,
617
+ });
618
+ return;
619
+ }
620
+ catch (error) {
621
+ if (attempt === maxAttempts) {
622
+ throw error;
623
+ }
624
+ console.warn(`Diagram breadcrumb dropdown did not open ` +
625
+ `(attempt ${attempt}/${maxAttempts}). Retrying.`);
626
+ }
627
+ }
594
628
  }
595
629
  async clickEditDiagramNameButton() {
596
630
  await this.renameDiagramNameButton.click({ timeout: 60000 });
@@ -26,6 +26,8 @@ declare class ModelerHomePage {
26
26
  readonly messageBanner: Locator;
27
27
  readonly closeButton: Locator;
28
28
  readonly formNameBreadcrumb: (formName: string) => Locator;
29
+ readonly formBreadcrumbButton: Locator;
30
+ readonly renameFormMenuItem: Locator;
29
31
  constructor(page: Page);
30
32
  dismissOverlays(): Promise<void>;
31
33
  clickCreateNewProjectButton(): Promise<void>;
@@ -43,6 +45,7 @@ declare class ModelerHomePage {
43
45
  clickIdpApplicationTemplateOption(): Promise<void>;
44
46
  clickFormOption(): Promise<void>;
45
47
  enterFormName(name: string): Promise<void>;
48
+ openFormRenameEditor(): Promise<void>;
46
49
  clickProjectBreadcrumb(): Promise<void>;
47
50
  clickHomeBreadcrumb(): Promise<void>;
48
51
  clickOpenOrganizationsButton(): Promise<void>;
@@ -31,6 +31,8 @@ class ModelerHomePage {
31
31
  messageBanner;
32
32
  closeButton;
33
33
  formNameBreadcrumb;
34
+ formBreadcrumbButton;
35
+ renameFormMenuItem;
34
36
  constructor(page) {
35
37
  this.page = page;
36
38
  this.modelerPageBanner = page.getByRole('banner', {
@@ -77,6 +79,8 @@ class ModelerHomePage {
77
79
  this.formNameBreadcrumb = (formName) => page.locator('button[data-test="breadcrumb-form"]', {
78
80
  hasText: formName,
79
81
  });
82
+ this.formBreadcrumbButton = page.locator('button[data-test="breadcrumb-form"]');
83
+ this.renameFormMenuItem = page.locator('[data-test="rename-form"]');
80
84
  }
81
85
  async dismissOverlays() {
82
86
  for (const locator of [
@@ -177,10 +181,46 @@ class ModelerHomePage {
177
181
  async clickFormOption() {
178
182
  await this.formTemplateOption.click();
179
183
  }
184
+ // Right after a form is created the hub renders its breadcrumb name in
185
+ // inline-edit mode, but once the form store finishes loading it re-renders
186
+ // the breadcrumb as a plain dropdown button and the inline input is gone for
187
+ // good - Playwright then reports "element was detached from the DOM,
188
+ // retrying" until the click times out. The editor is re-openable through the
189
+ // breadcrumb's own Rename item (camunda-hub
190
+ // frontend/apps/hub/src/app/pages/form/Header.tsx), so fall back to that
191
+ // whenever the inline input is not there, and confirm the name landed.
180
192
  async enterFormName(name) {
181
- await this.formNameInput.click({ timeout: 60000 });
182
- await this.formNameInput.fill(name);
183
- await this.formNameInput.press('Enter');
193
+ const maxAttempts = 3;
194
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
195
+ try {
196
+ const editorOpen = await this.formNameInput
197
+ .waitFor({ state: 'visible', timeout: 15000 })
198
+ .then(() => true)
199
+ .catch(() => false);
200
+ if (!editorOpen) {
201
+ await this.openFormRenameEditor();
202
+ }
203
+ await this.formNameInput.click({ timeout: 30000 });
204
+ await this.formNameInput.fill(name);
205
+ await this.formNameInput.press('Enter');
206
+ await this.formNameBreadcrumb(name).waitFor({
207
+ state: 'visible',
208
+ timeout: 30000,
209
+ });
210
+ return;
211
+ }
212
+ catch (error) {
213
+ if (attempt === maxAttempts) {
214
+ throw error;
215
+ }
216
+ console.warn(`Form rename to "${name}" did not commit ` +
217
+ `(attempt ${attempt}/${maxAttempts}). Retrying.`);
218
+ }
219
+ }
220
+ }
221
+ async openFormRenameEditor() {
222
+ await this.formBreadcrumbButton.click({ timeout: 60000 });
223
+ await this.renameFormMenuItem.click({ timeout: 30000 });
184
224
  }
185
225
  async clickProjectBreadcrumb() {
186
226
  await this.projectBreadcrumb.click({ timeout: 60000 });
@@ -18,7 +18,25 @@
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.createInstances = exports.deploy = void 0;
20
20
  const zeebe_node_1 = require("zeebe-node");
21
- const zbc = new zeebe_node_1.ZBClient(); // localhost:26500 || ZEEBE_GATEWAY_ADDRESS
21
+ // zeebe-node defaults to `maxRetries: -1`, which its retryOnFailure() turns
22
+ // into `forever: true` with at most 5s between attempts. So an unreachable
23
+ // gateway is retried indefinitely and nothing ever throws: run 32136136238
24
+ // spent 3h18m emitting 75,236 "[deployWorkflow]: Attempt N (max: -1)" lines,
25
+ // reached attempt 719, and still reported the job as successful.
26
+ //
27
+ // Bound it so an unreachable broker surfaces as a fast, visible test failure
28
+ // instead of silently consuming the job budget. Roughly 15 attempts against
29
+ // the 5s ceiling is about a minute of grace -- enough to ride out a gateway
30
+ // restart, short enough to fail honestly.
31
+ //
32
+ // Must be > 0: ZBClient resolves this as `options.maxRetries || DEFAULT`, so a
33
+ // 0 would fall through to the -1 default and restore the infinite loop.
34
+ const parsedMaxRetries = Number(process.env.ZEEBE_CLIENT_MAX_RETRIES);
35
+ const maxRetries = Number.isFinite(parsedMaxRetries) && parsedMaxRetries > 0
36
+ ? parsedMaxRetries
37
+ : 15;
38
+ // localhost:26500 || ZEEBE_GATEWAY_ADDRESS
39
+ const zbc = new zeebe_node_1.ZBClient({ maxRetries });
22
40
  const deploy = (processNames) => {
23
41
  return zbc.deployProcess(processNames);
24
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.984",
3
+ "version": "0.0.986",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",