@camunda/e2e-test-suite 0.0.1238 → 0.0.1240
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/AppsPage.d.ts +1 -1
- package/dist/pages/8.10/AppsPage.js +18 -1
- package/dist/pages/8.10/ModelerHomePage.js +12 -2
- package/dist/pages/SM-8.10/NavigationPage.d.ts +2 -1
- package/dist/pages/SM-8.10/NavigationPage.js +25 -4
- package/dist/tests/8.10/test-setup.spec.js +1 -1
- package/package.json +1 -1
|
@@ -31,7 +31,7 @@ declare class AppsPage {
|
|
|
31
31
|
clickCluster(component: Locator, name: string): Promise<void>;
|
|
32
32
|
clickModeler(): Promise<void>;
|
|
33
33
|
private isModelerAuthTransit;
|
|
34
|
-
openModelerWithRetry(banner: Locator, timeout?: number, maxRetries?: number, ready?: Locator): Promise<void>;
|
|
34
|
+
openModelerWithRetry(banner: Locator, timeout?: number, maxRetries?: number, ready?: Locator, beforeReady?: () => Promise<void>): Promise<void>;
|
|
35
35
|
openOperateWithRetry(banner: Locator, clusterName: string, timeout?: number, maxRetries?: number): Promise<void>;
|
|
36
36
|
clickTasklist(clusterName: string): Promise<void>;
|
|
37
37
|
openTasklistWithRetry(banner: Locator, clusterName: string, timeout?: number, maxRetries?: number): Promise<void>;
|
|
@@ -236,8 +236,25 @@ class AppsPage {
|
|
|
236
236
|
// something only an authenticated Modeler renders -- the projects list's
|
|
237
237
|
// create button -- and a logged-out tab is caught here instead, where the
|
|
238
238
|
// retry re-runs the handshake and with it the internal login.
|
|
239
|
-
async openModelerWithRetry(banner, timeout = 60000, maxRetries = 3, ready) {
|
|
239
|
+
async openModelerWithRetry(banner, timeout = 60000, maxRetries = 3, ready, beforeReady) {
|
|
240
240
|
const modelerReady = async () => {
|
|
241
|
+
if (beforeReady) {
|
|
242
|
+
// After the Camunda Hub rebrand the Modeler home greets a first visit
|
|
243
|
+
// with a "Welcome to Camunda Hub" onboarding dialog that mounts a beat
|
|
244
|
+
// after routing and marks the app shell inert, so the banner leaves the
|
|
245
|
+
// accessibility tree until the dialog is dismissed. Run beforeReady
|
|
246
|
+
// (the dialog dismissal) each interval so a dialog that mounts after the
|
|
247
|
+
// first pass is still cleared, instead of burning the whole timeout on a
|
|
248
|
+
// banner the overlay is holding out of reach.
|
|
249
|
+
await (0, test_1.expect)(async () => {
|
|
250
|
+
await beforeReady();
|
|
251
|
+
await (0, test_1.expect)(banner).toBeVisible({ timeout: 15000 });
|
|
252
|
+
if (ready) {
|
|
253
|
+
await (0, test_1.expect)(ready).toBeVisible({ timeout: 15000 });
|
|
254
|
+
}
|
|
255
|
+
}).toPass({ timeout, intervals: [1000, 2000, 5000] });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
241
258
|
await (0, test_1.expect)(banner).toBeVisible({ timeout });
|
|
242
259
|
if (ready) {
|
|
243
260
|
await (0, test_1.expect)(ready).toBeVisible({ timeout });
|
|
@@ -58,9 +58,19 @@ class ModelerHomePage {
|
|
|
58
58
|
constructor(page) {
|
|
59
59
|
this.page = page;
|
|
60
60
|
this.processApplicationPage = new ProcessApplicationPage_1.ProcessApplicationPage(page);
|
|
61
|
-
|
|
61
|
+
// Hub's design-system shell renders the app header as a role=banner with no
|
|
62
|
+
// accessible name after the Camunda Hub rebrand, so the classic
|
|
63
|
+
// name-matched banner no longer resolves; the Modeler logo link inside it
|
|
64
|
+
// still carries "Camunda Modeler home". Keep the legacy named-banner branch
|
|
65
|
+
// for shells where the rename has not shipped yet.
|
|
66
|
+
this.modelerPageBanner = page
|
|
67
|
+
.getByRole('banner', {
|
|
62
68
|
name: 'Camunda Modeler',
|
|
63
|
-
})
|
|
69
|
+
})
|
|
70
|
+
.or(page
|
|
71
|
+
.getByRole('link', { name: 'Camunda Modeler home' })
|
|
72
|
+
.and(page.locator(':not([href$="/login"])')))
|
|
73
|
+
.first();
|
|
64
74
|
// Hub renamed this button to "Create project" on both the classic and the
|
|
65
75
|
// design-system shell. The legacy label is kept so the flow still works
|
|
66
76
|
// against Modeler builds where the rename has not shipped yet. exact:true
|
|
@@ -14,11 +14,12 @@ declare class NavigationPage {
|
|
|
14
14
|
goTo(url: string, banner: Locator, sleepTimeout?: number, { username, password, }?: {
|
|
15
15
|
username?: string;
|
|
16
16
|
password?: string;
|
|
17
|
-
}, maxRetries?: number): Promise<void>;
|
|
17
|
+
}, maxRetries?: number, beforeBannerCheck?: () => Promise<void>): Promise<void>;
|
|
18
18
|
goToModeler(sleepTimeout?: number, credentials?: {
|
|
19
19
|
username: string;
|
|
20
20
|
password: string;
|
|
21
21
|
}): Promise<void>;
|
|
22
|
+
private dismissOnboardingDialog;
|
|
22
23
|
goToTasklist(sleepTimeout?: number, credentials?: {
|
|
23
24
|
username: string;
|
|
24
25
|
password: string;
|
|
@@ -112,12 +112,15 @@ class NavigationPage {
|
|
|
112
112
|
// that is exactly the reported "Login (/modeler) failed after 8 attempts".
|
|
113
113
|
// The 60s budget is unchanged: a genuinely slow shell still gets all of it,
|
|
114
114
|
// and a sustained outage still fails.
|
|
115
|
-
async waitForBanner(url, banner, submitted) {
|
|
115
|
+
async waitForBanner(url, banner, submitted, beforeBannerCheck) {
|
|
116
116
|
const totalTimeout = constants_1._1_SECOND_IN_MS * 60;
|
|
117
117
|
const deadline = Date.now() + totalTimeout;
|
|
118
118
|
let lastState = 'no banner';
|
|
119
119
|
while (Date.now() < deadline) {
|
|
120
120
|
const round = Math.min(constants_1._1_SECOND_IN_MS * 20, deadline - Date.now());
|
|
121
|
+
if (beforeBannerCheck) {
|
|
122
|
+
await beforeBannerCheck();
|
|
123
|
+
}
|
|
121
124
|
try {
|
|
122
125
|
await (0, test_1.expect)(banner).toBeVisible({ timeout: round });
|
|
123
126
|
return;
|
|
@@ -145,7 +148,7 @@ class NavigationPage {
|
|
|
145
148
|
}
|
|
146
149
|
throw new Error(`${url} did not render its banner within ${totalTimeout}ms: ${lastState}`);
|
|
147
150
|
}
|
|
148
|
-
async goTo(url, banner, sleepTimeout, { username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}, maxRetries = 8) {
|
|
151
|
+
async goTo(url, banner, sleepTimeout, { username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}, maxRetries = 8, beforeBannerCheck) {
|
|
149
152
|
const startTime = Date.now();
|
|
150
153
|
let timeout = constants_1._1_SECOND_IN_MS * 10;
|
|
151
154
|
if (url === '/modeler') {
|
|
@@ -214,7 +217,7 @@ class NavigationPage {
|
|
|
214
217
|
else {
|
|
215
218
|
submitted = await loginPage.login(username, password);
|
|
216
219
|
}
|
|
217
|
-
await this.waitForBanner(url, banner, submitted);
|
|
220
|
+
await this.waitForBanner(url, banner, submitted, beforeBannerCheck);
|
|
218
221
|
return;
|
|
219
222
|
}
|
|
220
223
|
catch (error) {
|
|
@@ -261,7 +264,25 @@ class NavigationPage {
|
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
266
|
async goToModeler(sleepTimeout, credentials) {
|
|
264
|
-
await this.goTo(MODELER_CONTEXT_PATH, this.modelerPageBanner, sleepTimeout, credentials);
|
|
267
|
+
await this.goTo(MODELER_CONTEXT_PATH, this.modelerPageBanner, sleepTimeout, credentials, 8, () => this.dismissOnboardingDialog());
|
|
268
|
+
}
|
|
269
|
+
// After the Camunda Hub rebrand a first visit to Modeler home greets the user
|
|
270
|
+
// with a multi-step "Welcome to Camunda Hub" onboarding dialog. It mounts over
|
|
271
|
+
// the home and marks the app shell inert, so the "Camunda Modeler home" banner
|
|
272
|
+
// link leaves the accessibility tree until the dialog is dismissed -- gating on
|
|
273
|
+
// the banner alone then loops until the whole login budget is spent. Close it
|
|
274
|
+
// through the dialog's own control before each banner check so the banner can
|
|
275
|
+
// resolve; only unambiguous dismissals are matched (never "Cancel", which is a
|
|
276
|
+
// form action on the dialogs other flows open on purpose).
|
|
277
|
+
async dismissOnboardingDialog() {
|
|
278
|
+
const dismiss = this.page
|
|
279
|
+
.locator('[role="dialog"]')
|
|
280
|
+
.getByRole('button', { name: /^(Got it|Close|Dismiss)/i })
|
|
281
|
+
.first();
|
|
282
|
+
await dismiss
|
|
283
|
+
.waitFor({ state: 'visible', timeout: 3000 })
|
|
284
|
+
.then(() => dismiss.click())
|
|
285
|
+
.catch(() => { });
|
|
265
286
|
}
|
|
266
287
|
async goToTasklist(sleepTimeout, credentials) {
|
|
267
288
|
await this.goTo(`${NORMALIZED_ORCHESTRATION_CONTEXT_PATH}/tasklist`, this.tasklistPageBanner, sleepTimeout, credentials);
|
|
@@ -168,7 +168,7 @@ _8_10_1.test.describe('Cluster Setup Tests', () => {
|
|
|
168
168
|
await (0, test_1.expect)(homePage.camundaComponentsButton).toBeVisible({
|
|
169
169
|
timeout: 120000,
|
|
170
170
|
});
|
|
171
|
-
await appsPage.openModelerWithRetry(modelerHomePage.modelerPageBanner, 180000);
|
|
171
|
+
await appsPage.openModelerWithRetry(modelerHomePage.modelerPageBanner, 180000, 3, undefined, () => modelerHomePage.dismissBlockingDialog());
|
|
172
172
|
});
|
|
173
173
|
await _8_10_1.test.step('Create Cross Component Project Folder', async () => {
|
|
174
174
|
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, user, Math.min((testInfo.workerIndex + 1) * 5000, 60000), async () => {
|