@camunda/e2e-test-suite 0.0.1379 → 0.0.1380

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.
@@ -24,6 +24,7 @@ declare class ClusterPage {
24
24
  readonly clusterVersionOption: Locator;
25
25
  readonly generationSearchInput: Locator;
26
26
  readonly g3DevClusterType: Locator;
27
+ readonly clusterRegion: (clusterName: string, regionText: string) => Locator;
27
28
  readonly alphaTab: Locator;
28
29
  readonly devTab: Locator;
29
30
  readonly stableTab: Locator;
@@ -49,7 +50,7 @@ declare class ClusterPage {
49
50
  fillClusterNameInput(name: string): Promise<void>;
50
51
  private extractClusterIdFromUrl;
51
52
  private logClusterCreationInfo;
52
- createCluster(name: string, region?: string, tasklistV1Api?: boolean): Promise<void>;
53
+ createCluster(name: string, region?: string, tasklistV1Api?: boolean, subRegion?: string): Promise<void>;
53
54
  determineTasklistAPI(tasklistV1Api?: boolean): Promise<void>;
54
55
  clickClusterType(): Promise<void>;
55
56
  clickCreateClusterButton(): Promise<void>;
@@ -89,7 +90,7 @@ declare class ClusterPage {
89
90
  clickDevTab(): Promise<void>;
90
91
  clickStableTab(): Promise<void>;
91
92
  clickQAGenerationsTab(): Promise<void>;
92
- selectSubRegion(region: string): Promise<void>;
93
+ selectSubRegion(region: string, subRegion?: string): Promise<void>;
93
94
  clickGCPRegion(): Promise<void>;
94
95
  clickTasklistV1Api(): Promise<void>;
95
96
  }
@@ -29,6 +29,7 @@ class ClusterPage {
29
29
  clusterVersionOption;
30
30
  generationSearchInput;
31
31
  g3DevClusterType;
32
+ clusterRegion;
32
33
  alphaTab;
33
34
  devTab;
34
35
  stableTab;
@@ -141,6 +142,7 @@ class ClusterPage {
141
142
  });
142
143
  this.dialog = page.getByRole('dialog');
143
144
  this.clusterVersion = (clusterName, versionText) => this.clusterRow(clusterName).getByText(versionText, { exact: false });
145
+ this.clusterRegion = (clusterName, regionText) => this.clusterRow(clusterName).getByText(regionText, { exact: false });
144
146
  }
145
147
  async clickClusterBanner() {
146
148
  // Camunda Hub has no `banner` landmark; "Clusters" instead lives in its
@@ -273,7 +275,7 @@ class ClusterPage {
273
275
  console.warn(`⚠️ Could not extract cluster info for "${clusterName}": ${error}`);
274
276
  }
275
277
  }
276
- async createCluster(name, region = 'GCP', tasklistV1Api) {
278
+ async createCluster(name, region = 'GCP', tasklistV1Api, subRegion) {
277
279
  await this.clickClusterTab();
278
280
  await this.deleteCluster(name);
279
281
  await this.clickCreateNewClusterButton();
@@ -288,7 +290,7 @@ class ClusterPage {
288
290
  .getByRole('tab', { name: region })
289
291
  .or(this.page.getByRole('radio', { name: region, exact: true }))
290
292
  .click();
291
- await this.selectSubRegion(region);
293
+ await this.selectSubRegion(region, subRegion);
292
294
  await this.clickClusterOption();
293
295
  await this.determineTasklistAPI(tasklistV1Api);
294
296
  await this.clickCreateClusterButton();
@@ -616,7 +618,29 @@ class ClusterPage {
616
618
  async clickQAGenerationsTab() {
617
619
  await this.qaGenerationsTab.click();
618
620
  }
619
- async selectSubRegion(region) {
621
+ async selectSubRegion(region, subRegion) {
622
+ // An explicit sub-region makes the choice reproducible. The default below
623
+ // picks at random, which is right for a test that only needs *a* cluster
624
+ // but wrong for one that has to know which region the cluster is in --
625
+ // console-cluster-duplication asserts that an overridden region beat the
626
+ // carried-over one, and a random source region can collide with the
627
+ // override and make that assertion vacuous.
628
+ if (subRegion) {
629
+ const known = {
630
+ Belgium: this.belgiumRegion,
631
+ Finland: this.finlandRegion,
632
+ London: this.londonRegion,
633
+ Ohio: this.ohioRegion,
634
+ };
635
+ const locator = known[subRegion];
636
+ if (!locator) {
637
+ throw new Error(`Unknown sub-region "${subRegion}". Known: ${Object.keys(known).join(', ')}`);
638
+ }
639
+ console.log(`Selected region: ${subRegion}`);
640
+ await (0, test_1.expect)(locator).toBeVisible({ timeout: 20000 });
641
+ await locator.click();
642
+ return;
643
+ }
620
644
  if (region === 'GCP') {
621
645
  if (process.env.IS_PROD == 'true') {
622
646
  await (0, test_1.expect)(this.londonRegion).toBeVisible({ timeout: 20000 });
@@ -10,6 +10,16 @@ const users_1 = require("../../utils/users");
10
10
  // reads C8_USERNAME_TEST, which is not a member of the run's org (and is not
11
11
  // exported at all in the nightly test job, so fill() received undefined).
12
12
  const testUser = (0, users_1.getTestUser)('mainUser');
13
+ // The two GCP sub-regions a non-prod org can create in. DUP-02 pins the source
14
+ // to one and overrides to the other: left to its default selectSubRegion()
15
+ // picks at random, and a source that lands on the override's region makes
16
+ // "the override won" indistinguishable from "the source value carried over".
17
+ // The strings are the rendered tile labels, not display names -- see the
18
+ // belgiumRegion/finlandRegion locators in pages/8.10/ClusterPage.ts.
19
+ const SOURCE_SUB_REGION = 'Belgium';
20
+ const OVERRIDE_SUB_REGION = 'Finland';
21
+ const SOURCE_REGION_LABEL = 'Chaos, Belgium, Europe (europe-west1)';
22
+ const OVERRIDE_REGION_LABEL = 'Finland, Europe (europe-north1)';
13
23
  /**
14
24
  * Epic: camunda/product-hub#3824 - Console cluster duplication.
15
25
  *
@@ -136,4 +146,95 @@ _8_10_1.test.describe('Console cluster duplication', () => {
136
146
  await clusterDetailsPage.assertComponentsHealth();
137
147
  });
138
148
  });
149
+ // Scoped to name and region. The epic's case also lists plan type, channel
150
+ // and generation, but neither is overridable through today's page object:
151
+ // ClusterPage models exactly one cluster type (defaultClusterType =
152
+ // 'G3-Dev'), and createCluster() already drives the source through the same
153
+ // clickClusterOption() the duplicate would use, so both land on the same
154
+ // generation and an "override" assertion would pass without overriding
155
+ // anything. Asserting a value the test never set is what the first draft of
156
+ // this case did. Covering them needs page-object work first.
157
+ (0, _8_10_1.test)('DUP-02: a name and region overridden on the duplication form win over the carried-over ones', async ({ page, homePage, clusterPage, clusterDetailsPage, clusterSecretsPage, }) => {
158
+ // Two cluster creations plus health polling - this case is long by nature.
159
+ _8_10_1.test.setTimeout(60 * 60 * 1000);
160
+ const randomSuffix = await (0, _setup_1.generateRandomStringAsync)(6);
161
+ const sourceClusterName = `dup-src-ovr-${randomSuffix}`;
162
+ const duplicateClusterName = `dup-ovr-${randomSuffix}`;
163
+ await _8_10_1.test.step('given a healthy source cluster in a known region with its settings populated', async () => {
164
+ await clusterPage.clickClusterTab();
165
+ createdClusterNames.push(sourceClusterName);
166
+ // Pin the source region explicitly: the override below must differ from
167
+ // it, otherwise "the override won" is indistinguishable from "carried
168
+ // over". The second argument is the cloud provider, the fourth the
169
+ // sub-region -- passing a region label as the provider matches no tab.
170
+ await clusterPage.createCluster(sourceClusterName, 'GCP', undefined, SOURCE_SUB_REGION);
171
+ await clusterPage.assertClusterHealthyStatusWithRetry(sourceClusterName);
172
+ // A populated source - against an empty one this case would pass by
173
+ // copying nothing at all.
174
+ await clusterSecretsPage.createNewSecret(`DUP_SECRET_${randomSuffix}`, `dup-secret-value-${randomSuffix}`, sourceClusterName);
175
+ });
176
+ await _8_10_1.test.step('when I override the name and the region before submitting', async () => {
177
+ await homePage.clickClusters();
178
+ await clusterPage.clickClusterLink(sourceClusterName);
179
+ await clusterDetailsPage.dismissOopsIfPresent();
180
+ await (0, UtilitiesPage_1.waitForLoadingToFinish)(page);
181
+ await page.getByRole('button', { name: 'cluster operations' }).click();
182
+ const duplicateAction = page
183
+ .getByRole('menuitem', { name: /duplicate/i })
184
+ .or(page.getByRole('button', { name: /duplicate/i }));
185
+ await (0, test_1.expect)(duplicateAction).toBeVisible({ timeout: 30000 });
186
+ await duplicateAction.click();
187
+ // Every editable field of the duplication form, changed away from the
188
+ // value the form carried over from the source cluster.
189
+ await clusterPage.clickClusterNameInput();
190
+ await clusterPage.fillClusterNameInput(duplicateClusterName);
191
+ // clickGCPRegion only acts when REGION_SELECTION is set, so the tile
192
+ // click below is what actually moves the region either way.
193
+ await clusterPage.clickGCPRegion();
194
+ await clusterPage.selectSubRegion('GCP', OVERRIDE_SUB_REGION);
195
+ createdClusterNames.push(duplicateClusterName);
196
+ const submitDuplicate = page.getByRole('button', {
197
+ name: 'Duplicate cluster',
198
+ exact: true,
199
+ });
200
+ await (0, test_1.expect)(submitDuplicate).toBeEnabled({ timeout: 30000 });
201
+ // Same as DUP-01: hold the page until the duplicate POST has answered,
202
+ // otherwise navigating away aborts the in-flight request.
203
+ const duplicateResponse = page.waitForResponse((response) => response.request().method() === 'POST' &&
204
+ /\/clusters\/[^/]+\/duplicate$/.test(new URL(response.url()).pathname), { timeout: 60000 });
205
+ await submitDuplicate.click();
206
+ const duplicate = await duplicateResponse;
207
+ (0, test_1.expect)(duplicate.ok()).toBe(true);
208
+ const { clusterId } = await duplicate.json();
209
+ await page.waitForURL(new RegExp(`/cluster/${clusterId}`), {
210
+ timeout: 60000,
211
+ });
212
+ });
213
+ await _8_10_1.test.step('then the created duplicate carries the overridden values, not the source ones, and is healthy', async () => {
214
+ await homePage.clickClusters();
215
+ await (0, UtilitiesPage_1.waitForLoadingToFinish)(page);
216
+ // The overridden name is what the cluster was actually created with.
217
+ await (0, test_1.expect)(clusterPage.clusterLink(duplicateClusterName)).toBeVisible({
218
+ timeout: 60000,
219
+ });
220
+ await (0, test_1.expect)(clusterPage.clusterLink(sourceClusterName)).toBeVisible();
221
+ // The result, not the form state: the row of the cluster that was really
222
+ // created carries the overridden region. Scoped to that row rather than
223
+ // read off a page-wide getByText -- the source cluster is still listed
224
+ // on this same page and carries the region the override had to beat.
225
+ await (0, test_1.expect)(clusterPage.clusterRegion(duplicateClusterName, OVERRIDE_REGION_LABEL)).toBeVisible({ timeout: 60000 });
226
+ // ...and not the one it would have inherited from the source. Asserted
227
+ // after the positive check above, so an empty row cannot pass it.
228
+ await (0, test_1.expect)(clusterPage.clusterRegion(duplicateClusterName, SOURCE_REGION_LABEL)).toHaveCount(0);
229
+ // The source kept its own region, which is what makes the two labels
230
+ // above a real comparison rather than two reads of the same cluster.
231
+ await (0, test_1.expect)(clusterPage.clusterRegion(sourceClusterName, SOURCE_REGION_LABEL)).toBeVisible();
232
+ // Completion rule: a duplicate that is created but never healthy is the
233
+ // failure this epic exists to prevent.
234
+ await clusterPage.assertClusterHealthyStatusWithRetry(duplicateClusterName);
235
+ await clusterPage.clickClusterLink(duplicateClusterName);
236
+ await clusterDetailsPage.dismissOopsIfPresent();
237
+ await clusterDetailsPage.assertComponentsHealth();
238
+ });
239
+ });
139
240
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/e2e-test-suite",
3
- "version": "0.0.1379",
3
+ "version": "0.0.1380",
4
4
  "description": "End-to-end test helpers for Camunda 8",
5
5
  "repository": {
6
6
  "type": "git",