@camunda/e2e-test-suite 0.0.1008 → 0.0.1010
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.10/FormJsPage.d.ts +2 -0
- package/dist/pages/8.10/FormJsPage.js +59 -1
- package/dist/pages/8.10/ModelerCreatePage.d.ts +1 -0
- package/dist/pages/8.10/ModelerCreatePage.js +139 -20
- package/dist/pages/8.10/ModelerHomePage.d.ts +12 -0
- package/dist/pages/8.10/ModelerHomePage.js +153 -12
- package/dist/pages/8.10/ProcessApplicationPage.d.ts +29 -0
- package/dist/pages/8.10/ProcessApplicationPage.js +237 -0
- package/dist/pages/8.10/UtilitiesPage.js +8 -0
- package/dist/pages/SM-8.10/FormJsPage.d.ts +1 -0
- package/dist/pages/SM-8.10/FormJsPage.js +26 -0
- package/dist/pages/SM-8.10/ModelerCreatePage.js +58 -16
- package/dist/pages/SM-8.10/ModelerHomePage.d.ts +11 -0
- package/dist/pages/SM-8.10/ModelerHomePage.js +154 -9
- package/dist/pages/SM-8.10/ProcessApplicationPage.d.ts +23 -0
- package/dist/pages/SM-8.10/ProcessApplicationPage.js +132 -0
- package/dist/pages/SM-8.10/UtilitiesPage.js +8 -0
- package/dist/tests/8.10/access-user-role-management.spec.js +3 -3
- package/dist/tests/8.10/idp-user-flows.spec.js +9 -3
- package/package.json +1 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProcessApplicationPage = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
const submitModalWithRetry_1 = require("../../utils/assertionHelpers/submitModalWithRetry");
|
|
6
|
+
// Which process application holds the current test's resources, and which
|
|
7
|
+
// cluster its development stage currently points at. Keyed by the Playwright
|
|
8
|
+
// Page because the object that creates the container (ModelerHomePage) and the
|
|
9
|
+
// objects that later need a specific cluster inside it (ModelerCreatePage,
|
|
10
|
+
// FormJsPage) hold separate ProcessApplicationPage instances but share one page.
|
|
11
|
+
const resourceContainers = new WeakMap();
|
|
12
|
+
// Since camunda/camunda-hub#25831 a process application is a first-class
|
|
13
|
+
// container rather than a folder, and a workspace root ("project" in today's
|
|
14
|
+
// UI) holds nothing but process applications and IDP applications. Every file
|
|
15
|
+
// and folder this suite creates therefore has to live inside a process
|
|
16
|
+
// application. This page object owns that container's surface only; entering
|
|
17
|
+
// and leaving it is driven from ModelerHomePage so the ~150 existing spec call
|
|
18
|
+
// sites keep working unchanged.
|
|
19
|
+
class ProcessApplicationPage {
|
|
20
|
+
page;
|
|
21
|
+
// Empty workspace root: a plain primary button rendered next to the "Create
|
|
22
|
+
// new" menu (hub's EmptyStateActionButtons).
|
|
23
|
+
createProcessApplicationButton;
|
|
24
|
+
// Non-empty root: the item inside the "Create new" menu. Hub passes
|
|
25
|
+
// hideProcessApplication at workspace level, so this is the fallback rather
|
|
26
|
+
// than the primary path -- its own unit test asserts the item is absent
|
|
27
|
+
// there. Kept because the Hub PR is still moving this surface.
|
|
28
|
+
createProcessApplicationOption;
|
|
29
|
+
creationDialog;
|
|
30
|
+
nameInput;
|
|
31
|
+
submitButton;
|
|
32
|
+
cancelButton;
|
|
33
|
+
breadcrumb;
|
|
34
|
+
folderExplorer;
|
|
35
|
+
createNewDropdown;
|
|
36
|
+
inlineNameInput;
|
|
37
|
+
// "Define stages" dialog, reached from the process application's "Connected
|
|
38
|
+
// clusters" card (or its /connected-clusters deep link). Assigning a cluster
|
|
39
|
+
// to a stage here is what makes it deployable: DeployModal renders
|
|
40
|
+
// ProcessAppClusterSelection for a process application, and that filters the
|
|
41
|
+
// cluster list through getProcessAppClustersByStage -- so a process
|
|
42
|
+
// application with no stage assigned offers no cluster at all.
|
|
43
|
+
defineStagesDialog;
|
|
44
|
+
developmentClusterSelect;
|
|
45
|
+
defineStagesSaveButton;
|
|
46
|
+
constructor(page) {
|
|
47
|
+
this.page = page;
|
|
48
|
+
// .first() defensively only: hub renders exactly one of these today, in the
|
|
49
|
+
// workspace-root empty state. A future second placement should not turn
|
|
50
|
+
// every PA-creating test into a strict-mode violation.
|
|
51
|
+
this.createProcessApplicationButton = page
|
|
52
|
+
.getByRole('button', { name: 'Create process application' })
|
|
53
|
+
.first();
|
|
54
|
+
this.createProcessApplicationOption = page.locator('[data-test="create-process-application"]');
|
|
55
|
+
this.creationDialog = page.getByRole('dialog', {
|
|
56
|
+
name: 'Create a process application',
|
|
57
|
+
});
|
|
58
|
+
// Deliberately scoped to the dialog: ModelerCreatePage owns an unscoped
|
|
59
|
+
// getByLabel('Name', {exact: true}) for the properties panel, which would
|
|
60
|
+
// resolve to two elements while the creation modal is open.
|
|
61
|
+
this.nameInput = this.creationDialog.getByLabel('Name', { exact: true });
|
|
62
|
+
this.submitButton = this.creationDialog.getByRole('button', {
|
|
63
|
+
name: 'Create',
|
|
64
|
+
exact: true,
|
|
65
|
+
});
|
|
66
|
+
this.cancelButton = this.creationDialog.getByRole('button', {
|
|
67
|
+
name: 'Cancel',
|
|
68
|
+
exact: true,
|
|
69
|
+
});
|
|
70
|
+
this.breadcrumb = page.locator('[data-test="breadcrumb-process-application-menu"]');
|
|
71
|
+
this.folderExplorer = page.getByRole('region', { name: 'Folder explorer' });
|
|
72
|
+
// The process application page renders more than one diagram-dropdown
|
|
73
|
+
// (hub's own unit tests reach for it with getAllByTestId), so the dropdown
|
|
74
|
+
// has to be resolved inside the folder explorer rather than page-wide.
|
|
75
|
+
this.createNewDropdown = this.folderExplorer
|
|
76
|
+
.locator('[data-test="diagram-dropdown"]')
|
|
77
|
+
.first();
|
|
78
|
+
this.inlineNameInput = page.locator('[data-test="editable-input"]');
|
|
79
|
+
this.defineStagesDialog = page
|
|
80
|
+
.getByRole('dialog')
|
|
81
|
+
.filter({ hasText: 'Define stages' });
|
|
82
|
+
// Carbon Dropdown / design-system Select both keep this id.
|
|
83
|
+
this.developmentClusterSelect = this.defineStagesDialog.locator('#dropdown-development-cluster');
|
|
84
|
+
this.defineStagesSaveButton = this.defineStagesDialog.getByRole('button', {
|
|
85
|
+
name: 'Save',
|
|
86
|
+
exact: true,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Either the folder explorer or the breadcrumb proves we are on the process
|
|
90
|
+
// application page; .first() because both are present once it has rendered.
|
|
91
|
+
pageReady() {
|
|
92
|
+
return this.folderExplorer.or(this.breadcrumb).first();
|
|
93
|
+
}
|
|
94
|
+
async waitForProcessApplication(timeout = 90000) {
|
|
95
|
+
await (0, test_1.expect)(this.pageReady()).toBeVisible({ timeout });
|
|
96
|
+
}
|
|
97
|
+
async clickCreateProcessApplicationButton() {
|
|
98
|
+
await (0, test_1.expect)(this.createProcessApplicationButton).toBeVisible({
|
|
99
|
+
timeout: 60000,
|
|
100
|
+
});
|
|
101
|
+
await this.createProcessApplicationButton.click({ timeout: 60000 });
|
|
102
|
+
}
|
|
103
|
+
async clickCreateProcessApplicationOption() {
|
|
104
|
+
await (0, test_1.expect)(this.createProcessApplicationOption).toBeVisible({
|
|
105
|
+
timeout: 60000,
|
|
106
|
+
});
|
|
107
|
+
await this.createProcessApplicationOption.click({ timeout: 60000 });
|
|
108
|
+
}
|
|
109
|
+
// Hub creates a process application through a modal today. It used an inline
|
|
110
|
+
// editable title before, and #27593 is still moving this surface, so the
|
|
111
|
+
// inline path is kept as a fallback — this is the one method that has to
|
|
112
|
+
// change if naming moves back inline.
|
|
113
|
+
async nameNewProcessApplication(name) {
|
|
114
|
+
const isModal = await this.creationDialog
|
|
115
|
+
.waitFor({ state: 'visible', timeout: 15000 })
|
|
116
|
+
.then(() => true)
|
|
117
|
+
.catch(() => false);
|
|
118
|
+
if (isModal) {
|
|
119
|
+
await this.nameInput.click({ timeout: 30000 });
|
|
120
|
+
await this.nameInput.fill(name);
|
|
121
|
+
await (0, test_1.expect)(this.nameInput).toHaveValue(name, { timeout: 10000 });
|
|
122
|
+
await (0, submitModalWithRetry_1.submitModalWithRetry)(this.submitButton, this.creationDialog);
|
|
123
|
+
await this.waitForProcessApplication();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
await (0, test_1.expect)(this.inlineNameInput).toBeVisible({ timeout: 30000 });
|
|
127
|
+
await this.inlineNameInput.click({ timeout: 60000 });
|
|
128
|
+
await this.inlineNameInput.fill(name);
|
|
129
|
+
await this.inlineNameInput.press('Enter');
|
|
130
|
+
await this.waitForProcessApplication();
|
|
131
|
+
}
|
|
132
|
+
// Assigns a cluster to this process application's development stage.
|
|
133
|
+
//
|
|
134
|
+
// Deploying from inside a process application goes through
|
|
135
|
+
// ProcessAppClusterSelection, which only lists clusters the application has
|
|
136
|
+
// assigned to a stage, and does not auto-select anything when that list is
|
|
137
|
+
// empty. A freshly created process application has no stages, so the deploy
|
|
138
|
+
// dialog shows "Clusters not configured for stages" and offers nothing to
|
|
139
|
+
// pick -- which is why the old per-deploy cluster toggle was nowhere to be
|
|
140
|
+
// found. Assign the stage once, at creation, and the deploy dialog then
|
|
141
|
+
// auto-selects it.
|
|
142
|
+
//
|
|
143
|
+
// clusterName is matched as a prefix because the dropdown renders each
|
|
144
|
+
// cluster as "<name> <generation>". Without it, the first real cluster is
|
|
145
|
+
// taken -- callers that care assert the name in the deploy dialog anyway.
|
|
146
|
+
async defineDevelopmentStage(clusterName) {
|
|
147
|
+
await (0, test_1.expect)(this.defineStagesDialog).toBeVisible({ timeout: 60000 });
|
|
148
|
+
await this.developmentClusterSelect.click({ timeout: 30000 });
|
|
149
|
+
// Escape before interpolating: a cluster name can carry regex
|
|
150
|
+
// metacharacters -- "Test Cluster (v2)" is the common case -- which would
|
|
151
|
+
// otherwise mis-match or throw. Same treatment as
|
|
152
|
+
// utils/modelerCluster.selectModelerCluster.
|
|
153
|
+
const escapedClusterName = clusterName?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
154
|
+
const option = clusterName
|
|
155
|
+
? this.defineStagesDialog
|
|
156
|
+
.getByRole('option', { name: new RegExp(`^${escapedClusterName}`) })
|
|
157
|
+
.first()
|
|
158
|
+
: this.defineStagesDialog
|
|
159
|
+
.getByRole('option')
|
|
160
|
+
.filter({ hasNotText: 'Select a development cluster' })
|
|
161
|
+
.first();
|
|
162
|
+
await option.click({ timeout: 30000 });
|
|
163
|
+
await this.defineStagesSaveButton.click({ timeout: 30000 });
|
|
164
|
+
await (0, test_1.expect)(this.defineStagesDialog).toBeHidden({ timeout: 60000 });
|
|
165
|
+
}
|
|
166
|
+
rememberResourceContainer(url) {
|
|
167
|
+
resourceContainers.set(this.page, { url });
|
|
168
|
+
}
|
|
169
|
+
// A process application deploys to the clusters bound to its stages, and
|
|
170
|
+
// nothing else: inside a container DeployModal renders
|
|
171
|
+
// ProcessAppClusterSelection, which lists only those and auto-selects the
|
|
172
|
+
// first. Which cluster a test wants is known only once a deploy flow names
|
|
173
|
+
// it, so the binding happens here, on demand -- leave the diagram, bind the
|
|
174
|
+
// cluster to the development stage, come back. Repeat calls for the same
|
|
175
|
+
// cluster cost nothing, and a test deploying to a second cluster rebinds.
|
|
176
|
+
// Returns whether it navigated: the caller may have been on a view that a
|
|
177
|
+
// reload does not restore -- Play is a tab click, not a URL -- and has to
|
|
178
|
+
// re-enter it.
|
|
179
|
+
async ensureStageCluster(clusterName) {
|
|
180
|
+
const container = resourceContainers.get(this.page);
|
|
181
|
+
if (!container || container.developmentCluster === clusterName) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
const returnTo = this.page.url();
|
|
185
|
+
const paUrl = container.url.replace(/[?#].*$/, '').replace(/\/$/, '');
|
|
186
|
+
await this.page.goto(`${paUrl}/connected-clusters`, {
|
|
187
|
+
waitUntil: 'domcontentloaded',
|
|
188
|
+
});
|
|
189
|
+
await this.openStageDefinition();
|
|
190
|
+
await this.defineDevelopmentStage(clusterName);
|
|
191
|
+
container.developmentCluster = clusterName;
|
|
192
|
+
await this.page.goto(returnTo, { waitUntil: 'domcontentloaded' });
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
// The /connected-clusters deep link opens the Define stages dialog by itself
|
|
196
|
+
// while the application has no stage bound. Once one is bound -- a test that
|
|
197
|
+
// deploys to a second cluster -- it has to be reopened from the page, so try
|
|
198
|
+
// the affordances hub offers before failing with exactly what was looked for.
|
|
199
|
+
// Worth the noise: an unbound cluster otherwise surfaces as a deploy dialog
|
|
200
|
+
// that silently offers nothing, which says nothing about its own cause.
|
|
201
|
+
async openStageDefinition() {
|
|
202
|
+
const opened = await this.defineStagesDialog
|
|
203
|
+
.waitFor({ state: 'visible', timeout: 15000 })
|
|
204
|
+
.then(() => true)
|
|
205
|
+
.catch(() => false);
|
|
206
|
+
if (opened) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// Page-scoped .first(): hub renders one such control on this page, and a
|
|
210
|
+
// second placement must not turn every rebinding test into a strict-mode
|
|
211
|
+
// violation.
|
|
212
|
+
const reopen = this.page
|
|
213
|
+
.getByRole('button', { name: /define stages|edit stages|configure/i })
|
|
214
|
+
.first();
|
|
215
|
+
const canReopen = await reopen
|
|
216
|
+
.waitFor({ state: 'visible', timeout: 10000 })
|
|
217
|
+
.then(() => true)
|
|
218
|
+
.catch(() => false);
|
|
219
|
+
if (!canReopen) {
|
|
220
|
+
throw new Error('Could not open the "Define stages" dialog on /connected-clusters: it ' +
|
|
221
|
+
'did not open by itself and no "Define stages" / "Edit stages" / ' +
|
|
222
|
+
'"Configure" control was found.');
|
|
223
|
+
}
|
|
224
|
+
await reopen.click({ timeout: 30000 });
|
|
225
|
+
}
|
|
226
|
+
async openByName(name) {
|
|
227
|
+
const processApplication = this.page
|
|
228
|
+
.getByRole('row')
|
|
229
|
+
.filter({ hasText: name })
|
|
230
|
+
.getByTitle(name)
|
|
231
|
+
.first();
|
|
232
|
+
await (0, test_1.expect)(processApplication).toBeVisible({ timeout: 90000 });
|
|
233
|
+
await processApplication.click({ timeout: 60000 });
|
|
234
|
+
await this.waitForProcessApplication();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
exports.ProcessApplicationPage = ProcessApplicationPage;
|
|
@@ -653,6 +653,14 @@ async function modelAndRunConnectorsTimerEventDiagram(modelerCreatePage, modeler
|
|
|
653
653
|
timeout: 60000,
|
|
654
654
|
});
|
|
655
655
|
await connectorMarketplacePage.downloadConnectorToProject();
|
|
656
|
+
// Both lookups are container-relative: clickProjectBreadcrumb() returns to
|
|
657
|
+
// this test's process application, which is where the uploaded diagram
|
|
658
|
+
// lives. The downloaded element template is the open question -- hub
|
|
659
|
+
// publishes element templates to the workspace, but the marketplace download
|
|
660
|
+
// is initiated from inside the container, so it should land there. If a
|
|
661
|
+
// trace shows the template at workspace root instead, the first of these two
|
|
662
|
+
// calls becomes clickWorkspaceBreadcrumb() followed by
|
|
663
|
+
// returnToResourceContainer() before the diagram is reopened.
|
|
656
664
|
await modelerHomePage.clickProjectBreadcrumb();
|
|
657
665
|
await modelerHomePage.clickProcessDiagram('REST Outbound Connector');
|
|
658
666
|
await connectorTemplatePage.publishConnector();
|
|
@@ -27,6 +27,7 @@ declare class FormJsPage {
|
|
|
27
27
|
filldocumentReferenceInput(key: string): Promise<void>;
|
|
28
28
|
clickDeployFormButton(): Promise<void>;
|
|
29
29
|
clickDeployModalSubmitButton(): Promise<void>;
|
|
30
|
+
selectOnlyThisResource(): Promise<void>;
|
|
30
31
|
deployForm(): Promise<void>;
|
|
31
32
|
}
|
|
32
33
|
export { FormJsPage };
|
|
@@ -85,10 +85,36 @@ class FormJsPage {
|
|
|
85
85
|
async clickDeployModalSubmitButton() {
|
|
86
86
|
await this.deployModalSubmitButton.click({ timeout: 60000 });
|
|
87
87
|
}
|
|
88
|
+
// Since camunda/camunda-hub#25831 a form lives inside a process application,
|
|
89
|
+
// and Hub then scopes Deploy to the WHOLE application by default -- it calls
|
|
90
|
+
// deployProcessApplication, not deployFile, so the "Form deployed!" toast
|
|
91
|
+
// never fires (hub's own form-deploy-action.spec.sm.tsx asserts exactly that
|
|
92
|
+
// default). Narrowing the scope keeps this a form-deploy test instead of
|
|
93
|
+
// silently turning it into a process-application deploy. The combobox only
|
|
94
|
+
// exists inside a container, hence the boolean probe.
|
|
95
|
+
async selectOnlyThisResource() {
|
|
96
|
+
const scopeSelect = this.deployDialog.getByRole('combobox', {
|
|
97
|
+
name: 'Resources to deploy',
|
|
98
|
+
});
|
|
99
|
+
const hasScopeSelect = await scopeSelect
|
|
100
|
+
.waitFor({ state: 'visible', timeout: 10000 })
|
|
101
|
+
.then(() => true)
|
|
102
|
+
.catch(() => false);
|
|
103
|
+
if (!hasScopeSelect) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
await scopeSelect.click();
|
|
107
|
+
await this.deployDialog
|
|
108
|
+
.getByRole('option', { name: 'Only this resource' })
|
|
109
|
+
.or(this.deployDialog.getByText('Only this resource', { exact: true }))
|
|
110
|
+
.first()
|
|
111
|
+
.click({ timeout: 30000 });
|
|
112
|
+
}
|
|
88
113
|
async deployForm() {
|
|
89
114
|
await this.clickDeployFormButton();
|
|
90
115
|
await (0, test_1.expect)(this.deployDialog).toBeVisible({ timeout: 30000 });
|
|
91
116
|
await (0, modelerCluster_1.selectModelerCluster)(this.deployDialog);
|
|
117
|
+
await this.selectOnlyThisResource();
|
|
92
118
|
await this.clickDeployModalSubmitButton();
|
|
93
119
|
await (0, test_1.expect)(this.deploySuccessNotification).toBeVisible({ timeout: 30000 });
|
|
94
120
|
}
|
|
@@ -827,6 +827,10 @@ class ModelerCreatePage {
|
|
|
827
827
|
// Design System editor has none: renaming moved to the breadcrumb's "More
|
|
828
828
|
// actions" > "Rename" dialog. Use whichever the deployed shell offers.
|
|
829
829
|
async enterDiagramName(name) {
|
|
830
|
+
// Same hazard as ModelerHomePage.enterFormName: the project page also has a
|
|
831
|
+
// "More actions" button, so the or() gate can be satisfied before the
|
|
832
|
+
// editor has loaded and the rename would target the project.
|
|
833
|
+
await this.page.waitForURL(/\/diagrams\//, { timeout: 60000 });
|
|
830
834
|
await this.diagramNameInput
|
|
831
835
|
.or(this.moreActionsButton)
|
|
832
836
|
.first()
|
|
@@ -1016,19 +1020,37 @@ class ModelerCreatePage {
|
|
|
1016
1020
|
name: /^Configure (test case|scenario)$/,
|
|
1017
1021
|
}))
|
|
1018
1022
|
.first();
|
|
1019
|
-
//
|
|
1020
|
-
//
|
|
1021
|
-
//
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1023
|
+
// Play settles into exactly ONE of three states, and which one is not
|
|
1024
|
+
// knowable up front, so race them instead of timing out on each in turn:
|
|
1025
|
+
// the setup overlay, the legacy Continue button, or the configure-test
|
|
1026
|
+
// panel (meaning setup is already done for this diagram).
|
|
1027
|
+
//
|
|
1028
|
+
// Waiting only for the first two and reading "neither" as "already ready"
|
|
1029
|
+
// was wrong once the diagram moved inside a process application.
|
|
1030
|
+
// ConfigurationOverlay renders null until isDeploymentStateValidated, and
|
|
1031
|
+
// it sets that flag synchronously ONLY when processApplicationId is
|
|
1032
|
+
// undefined -- exactly what a project-root diagram used to give it. With
|
|
1033
|
+
// the diagram in a process application the id is defined, so the overlay
|
|
1034
|
+
// must first await checkExistingDeployment(). The old 15s probe raced that
|
|
1035
|
+
// async call, concluded "already ready" and returned while the overlay was
|
|
1036
|
+
// still about to appear. ConfigureTestPanel returns null for as long as the
|
|
1037
|
+
// overlay is up, so the Start button never existed and
|
|
1038
|
+
// clickStartInstanceButton burned its entire retry budget looking for it.
|
|
1039
|
+
const configurationOverlay = this.page.locator('[data-test="play-configuration-overlay"]');
|
|
1040
|
+
const configureTestPanel = this.page.getByTestId('configure-test-panel');
|
|
1041
|
+
await (0, test_1.expect)(configurationOverlay
|
|
1042
|
+
.or(this.continueToPlayButton)
|
|
1043
|
+
.or(configureTestPanel)
|
|
1044
|
+
.first()).toBeVisible({ timeout: 90000 });
|
|
1045
|
+
if (await configureTestPanel.isVisible()) {
|
|
1046
|
+
// Already past setup for this diagram -- nothing to drive.
|
|
1029
1047
|
return;
|
|
1030
1048
|
}
|
|
1031
|
-
|
|
1049
|
+
// Keyed on the overlay itself, not on its Deploy button: when
|
|
1050
|
+
// checkExistingDeployment finds a deployment the overlay opens with the
|
|
1051
|
+
// deploy step already complete, so there is no Deploy button to see and
|
|
1052
|
+
// keying on it would fall through to the legacy Continue flow.
|
|
1053
|
+
const isNewFlow = await configurationOverlay.isVisible();
|
|
1032
1054
|
if (isNewFlow) {
|
|
1033
1055
|
// Step 1: connect cluster if not yet connected (modal with cluster dropdown)
|
|
1034
1056
|
const connectClusterButton = this.page.getByRole('button', {
|
|
@@ -1048,11 +1070,31 @@ class ModelerCreatePage {
|
|
|
1048
1070
|
.getByRole('button', { name: 'Save' })
|
|
1049
1071
|
.click({ timeout });
|
|
1050
1072
|
}
|
|
1051
|
-
// Step 2: deploy
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
//
|
|
1055
|
-
|
|
1073
|
+
// Step 2: deploy, unless the overlay already opened with the
|
|
1074
|
+
// deploy step complete. checkExistingDeployment only runs when
|
|
1075
|
+
// processApplicationId is defined, which it now is, so re-entering
|
|
1076
|
+
// Play on an already-deployed process application legitimately
|
|
1077
|
+
// has nothing to deploy and renders no Deploy button at all.
|
|
1078
|
+
const alreadyDeployed = await configureScenarioButton
|
|
1079
|
+
.isVisible({ timeout: 3000 })
|
|
1080
|
+
.catch(() => false);
|
|
1081
|
+
if (!alreadyDeployed) {
|
|
1082
|
+
// Step 2: deploy
|
|
1083
|
+
await setupDeployButton.click({ timeout });
|
|
1084
|
+
await (0, test_1.expect)(this.page.getByText('Process has been successfully deployed')).toBeVisible({ timeout: 90000 });
|
|
1085
|
+
}
|
|
1086
|
+
// Step 3: leave the overlay, and confirm we actually left it. The
|
|
1087
|
+
// button only calls hideConfigurationOverlay(); the overlay's own
|
|
1088
|
+
// cluster-change effect can then fire resetDeployment and bring it
|
|
1089
|
+
// straight back, and ConfigureTestPanel stays null while it is up.
|
|
1090
|
+
// Assert the panel really rendered, and re-drive the click if the
|
|
1091
|
+
// overlay returned.
|
|
1092
|
+
await (0, test_1.expect)(async () => {
|
|
1093
|
+
if (await configurationOverlay.isVisible()) {
|
|
1094
|
+
await configureScenarioButton.click({ timeout });
|
|
1095
|
+
}
|
|
1096
|
+
await (0, test_1.expect)(configureTestPanel).toBeVisible({ timeout: 15000 });
|
|
1097
|
+
}).toPass({ timeout: 90000 });
|
|
1056
1098
|
return;
|
|
1057
1099
|
}
|
|
1058
1100
|
// Legacy flow: "Continue" button → "Play environment is ready" confirmation.
|
|
@@ -2,6 +2,9 @@ import { Page, Locator } from '@playwright/test';
|
|
|
2
2
|
declare class ModelerHomePage {
|
|
3
3
|
private page;
|
|
4
4
|
private defaultFolderName;
|
|
5
|
+
private processApplicationPage;
|
|
6
|
+
private processApplicationUrl?;
|
|
7
|
+
private processApplicationName?;
|
|
5
8
|
readonly modelerPageBanner: Locator;
|
|
6
9
|
readonly createNewProjectButton: Locator;
|
|
7
10
|
readonly projectNameInput: Locator;
|
|
@@ -14,6 +17,7 @@ declare class ModelerHomePage {
|
|
|
14
17
|
readonly bpmnTemplateOption: Locator;
|
|
15
18
|
readonly formTemplateOption: Locator;
|
|
16
19
|
readonly projectBreadcrumb: Locator;
|
|
20
|
+
readonly workspaceBreadcrumb: Locator;
|
|
17
21
|
readonly openOrganizationsButton: Locator;
|
|
18
22
|
readonly manageButton: Locator;
|
|
19
23
|
readonly crossComponentProjectFolder: Locator;
|
|
@@ -43,10 +47,17 @@ declare class ModelerHomePage {
|
|
|
43
47
|
enterFormName(name: string): Promise<void>;
|
|
44
48
|
private renameViaMoreActions;
|
|
45
49
|
clickProjectBreadcrumb(): Promise<void>;
|
|
50
|
+
clickWorkspaceBreadcrumb(): Promise<void>;
|
|
51
|
+
enterResourceContainer(name?: string): Promise<void>;
|
|
52
|
+
private clickCreateProcessApplication;
|
|
53
|
+
private ensureInResourceContainer;
|
|
54
|
+
returnToResourceContainer(): Promise<void>;
|
|
55
|
+
startBlankBpmnDiagram(): Promise<void>;
|
|
46
56
|
clickOpenOrganizationsButton(): Promise<void>;
|
|
47
57
|
clickManageButton(): Promise<void>;
|
|
48
58
|
clickUploadFilesButton(): Promise<void>;
|
|
49
59
|
clickMessageBanner(): Promise<void>;
|
|
60
|
+
private becameVisible;
|
|
50
61
|
private overlayBecameVisible;
|
|
51
62
|
}
|
|
52
63
|
export { ModelerHomePage };
|