@camunda/e2e-test-suite 0.0.544 → 0.0.545

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.
@@ -29,6 +29,7 @@ declare class ModelerCreatePage {
29
29
  readonly cancelButton: Locator;
30
30
  readonly restConnectorOption: Locator;
31
31
  readonly marketPlaceButton: Locator;
32
+ private readonly changeTypeSearchInput;
32
33
  readonly clientIdTextbox: Locator;
33
34
  readonly clientSecretTextbox: Locator;
34
35
  readonly rememberCredentialsCheckbox: Locator;
@@ -134,6 +135,7 @@ declare class ModelerCreatePage {
134
135
  clickDeployButton(): Promise<void>;
135
136
  clickDeploySubButton(): Promise<void>;
136
137
  clickCancelButton(): Promise<void>;
138
+ private searchAndClickRestConnector;
137
139
  clickRestConnectorOption(): Promise<void>;
138
140
  clickMarketPlaceButton(): Promise<void>;
139
141
  completeDeploymentEndpointConfiguration(): Promise<void>;
@@ -34,6 +34,7 @@ class ModelerCreatePage {
34
34
  cancelButton;
35
35
  restConnectorOption;
36
36
  marketPlaceButton;
37
+ changeTypeSearchInput;
37
38
  clientIdTextbox;
38
39
  clientSecretTextbox;
39
40
  rememberCredentialsCheckbox;
@@ -148,6 +149,13 @@ class ModelerCreatePage {
148
149
  name: 'REST Outbound Connector',
149
150
  });
150
151
  this.marketPlaceButton = page.getByTitle('Browse Marketplace for more Connectors');
152
+ // Search input inside the Change element panel — used to filter the connector list
153
+ this.changeTypeSearchInput = page
154
+ .locator('div')
155
+ .filter({ hasText: /^Change element/ })
156
+ .locator('input')
157
+ .or(page.locator('[data-testid="search-field"] input'))
158
+ .first();
151
159
  this.clientIdTextbox = page.getByLabel('Client ID');
152
160
  this.clientSecretTextbox = page.getByLabel('Client secret');
153
161
  this.rememberCredentialsCheckbox = page.getByText('Remember credentials');
@@ -600,27 +608,47 @@ class ModelerCreatePage {
600
608
  async clickCancelButton() {
601
609
  await this.cancelButton.click();
602
610
  }
611
+ async searchAndClickRestConnector() {
612
+ // Fill the Change element search box with 'REST' to surface the connector
613
+ // regardless of scroll position. Wrapped in try/catch so a missing or
614
+ // unfocusable search box doesn't abort the attempt.
615
+ try {
616
+ await this.changeTypeSearchInput.fill('REST', { timeout: 5000 });
617
+ }
618
+ catch {
619
+ // Search box unavailable — connector may still be visible without filtering
620
+ }
621
+ await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
622
+ await this.restConnectorOption.click({ timeout: 90000 });
623
+ }
603
624
  async clickRestConnectorOption() {
604
625
  const maxRetries = 4;
605
626
  for (let retries = 0; retries < maxRetries; retries++) {
606
627
  try {
607
- if (retries > 0) {
608
- // The change-type panel may have closed; re-select the element and reopen it
628
+ if (retries === 0) {
629
+ // Panel already open from the caller (modelRestConnector in UtilitiesPage)
630
+ await this.searchAndClickRestConnector();
631
+ }
632
+ else if (retries === 1 || retries === 2) {
609
633
  await this.secondElement.click({ timeout: 60000 });
610
634
  await this.changeTypeButton.click({ force: true, 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
- }
635
+ await this.searchAndClickRestConnector();
636
+ }
637
+ else {
638
+ // Fourth attempt: install via marketplace in case connector is missing
639
+ await this.secondElement.click({ timeout: 60000 });
640
+ await this.changeTypeButton.click({ force: true, timeout: 60000 });
641
+ await this.clickMarketPlaceButton();
642
+ const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
643
+ await marketplace.clickSearchForConnectorTextbox();
644
+ await (0, sleep_1.sleep)(5000);
645
+ await marketplace.fillSearchForConnectorTextbox('REST Connector');
646
+ await marketplace.downloadConnectorToProject();
647
+ // Marketplace closes the change-type panel; reopen it so the
648
+ // newly installed connector appears in the list.
649
+ await this.changeTypeButton.click({ force: true, timeout: 60000 });
650
+ await this.searchAndClickRestConnector();
621
651
  }
622
- await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
623
- await this.restConnectorOption.click({ timeout: 90000 });
624
652
  return;
625
653
  }
626
654
  catch (error) {
@@ -13,6 +13,7 @@ declare class OperateProcessesPage {
13
13
  readonly processInstanceKeyTextBox: Locator;
14
14
  private readonly whatsNewPopUp;
15
15
  private readonly gotItButton;
16
+ private readonly processesTabLink;
16
17
  constructor(page: Page);
17
18
  private checkCheckbox;
18
19
  private uncheckCheckbox;
@@ -19,21 +19,17 @@ class OperateProcessesPage {
19
19
  processInstanceKeyTextBox;
20
20
  whatsNewPopUp;
21
21
  gotItButton;
22
+ processesTabLink;
22
23
  constructor(page) {
23
24
  this.page = page;
24
25
  this.processResultCount = page.getByTestId('result-count');
25
- this.processActiveCheckbox = page
26
- .locator('label')
27
- .filter({ hasText: 'Active' });
28
- this.processCompletedCheckbox = page
29
- .locator('label')
30
- .filter({ hasText: 'Completed' });
26
+ this.processesTabLink = page.getByRole('link', { name: 'Processes' });
27
+ this.processActiveCheckbox = page.locator('input#active');
28
+ this.processCompletedCheckbox = page.locator('input#completed');
31
29
  this.processRunningInstancesCheckbox = page
32
- .locator('label')
33
- .filter({ hasText: 'Running Instances' });
34
- this.processIncidentsCheckbox = page
35
- .locator('label')
36
- .filter({ hasText: 'Incidents' });
30
+ .getByTestId('filter-running-instances')
31
+ .getByRole('checkbox');
32
+ this.processIncidentsCheckbox = page.locator('input#incidents');
37
33
  this.processPageHeading = page
38
34
  .getByTestId('expanded-panel')
39
35
  .getByRole('heading', { name: 'Process' });
@@ -51,22 +47,22 @@ class OperateProcessesPage {
51
47
  this.gotItButton = page.getByRole('button', { name: 'Got it' });
52
48
  }
53
49
  async checkCheckbox(checkbox) {
54
- await checkbox.waitFor({ state: 'visible', timeout: constants_1._1_SECOND_IN_MS * 10 });
50
+ await checkbox.waitFor({ state: 'attached', timeout: constants_1._1_SECOND_IN_MS * 10 });
55
51
  if (!(await checkbox.isChecked())) {
56
- await checkbox.click();
52
+ await checkbox.check({ force: true, timeout: constants_1._1_SECOND_IN_MS * 30 });
57
53
  await (0, test_1.expect)(checkbox).toBeChecked({
58
54
  checked: true,
59
- timeout: constants_1._1_SECOND_IN_MS * 2,
55
+ timeout: constants_1._1_SECOND_IN_MS * 10,
60
56
  });
61
57
  }
62
58
  }
63
59
  async uncheckCheckbox(checkbox) {
64
- await checkbox.waitFor({ state: 'visible', timeout: constants_1._1_SECOND_IN_MS * 10 });
60
+ await checkbox.waitFor({ state: 'attached', timeout: constants_1._1_SECOND_IN_MS * 10 });
65
61
  if (await checkbox.isChecked()) {
66
- await checkbox.click();
62
+ await checkbox.uncheck({ force: true, timeout: constants_1._1_SECOND_IN_MS * 30 });
67
63
  await (0, test_1.expect)(checkbox).toBeChecked({
68
64
  checked: false,
69
- timeout: constants_1._1_SECOND_IN_MS * 2,
65
+ timeout: constants_1._1_SECOND_IN_MS * 10,
70
66
  });
71
67
  }
72
68
  }
@@ -80,7 +76,7 @@ class OperateProcessesPage {
80
76
  await this.uncheckCompletedCheckbox();
81
77
  await this.clickProcessIncidentsCheckbox();
82
78
  await this.processActiveCheckbox.waitFor({
83
- state: 'visible',
79
+ state: 'attached',
84
80
  timeout: constants_1._1_SECOND_IN_MS * 10,
85
81
  });
86
82
  if (await this.processActiveCheckbox.isChecked({ timeout: constants_1._1_SECOND_IN_MS })) {
@@ -96,7 +92,7 @@ class OperateProcessesPage {
96
92
  await this.uncheckActiveCheckbox();
97
93
  await this.clickProcessIncidentsCheckbox();
98
94
  await this.processCompletedCheckbox.waitFor({
99
- state: 'visible',
95
+ state: 'attached',
100
96
  timeout: constants_1._1_SECOND_IN_MS * 10,
101
97
  });
102
98
  if (await this.processCompletedCheckbox.isChecked({ timeout: constants_1._1_SECOND_IN_MS })) {
@@ -140,11 +136,11 @@ class OperateProcessesPage {
140
136
  }
141
137
  async clickProcessActiveCheckbox() {
142
138
  await this.processActiveCheckbox.waitFor({
143
- state: 'visible',
139
+ state: 'attached',
144
140
  timeout: constants_1._1_SECOND_IN_MS * 10,
145
141
  });
146
- if (!(await this.processActiveCheckbox.isChecked({ timeout: 60000 }))) {
147
- await this.processActiveCheckbox.click({ timeout: 120000 });
142
+ if (!(await this.processActiveCheckbox.isChecked())) {
143
+ await this.processActiveCheckbox.check({ force: true, timeout: 120000 });
148
144
  await (0, test_1.expect)(this.processActiveCheckbox).toBeChecked({
149
145
  checked: true,
150
146
  timeout: constants_1._1_SECOND_IN_MS * 5,
@@ -153,11 +149,11 @@ class OperateProcessesPage {
153
149
  }
154
150
  async clickProcessCompletedCheckbox() {
155
151
  await this.processCompletedCheckbox.waitFor({
156
- state: 'visible',
152
+ state: 'attached',
157
153
  timeout: constants_1._1_SECOND_IN_MS * 10,
158
154
  });
159
- if (!(await this.processCompletedCheckbox.isChecked({ timeout: 60000 }))) {
160
- await this.processCompletedCheckbox.click({ timeout: 120000 });
155
+ if (!(await this.processCompletedCheckbox.isChecked())) {
156
+ await this.processCompletedCheckbox.check({ force: true, timeout: 120000 });
161
157
  await (0, test_1.expect)(this.processCompletedCheckbox).toBeChecked({
162
158
  checked: true,
163
159
  timeout: constants_1._1_SECOND_IN_MS * 5,
@@ -166,11 +162,19 @@ class OperateProcessesPage {
166
162
  }
167
163
  async clickProcessIncidentsCheckbox() {
168
164
  await this.processIncidentsCheckbox.waitFor({
169
- state: 'visible',
165
+ state: 'attached',
170
166
  timeout: constants_1._1_SECOND_IN_MS * 10,
171
167
  });
172
168
  const wasChecked = await this.processIncidentsCheckbox.isChecked();
173
- await this.processIncidentsCheckbox.click({ timeout: 90000 });
169
+ if (wasChecked) {
170
+ await this.processIncidentsCheckbox.uncheck({
171
+ force: true,
172
+ timeout: 90000,
173
+ });
174
+ }
175
+ else {
176
+ await this.processIncidentsCheckbox.check({ force: true, timeout: 90000 });
177
+ }
174
178
  await (0, test_1.expect)(this.processIncidentsCheckbox).toBeChecked({
175
179
  checked: !wasChecked,
176
180
  timeout: constants_1._1_SECOND_IN_MS * 5,
@@ -178,11 +182,22 @@ class OperateProcessesPage {
178
182
  }
179
183
  async clickRunningProcessInstancesCheckbox() {
180
184
  await this.processRunningInstancesCheckbox.waitFor({
181
- state: 'visible',
185
+ state: 'attached',
182
186
  timeout: constants_1._1_SECOND_IN_MS * 10,
183
187
  });
184
188
  const wasChecked = await this.processRunningInstancesCheckbox.isChecked();
185
- await this.processRunningInstancesCheckbox.click({ timeout: 90000 });
189
+ if (wasChecked) {
190
+ await this.processRunningInstancesCheckbox.uncheck({
191
+ force: true,
192
+ timeout: 90000,
193
+ });
194
+ }
195
+ else {
196
+ await this.processRunningInstancesCheckbox.check({
197
+ force: true,
198
+ timeout: 90000,
199
+ });
200
+ }
186
201
  await (0, test_1.expect)(this.processRunningInstancesCheckbox).toBeChecked({
187
202
  checked: !wasChecked,
188
203
  timeout: constants_1._1_SECOND_IN_MS * 5,
@@ -206,7 +221,9 @@ class OperateProcessesPage {
206
221
  return;
207
222
  }
208
223
  const MAX_ATTEMPTS = 30;
209
- const TOTAL_TIMEOUT_MS = constants_1._1_MINUTE_IN_MS * 6;
224
+ const TOTAL_TIMEOUT_MS = env_1.isOpenSearch
225
+ ? constants_1._1_MINUTE_IN_MS * 10
226
+ : constants_1._1_MINUTE_IN_MS * 6;
210
227
  let attempt = 0;
211
228
  let lastError;
212
229
  const startTime = Date.now();
@@ -239,6 +256,22 @@ class OperateProcessesPage {
239
256
  .waitForLoadState('networkidle', { timeout: 30000 })
240
257
  .catch(() => console.log('waitForLoadState after Operate navigation timed out, continuing...'));
241
258
  }
259
+ // Operate may land on the Dashboard after reload even when the captured
260
+ // URL pointed at the Processes view. The filter checkboxes only exist on
261
+ // the Processes tab, so navigate there explicitly before applying filters.
262
+ try {
263
+ await this.processesTabLink.waitFor({
264
+ state: 'visible',
265
+ timeout: constants_1._1_SECOND_IN_MS * 10,
266
+ });
267
+ await this.processesTabLink.click({ timeout: constants_1._1_SECOND_IN_MS * 10 });
268
+ await this.page
269
+ .waitForLoadState('networkidle', { timeout: 30000 })
270
+ .catch(() => { });
271
+ }
272
+ catch (navErr) {
273
+ console.log(`Processes tab click failed after reload: ${String(navErr)}`);
274
+ }
242
275
  // Re-apply checkbox filter lost after reload
243
276
  try {
244
277
  await this.applyProcessStateFilter(type);
@@ -246,6 +279,20 @@ class OperateProcessesPage {
246
279
  catch (toggleErr) {
247
280
  console.log(`Checkbox toggle failed after reload: ${String(toggleErr)}`);
248
281
  }
282
+ // Re-fill Process Instance Key filter if it was previously applied
283
+ // but its value was cleared by the reload.
284
+ try {
285
+ const isFilterVisible = await this.processInstanceKeyTextBox.isVisible();
286
+ if (isFilterVisible) {
287
+ const currentValue = await this.processInstanceKeyTextBox.inputValue();
288
+ if (!currentValue) {
289
+ await this.processInstanceKeyTextBox.fill(processName);
290
+ }
291
+ }
292
+ }
293
+ catch {
294
+ // Filter input not available, skip
295
+ }
249
296
  await (0, sleep_1.sleep)(2000);
250
297
  }
251
298
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.544",
3
+ "version": "0.0.545",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",