@camunda/e2e-test-suite 0.0.1021 → 0.0.1023
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.
- package/dist/pages/8.7/ClusterSecretsPage.d.ts +1 -0
- package/dist/pages/8.7/ClusterSecretsPage.js +45 -17
- package/dist/pages/8.7/UtilitiesPage.js +7 -1
- package/dist/pages/SM-8.10/ManagementIdentityPage.js +11 -14
- package/dist/pages/SM-8.10/OCIdentityClusterVariablesPage.js +27 -8
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@ declare class ClusterSecretsPage {
|
|
|
16
16
|
readonly confirmDeleteInput: Locator;
|
|
17
17
|
constructor(page: Page);
|
|
18
18
|
deleteConnectorSecretsIfExist(): Promise<void>;
|
|
19
|
+
private dismissOpenModal;
|
|
19
20
|
clickCreateNewSecretButton(clusterName: string): Promise<void>;
|
|
20
21
|
clickClusterBanner(): Promise<void>;
|
|
21
22
|
clickCluster(name: string): Promise<void>;
|
|
@@ -38,14 +38,25 @@ class ClusterSecretsPage {
|
|
|
38
38
|
name: 'Delete',
|
|
39
39
|
exact: true,
|
|
40
40
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// The confirmation modal's destructive action is a plain "Delete" button
|
|
42
|
+
// (Console renders Carbon's ModalFooter danger button, whose accessible
|
|
43
|
+
// name is just its label). The old 'danger Delete' name came from a Carbon
|
|
44
|
+
// version that prefixed danger buttons with a visually-hidden kind label;
|
|
45
|
+
// it matches nothing today, so the click timed out and left the modal open
|
|
46
|
+
// on top of the page. Scoped to the dialog so it cannot collide with the
|
|
47
|
+
// row-level Delete control behind it.
|
|
48
|
+
this.deleteConnectorSecretSubButton = page
|
|
49
|
+
.getByRole('dialog')
|
|
50
|
+
.getByRole('button', { name: 'Delete', exact: true });
|
|
44
51
|
this.dialog = page.getByRole('dialog');
|
|
45
52
|
this.clusterBanner = this.page
|
|
46
53
|
.getByRole('banner')
|
|
47
54
|
.getByRole('link', { name: 'Clusters' });
|
|
48
|
-
|
|
55
|
+
// exact: true because console-user-flows.spec.ts creates a second cluster
|
|
56
|
+
// called "UI Test Cluster" in the same org -- a substring match on
|
|
57
|
+
// "Test Cluster" then resolves to both links and fails on strict mode.
|
|
58
|
+
// ClusterPage's own cluster locators already match exactly.
|
|
59
|
+
this.clusterLink = (name) => page.getByRole('link', { name: name, exact: true });
|
|
49
60
|
this.clusterSecretTab = this.page.getByRole('tab', {
|
|
50
61
|
name: 'Connector Secrets',
|
|
51
62
|
});
|
|
@@ -95,13 +106,39 @@ class ClusterSecretsPage {
|
|
|
95
106
|
break;
|
|
96
107
|
}
|
|
97
108
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
// Console auto-provisions CAMUNDA_PROVIDED_LLM_* secrets whose Delete
|
|
110
|
+
// menu item is disabled, so the table is never empty once the sweep is
|
|
111
|
+
// done. A page-wide not.toBeVisible() therefore matched three Options
|
|
112
|
+
// buttons at once (strict mode violation) while asserting something that
|
|
113
|
+
// is no longer true. The post-condition this helper actually owns is
|
|
114
|
+
// that nothing *deletable* is left behind.
|
|
115
|
+
const deletableSecretRows = this.page
|
|
116
|
+
.getByRole('row')
|
|
117
|
+
.filter({ has: this.page.getByRole('cell', { name: 'Options' }) })
|
|
118
|
+
.filter({ hasNotText: 'CAMUNDA_PROVIDED_' });
|
|
119
|
+
await (0, test_1.expect)(deletableSecretRows).toHaveCount(0, { timeout: 30000 });
|
|
101
120
|
}
|
|
102
121
|
catch (error) {
|
|
103
122
|
console.error('Error during Connector Secrets deletion: ', error);
|
|
123
|
+
// A half-completed delete leaves Carbon's confirmation modal on screen,
|
|
124
|
+
// where its overlay swallows pointer events for every later click -- the
|
|
125
|
+
// next "Create new secret" click then burns its whole timeout against
|
|
126
|
+
// the overlay instead of the button. Cleanup must never hand the page
|
|
127
|
+
// back with a modal still open.
|
|
128
|
+
await this.dismissOpenModal();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Closes whichever Carbon modal is currently on screen, and waits for it to
|
|
132
|
+
// actually leave the DOM rather than assuming a fixed delay.
|
|
133
|
+
async dismissOpenModal() {
|
|
134
|
+
const openModal = this.page.locator('.cds--modal.is-visible');
|
|
135
|
+
if ((await openModal.count().catch(() => 0)) === 0) {
|
|
136
|
+
return;
|
|
104
137
|
}
|
|
138
|
+
await this.page.keyboard.press('Escape').catch(() => { });
|
|
139
|
+
await (0, test_1.expect)(openModal)
|
|
140
|
+
.toHaveCount(0, { timeout: 10000 })
|
|
141
|
+
.catch(() => { });
|
|
105
142
|
}
|
|
106
143
|
async clickCreateNewSecretButton(clusterName) {
|
|
107
144
|
try {
|
|
@@ -118,16 +155,7 @@ class ClusterSecretsPage {
|
|
|
118
155
|
}
|
|
119
156
|
}
|
|
120
157
|
async clickClusterBanner() {
|
|
121
|
-
|
|
122
|
-
const blockingModal = this.page.locator('.cds--modal.is-visible');
|
|
123
|
-
if ((await blockingModal.count()) > 0) {
|
|
124
|
-
await this.page.keyboard.press('Escape');
|
|
125
|
-
await (0, sleep_1.sleep)(1000);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch (_e) {
|
|
129
|
-
// no blocking modal to dismiss
|
|
130
|
-
}
|
|
158
|
+
await this.dismissOpenModal();
|
|
131
159
|
await (0, test_1.expect)(this.clusterBanner).toBeVisible({ timeout: 30000 });
|
|
132
160
|
await this.clusterBanner.click({ timeout: 60000 });
|
|
133
161
|
}
|
|
@@ -89,8 +89,14 @@ async function modelRestConnector(modelerCreatePage, connectorSettingsPage, proc
|
|
|
89
89
|
username: '',
|
|
90
90
|
password: '',
|
|
91
91
|
}) {
|
|
92
|
+
// 120s to match every other properties-panel wait in the 8.7 suite
|
|
93
|
+
// (modelJobWorkerDiagram, clickDiagramBreadcrumb and the specs' own waits all
|
|
94
|
+
// allow 90-200s). 30s was the lone outlier here and the bpmn-js properties
|
|
95
|
+
// panel regularly needs longer than that to mount on a freshly created
|
|
96
|
+
// diagram, which failed the REST connector flows before a single element was
|
|
97
|
+
// modelled.
|
|
92
98
|
await (0, test_1.expect)(modelerCreatePage.generalPanel).toBeVisible({
|
|
93
|
-
timeout:
|
|
99
|
+
timeout: 120000,
|
|
94
100
|
});
|
|
95
101
|
await modelerCreatePage.enterDiagramName(processName);
|
|
96
102
|
await (0, sleep_1.sleep)(10000);
|
|
@@ -46,16 +46,15 @@ class ManagementIdentityPage {
|
|
|
46
46
|
this.optimizeCheckbox = page
|
|
47
47
|
.locator('label')
|
|
48
48
|
.filter({ hasText: 'Optimize (Grants full access to Optimize)' });
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
this
|
|
57
|
-
|
|
58
|
-
});
|
|
49
|
+
// The chart's Keycloak preset (camunda-platform-helm#6896) renamed the Hub
|
|
50
|
+
// application and added "Hub"/"Hub Admin" roles while keeping the identical
|
|
51
|
+
// legacy "Web Modeler"/"Web Modeler Admin" roles for 8.10-alpha upgrades,
|
|
52
|
+
// so the straddle alternation that matched either wording now resolves to
|
|
53
|
+
// two rows and trips strict mode. Both roles grant the same permissions on
|
|
54
|
+
// the same application; target the go-forward "Hub" name, which is also
|
|
55
|
+
// what the chart assigns its own QA users. The `for` attribute is the role
|
|
56
|
+
// name, so this survives further description rewording.
|
|
57
|
+
this.modelerCheckbox = page.locator('label[for="Hub"]');
|
|
59
58
|
this.identityCheckbox = page.locator('label').filter({
|
|
60
59
|
hasText: 'ManagementIdentity (Provides full access to Management Identity)',
|
|
61
60
|
});
|
|
@@ -67,10 +66,8 @@ class ManagementIdentityPage {
|
|
|
67
66
|
this.licenseKeyTagNonCommercial = page.getByText('Non-commercial license');
|
|
68
67
|
this.licenseKeyTagProduction = page.getByText('Production license').first();
|
|
69
68
|
this.licenseKeyTagCommercial = page.getByText('Commercial license');
|
|
70
|
-
// Same
|
|
71
|
-
this.modelerAdminCheckbox = page.locator('label')
|
|
72
|
-
hasText: /(Web Modeler|Hub) Admin \(Grants elevated access to (Web Modeler|Hub)\)/,
|
|
73
|
-
});
|
|
69
|
+
// Same two-role split as `modelerCheckbox` above.
|
|
70
|
+
this.modelerAdminCheckbox = page.locator('label[for="Hub Admin"]');
|
|
74
71
|
this.openSidebarButton = page.getByLabel('Open User Sidebar');
|
|
75
72
|
this.logoutButton = page.getByRole('button', { name: 'Log out' });
|
|
76
73
|
this.orchestrationCheckbox = page.locator('label').filter({
|
|
@@ -21,19 +21,34 @@ class OCIdentityClusterVariablesPage {
|
|
|
21
21
|
editModalHeading;
|
|
22
22
|
constructor(page) {
|
|
23
23
|
this.page = page;
|
|
24
|
-
|
|
24
|
+
// The Admin UI is migrating off Carbon onto the Camunda design system:
|
|
25
|
+
// `identity/client/src/pages/cluster-variables/index.tsx` renders ListV2
|
|
26
|
+
// (design-system `DataTable`, Radix dialog/menu) when the
|
|
27
|
+
// `isNewDesignSystemEnabled` client config is on, which the orchestration
|
|
28
|
+
// server defaults to for Self-Managed. Released 8.10 alpha images predate
|
|
29
|
+
// ListV2 and still render Carbon, so the locators that differ between the
|
|
30
|
+
// two DOMs accept either.
|
|
31
|
+
this.variablesList = page.locator('table.cds--data-table, table[data-slot="table"]');
|
|
25
32
|
this.variableRow = (variableName) => this.variablesList
|
|
26
33
|
.locator('tbody')
|
|
27
34
|
.getByRole('row')
|
|
28
35
|
.filter({ hasText: variableName });
|
|
29
|
-
|
|
36
|
+
// Carbon's OverflowMenu labels its trigger "Options"; the design-system
|
|
37
|
+
// DataTable labels it "Row actions".
|
|
38
|
+
this.editVariableButton = (variableName) => this.variableRow(variableName).getByRole('button', {
|
|
39
|
+
name: /^(Options|Row actions)$/,
|
|
40
|
+
});
|
|
30
41
|
this.editVariableModal = page.getByRole('dialog', {
|
|
31
42
|
name: /Edit.*variable/i,
|
|
32
43
|
});
|
|
33
44
|
this.variableValueField = this.editVariableModal.getByRole('textbox', {
|
|
34
45
|
name: 'Editor content',
|
|
35
46
|
});
|
|
36
|
-
|
|
47
|
+
// Both modals pass `confirmLabel={t("save")}`, so the accessible name is
|
|
48
|
+
// stable across the two footers.
|
|
49
|
+
this.saveVariableButton = this.editVariableModal.getByRole('button', {
|
|
50
|
+
name: 'Save',
|
|
51
|
+
});
|
|
37
52
|
this.closeEditVariableModal = this.editVariableModal.getByRole('button', {
|
|
38
53
|
name: 'Close',
|
|
39
54
|
});
|
|
@@ -44,11 +59,15 @@ class OCIdentityClusterVariablesPage {
|
|
|
44
59
|
this.monacoEditorTextArea = this.monacoEditor.locator('textarea.inputarea');
|
|
45
60
|
this.monacoSuggestWidget = this.monacoEditor.locator('.editor-widget.suggest-widget');
|
|
46
61
|
this.successMessage = this.page.getByText('Cluster variable updated');
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
// Carbon renders the modal title as an h3, the design-system dialog as an
|
|
63
|
+
// h2; the heading role covers both.
|
|
64
|
+
this.editModalHeading = this.editVariableModal.getByRole('heading').first();
|
|
65
|
+
// Carbon menu items are buttons, Radix menu items are divs — match on the
|
|
66
|
+
// role instead of the tag.
|
|
67
|
+
this.editMenuItem = this.page.getByRole('menuitem', {
|
|
68
|
+
name: 'Edit',
|
|
69
|
+
exact: true,
|
|
70
|
+
});
|
|
52
71
|
}
|
|
53
72
|
async editVariable(variableName, newValue) {
|
|
54
73
|
await this.editVariableButton(variableName).click();
|