@camunda/e2e-test-suite 0.0.1468 → 0.0.1470
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.
|
@@ -66,8 +66,14 @@ export declare function isAtModelerLoginRoute(page: Page): boolean;
|
|
|
66
66
|
* the moment the session is accepted, and otherwise spends the wait backing
|
|
67
67
|
* off.
|
|
68
68
|
*
|
|
69
|
+
* Every healthy reload also passes through `/login?returnUrl=...` while the
|
|
70
|
+
* session call is in flight, and callers often check right after a
|
|
71
|
+
* `domcontentloaded` reload. So the page only counts as stuck once it has stayed
|
|
72
|
+
* on `/login` for `graceTimeout`; reloading earlier interrupts a working
|
|
73
|
+
* hand-off and sends a second session call for the same user.
|
|
74
|
+
*
|
|
69
75
|
* Cheap to call speculatively -- a page that is not on `/login` costs one URL
|
|
70
76
|
* comparison and no DOM access, which is what lets the Modeler page objects
|
|
71
77
|
* guard their navigations with it.
|
|
72
78
|
*/
|
|
73
|
-
export declare function recoverStuckModelerLogin(page: Page, attempts?: number, settleTimeout?: number): Promise<boolean>;
|
|
79
|
+
export declare function recoverStuckModelerLogin(page: Page, attempts?: number, settleTimeout?: number, graceTimeout?: number): Promise<boolean>;
|
|
@@ -15,8 +15,48 @@ const signedInUser = new WeakMap();
|
|
|
15
15
|
*/
|
|
16
16
|
function trackSignedInUser(page, username) {
|
|
17
17
|
signedInUser.set(page, username);
|
|
18
|
+
watchModelerSessionCalls(page);
|
|
18
19
|
}
|
|
19
20
|
exports.trackSignedInUser = trackSignedInUser;
|
|
21
|
+
const SESSION_CALL_PATH = /\/api\/internal\/login\/?$/;
|
|
22
|
+
// The status of the last `POST /api/internal/login` this page received, so a
|
|
23
|
+
// "stuck on /login" verdict can say what the backend actually answered rather
|
|
24
|
+
// than assume a 5xx from the URL alone.
|
|
25
|
+
const lastSessionCallStatus = new WeakMap();
|
|
26
|
+
const watchedPages = new WeakSet();
|
|
27
|
+
function watchModelerSessionCalls(page) {
|
|
28
|
+
if (watchedPages.has(page)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
watchedPages.add(page);
|
|
32
|
+
page.on('response', (response) => {
|
|
33
|
+
if (response.request().method() !== 'POST') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let pathname;
|
|
37
|
+
try {
|
|
38
|
+
pathname = new URL(response.url()).pathname;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!SESSION_CALL_PATH.test(pathname)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const status = response.status();
|
|
47
|
+
lastSessionCallStatus.set(page, status);
|
|
48
|
+
if (status >= 500) {
|
|
49
|
+
console.warn(`Modeler session call failed: POST ${response.url()} answered ` +
|
|
50
|
+
`${status} at ${new Date().toISOString()}`);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function describeLastSessionCall(page) {
|
|
55
|
+
const status = lastSessionCallStatus.get(page);
|
|
56
|
+
return status === undefined
|
|
57
|
+
? 'no response to POST /api/internal/login was seen'
|
|
58
|
+
: `the last POST /api/internal/login answered ${status}`;
|
|
59
|
+
}
|
|
20
60
|
// Read back out of the environment at the moment it is needed, from the
|
|
21
61
|
// `C8_USERNAME*` / `C8_PASSWORD*` pair that defines this user -- the same
|
|
22
62
|
// source LoginPage reads its own defaults from. Nothing secret is carried
|
|
@@ -189,17 +229,35 @@ exports.isAtModelerLoginRoute = isAtModelerLoginRoute;
|
|
|
189
229
|
* the moment the session is accepted, and otherwise spends the wait backing
|
|
190
230
|
* off.
|
|
191
231
|
*
|
|
232
|
+
* Every healthy reload also passes through `/login?returnUrl=...` while the
|
|
233
|
+
* session call is in flight, and callers often check right after a
|
|
234
|
+
* `domcontentloaded` reload. So the page only counts as stuck once it has stayed
|
|
235
|
+
* on `/login` for `graceTimeout`; reloading earlier interrupts a working
|
|
236
|
+
* hand-off and sends a second session call for the same user.
|
|
237
|
+
*
|
|
192
238
|
* Cheap to call speculatively -- a page that is not on `/login` costs one URL
|
|
193
239
|
* comparison and no DOM access, which is what lets the Modeler page objects
|
|
194
240
|
* guard their navigations with it.
|
|
195
241
|
*/
|
|
196
|
-
async function recoverStuckModelerLogin(page, attempts = 4, settleTimeout = 25000) {
|
|
242
|
+
async function recoverStuckModelerLogin(page, attempts = 4, settleTimeout = 25000, graceTimeout = 20000) {
|
|
197
243
|
if (!isAtModelerLoginRoute(page)) {
|
|
198
244
|
return false;
|
|
199
245
|
}
|
|
246
|
+
watchModelerSessionCalls(page);
|
|
247
|
+
const leftOnItsOwn = await page
|
|
248
|
+
.waitForURL((url) => !LOGIN_ROUTE.test(url.pathname), {
|
|
249
|
+
timeout: graceTimeout,
|
|
250
|
+
waitUntil: 'commit',
|
|
251
|
+
})
|
|
252
|
+
.then(() => true)
|
|
253
|
+
.catch(() => false);
|
|
254
|
+
if (leftOnItsOwn) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
200
257
|
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
201
|
-
console.warn(`recoverStuckModelerLogin: Modeler is
|
|
202
|
-
|
|
258
|
+
console.warn(`recoverStuckModelerLogin: Modeler is still on ${page.url()} after ` +
|
|
259
|
+
`${graceTimeout / 1000}s; ${describeLastSessionCall(page)}. ` +
|
|
260
|
+
`Reload ${attempt}/${attempts}.`);
|
|
203
261
|
await page
|
|
204
262
|
.reload({ waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
205
263
|
.catch(() => undefined);
|
|
@@ -212,6 +270,7 @@ async function recoverStuckModelerLogin(page, attempts = 4, settleTimeout = 2500
|
|
|
212
270
|
const recovered = await page
|
|
213
271
|
.waitForURL((url) => !LOGIN_ROUTE.test(url.pathname), {
|
|
214
272
|
timeout: settleTimeout,
|
|
273
|
+
waitUntil: 'commit',
|
|
215
274
|
})
|
|
216
275
|
.then(() => true)
|
|
217
276
|
.catch(() => false);
|
|
@@ -219,8 +278,8 @@ async function recoverStuckModelerLogin(page, attempts = 4, settleTimeout = 2500
|
|
|
219
278
|
return true;
|
|
220
279
|
}
|
|
221
280
|
}
|
|
222
|
-
console.warn(
|
|
223
|
-
|
|
281
|
+
console.warn(`recoverStuckModelerLogin: Modeler never left /login; ` +
|
|
282
|
+
`${describeLastSessionCall(page)}.`);
|
|
224
283
|
return true;
|
|
225
284
|
}
|
|
226
285
|
exports.recoverStuckModelerLogin = recoverStuckModelerLogin;
|