@camunda/e2e-test-suite 0.0.1213 → 0.0.1215
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.9/LoginPage.js +4 -0
- package/dist/pages/8.9/ModelerCreatePage.js +19 -1
- package/dist/pages/8.9/ModelerHomePage.js +14 -0
- package/dist/tests/8.10/rba-enabled-v2-user-flows.spec.js +21 -3
- package/dist/tests/8.10/web-modeler-user-flows.spec.js +19 -4
- package/dist/tests/8.9/hto-user-flows.spec.js +11 -4
- package/dist/tests/8.9/web-modeler-user-flows.spec.js +10 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ exports.LoginPage = void 0;
|
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
5
|
const authErrorClassification_1 = require("../../utils/authErrorClassification");
|
|
6
6
|
const UtilitiesPage_1 = require("./UtilitiesPage");
|
|
7
|
+
const sessionRecovery_1 = require("../../utils/sessionRecovery");
|
|
7
8
|
const userNameInputValidInputSchema = {
|
|
8
9
|
_schema: {
|
|
9
10
|
maxlength: 254,
|
|
@@ -67,6 +68,7 @@ class LoginPage {
|
|
|
67
68
|
}
|
|
68
69
|
async login(credentials = {}) {
|
|
69
70
|
const { username = process.env.C8_USERNAME, password = process.env.C8_PASSWORD, } = credentials;
|
|
71
|
+
(0, sessionRecovery_1.trackSignedInUser)(this.page, username);
|
|
70
72
|
await (0, test_1.expect)(this.loginMessage).toBeVisible({ timeout: 120000 });
|
|
71
73
|
await (0, test_1.expect)(this.usernameInput.locator).toBeVisible({ timeout: 30000 });
|
|
72
74
|
await this.fillUsername(username);
|
|
@@ -78,6 +80,7 @@ class LoginPage {
|
|
|
78
80
|
}
|
|
79
81
|
async loginWithTestUser(credentials = {}) {
|
|
80
82
|
const { username = process.env.C8_USERNAME_TEST, password = process.env.C8_PASSWORD_TEST, } = credentials;
|
|
83
|
+
(0, sessionRecovery_1.trackSignedInUser)(this.page, username);
|
|
81
84
|
// Navigate to app root to trigger auth redirect. The Console app (at
|
|
82
85
|
// console.* hostnames) embeds a hidden invite-user email input also labeled
|
|
83
86
|
// "Email address" that would otherwise satisfy the locator below before the
|
|
@@ -166,6 +169,7 @@ class LoginPage {
|
|
|
166
169
|
}
|
|
167
170
|
async loginWithoutOrgAssertion(credentials = {}) {
|
|
168
171
|
const { username = process.env.C8_USERNAME, password = process.env.C8_PASSWORD, } = credentials;
|
|
172
|
+
(0, sessionRecovery_1.trackSignedInUser)(this.page, username);
|
|
169
173
|
await (0, test_1.expect)(this.usernameInput.locator).toBeVisible({ timeout: 180000 });
|
|
170
174
|
await this.fillUsername(username);
|
|
171
175
|
await this.clickContinueButton();
|
|
@@ -353,13 +353,31 @@ class ModelerCreatePage {
|
|
|
353
353
|
});
|
|
354
354
|
await this.enterDiagramName(processName);
|
|
355
355
|
await (0, sleep_1.sleep)(10000);
|
|
356
|
+
// Renaming the file is what normally propagates the name into
|
|
357
|
+
// `bpmn:process@name`, but the canvas keeps its own in-memory copy of the
|
|
358
|
+
// model and serialises that copy back on the first edit after the rename --
|
|
359
|
+
// trace evidence from a failing run shows revision 3 saved with the new
|
|
360
|
+
// name and revision 4, ten seconds later, reverting it to the template
|
|
361
|
+
// default "New BPMN diagram". That name is the label Tasklist prints under
|
|
362
|
+
// each task (the user task itself is unnamed, so its row reads
|
|
363
|
+
// `Activity_<id>` / `New BPMN diagram`), so `openTask(processName)` then
|
|
364
|
+
// waits out its whole 20-minute budget on a task sitting right there under
|
|
365
|
+
// the wrong label. Set the name on the canvas model, where no later save
|
|
366
|
+
// can revert it. Same race already handled in
|
|
367
|
+
// `modelCamundaUserTaskDiagram`.
|
|
368
|
+
await this.clickCanvas();
|
|
369
|
+
await this.clickGeneralPropertiesPanel();
|
|
370
|
+
await this.clickNameInput();
|
|
371
|
+
await this.fillNamedInput(processName);
|
|
356
372
|
if (processId.length > 0) {
|
|
357
373
|
await this.clickStartEventElement();
|
|
358
374
|
await this.clickGeneralPropertiesPanel();
|
|
359
375
|
await this.clickIdInput();
|
|
360
376
|
await this.fillIdInput(processId);
|
|
361
|
-
await this.clickStartEventElement();
|
|
362
377
|
}
|
|
378
|
+
// `clickCanvas` cleared the selection, and the append create pad only
|
|
379
|
+
// renders for a selected element, so re-select before appending.
|
|
380
|
+
await this.clickStartEventElement();
|
|
363
381
|
await this.clickAppendElementButton();
|
|
364
382
|
await this.clickAppendTaskButton();
|
|
365
383
|
await this.clickChangeTypeButton();
|
|
@@ -6,6 +6,7 @@ const sleep_1 = require("../../utils/sleep");
|
|
|
6
6
|
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
|
|
7
7
|
const randomName_1 = require("../../utils/randomName");
|
|
8
8
|
const ProcessApplicationPage_1 = require("./ProcessApplicationPage");
|
|
9
|
+
const sessionRecovery_1 = require("../../utils/sessionRecovery");
|
|
9
10
|
class ModelerHomePage {
|
|
10
11
|
defaultFolderName = 'Cross Component Test Project';
|
|
11
12
|
page;
|
|
@@ -221,6 +222,10 @@ class ModelerHomePage {
|
|
|
221
222
|
async clickCreateNewProjectButton() {
|
|
222
223
|
await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.createNewProjectButton, {
|
|
223
224
|
preAction: async () => {
|
|
225
|
+
// Modeler logs the SPA out on its own when a backend call fails, and
|
|
226
|
+
// every later attempt then waits for this button on the Auth0 form
|
|
227
|
+
// instead of on Modeler. Get the session back before looking for it.
|
|
228
|
+
await (0, sessionRecovery_1.restoreSessionIfLoggedOut)(this.page);
|
|
224
229
|
await this.dismissOverlays();
|
|
225
230
|
},
|
|
226
231
|
totalTimeout: 120000,
|
|
@@ -488,6 +493,15 @@ class ModelerHomePage {
|
|
|
488
493
|
await this.dismissOverlays();
|
|
489
494
|
},
|
|
490
495
|
postAction: async () => {
|
|
496
|
+
// Before anything else: a 5xx from Modeler's own /api/internal/login
|
|
497
|
+
// makes the SPA log itself out, and from then on the reload below only
|
|
498
|
+
// re-renders the Auth0 form -- the tile can never come back, so every
|
|
499
|
+
// remaining attempt burns its visibility timeout for nothing. Recover
|
|
500
|
+
// the session as the current test user and let the next attempt probe
|
|
501
|
+
// the tile again.
|
|
502
|
+
if (await (0, sessionRecovery_1.restoreSessionIfLoggedOut)(this.page)) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
491
505
|
await this.page.reload();
|
|
492
506
|
await this.page.waitForLoadState('domcontentloaded');
|
|
493
507
|
},
|
|
@@ -84,7 +84,13 @@ _8_10_1.test.describe.parallel('RBA Enabled User Flows Test @tasklistV2', () =>
|
|
|
84
84
|
});
|
|
85
85
|
await _8_10_1.test.step('Navigate to Cross Component Test Project', async () => {
|
|
86
86
|
await homePage.clickSkipCustomization();
|
|
87
|
-
|
|
87
|
+
// createCrossComponentProjectFolder() hunts for a project tile that
|
|
88
|
+
// Modeler's own login page will never render. A dropped session (a 5xx
|
|
89
|
+
// from `/api/internal/login`) surfaces here as "element(s) not found"
|
|
90
|
+
// rather than as the sign-out it actually was (run 35562939552) --
|
|
91
|
+
// withSessionRecovery detects that case and signs back in as the test
|
|
92
|
+
// user this test just switched to, before retrying once.
|
|
93
|
+
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, testUser, (testInfo.workerIndex + 1) * 1000, () => modelerHomePage.createCrossComponentProjectFolder());
|
|
88
94
|
});
|
|
89
95
|
await _8_10_1.test.step('Create Two BPMN Diagrams with User Task and Start Process Instance', async () => {
|
|
90
96
|
await (0, UtilitiesPage_1.runMultipleProcesses)(clusterName, page, modelerHomePage, modelerCreatePage, {
|
|
@@ -196,7 +202,13 @@ _8_10_1.test.describe.parallel('RBA Enabled User Flows Test @tasklistV2', () =>
|
|
|
196
202
|
});
|
|
197
203
|
await _8_10_1.test.step('Navigate to Cross Component Test Project', async () => {
|
|
198
204
|
await homePage.clickSkipCustomization();
|
|
199
|
-
|
|
205
|
+
// createCrossComponentProjectFolder() hunts for a project tile that
|
|
206
|
+
// Modeler's own login page will never render. A dropped session (a 5xx
|
|
207
|
+
// from `/api/internal/login`) surfaces here as "element(s) not found"
|
|
208
|
+
// rather than as the sign-out it actually was (run 35562939552) --
|
|
209
|
+
// withSessionRecovery detects that case and signs back in as the test
|
|
210
|
+
// user this test just switched to, before retrying once.
|
|
211
|
+
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, testUser, (testInfo.workerIndex + 1) * 1000, () => modelerHomePage.createCrossComponentProjectFolder());
|
|
200
212
|
});
|
|
201
213
|
await _8_10_1.test.step('Create Two BPMN Diagrams with User Task and Start Process Instance', async () => {
|
|
202
214
|
await (0, UtilitiesPage_1.runMultipleProcesses)(clusterName, page, modelerHomePage, modelerCreatePage, {
|
|
@@ -428,7 +440,13 @@ _8_10_1.test.describe.parallel('RBA Enabled User Flows Test @tasklistV2', () =>
|
|
|
428
440
|
});
|
|
429
441
|
await _8_10_1.test.step('Navigate to Cross Component Test Project', async () => {
|
|
430
442
|
await homePage.clickSkipCustomization();
|
|
431
|
-
|
|
443
|
+
// createCrossComponentProjectFolder() hunts for a project tile that
|
|
444
|
+
// Modeler's own login page will never render. A dropped session (a 5xx
|
|
445
|
+
// from `/api/internal/login`) surfaces here as "element(s) not found"
|
|
446
|
+
// rather than as the sign-out it actually was (run 35562939552) --
|
|
447
|
+
// withSessionRecovery detects that case and signs back in as the test
|
|
448
|
+
// user this test just switched to, before retrying once.
|
|
449
|
+
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, testUser, (testInfo.workerIndex + 1) * 1000, () => modelerHomePage.createCrossComponentProjectFolder());
|
|
432
450
|
});
|
|
433
451
|
await _8_10_1.test.step('Create Two BPMN Diagrams with User Task and Start Process Instance', async () => {
|
|
434
452
|
await (0, UtilitiesPage_1.runMultipleProcesses)(clusterName, page, modelerHomePage, modelerCreatePage, {
|
|
@@ -35,7 +35,7 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
35
35
|
await (0, mailSlurpClient_1.deleteInbox)(inboxes[testInfo.title]);
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
|
-
(0, _8_10_1.test)('Form.js Integration with User Task and AI Generated Form @ai-external', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, consoleOrganizationsPage, }) => {
|
|
38
|
+
(0, _8_10_1.test)('Form.js Integration with User Task and AI Generated Form @ai-external', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, consoleOrganizationsPage, loginPage, }, testInfo) => {
|
|
39
39
|
_8_10_1.test.slow();
|
|
40
40
|
const randomString = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
41
41
|
const processName = 'User_Task_Process_With_AI_Form' + randomString;
|
|
@@ -65,7 +65,16 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
65
65
|
// unclickable project tile. openModelerWithRetry re-runs the handshake,
|
|
66
66
|
// and with it the internal login, when Modeler is not actually signed
|
|
67
67
|
// in.
|
|
68
|
-
|
|
68
|
+
//
|
|
69
|
+
// That handshake retry still assumes Console itself is still
|
|
70
|
+
// authenticated -- re-entering through the apps menu cannot help when
|
|
71
|
+
// the whole session was dropped, not just Modeler's. withSessionRecovery
|
|
72
|
+
// is the fallback for that case: it only engages when the wrapped
|
|
73
|
+
// action still fails, checks whether the tab actually landed on an
|
|
74
|
+
// identity-provider page, and if so signs back in before trying once
|
|
75
|
+
// more (run 35562939552, "Camunda Modeler" banner absent 90s after 3
|
|
76
|
+
// such retries).
|
|
77
|
+
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, testUser, (testInfo.workerIndex + 1) * 1000, () => appsPage.openModelerWithRetry(modelerHomePage.modelerPageBanner, 90000, 3, modelerHomePage.createNewProjectButton));
|
|
69
78
|
});
|
|
70
79
|
await _8_10_1.test.step('Open Cross Component Test Project', async () => {
|
|
71
80
|
await modelerHomePage.clickCrossComponentProjectFolder();
|
|
@@ -357,7 +366,7 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
357
366
|
await (0, deleteOrg_1.deleteOrganization)(page, newOrganizationUuid);
|
|
358
367
|
});
|
|
359
368
|
});
|
|
360
|
-
(0, _8_10_1.test)('Timer Event User Flow @tasklistV2', async ({ homePage, modelerHomePage, appsPage, modelerCreatePage, operateHomePage, operateProcessInstancePage, operateProcessesPage, }) => {
|
|
369
|
+
(0, _8_10_1.test)('Timer Event User Flow @tasklistV2', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, operateHomePage, operateProcessInstancePage, operateProcessesPage, loginPage, }, testInfo) => {
|
|
361
370
|
const processName = 'Timer_Event_Process' + (await (0, _setup_1.generateRandomStringAsync)(3));
|
|
362
371
|
await _8_10_1.test.step('Navigate to Web Modeler', async () => {
|
|
363
372
|
await (0, test_1.expect)(homePage.camundaComponentsButton).toBeVisible({
|
|
@@ -370,7 +379,13 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
370
379
|
});
|
|
371
380
|
});
|
|
372
381
|
await _8_10_1.test.step('Open Cross Component Test Project and Create a BPMN Diagram Template', async () => {
|
|
373
|
-
|
|
382
|
+
// clickCrossComponentProjectFolder() hunts for a project tile that
|
|
383
|
+
// Modeler's own login page will never render. A dropped session (a 5xx
|
|
384
|
+
// from `/api/internal/login`) surfaces here as "element(s) not found"
|
|
385
|
+
// rather than as the sign-out it actually was (run 35562939552) --
|
|
386
|
+
// withSessionRecovery detects that case and signs back in before
|
|
387
|
+
// retrying once, same as the other 8.10 specs that hit this.
|
|
388
|
+
await (0, UtilitiesPage_1.withSessionRecovery)(page, loginPage, appsPage, modelerHomePage.modelerPageBanner, testUser, (testInfo.workerIndex + 1) * 1000, () => modelerHomePage.clickCrossComponentProjectFolder());
|
|
374
389
|
await modelerHomePage.clickDiagramTypeDropdown();
|
|
375
390
|
await modelerHomePage.clickBpmnTemplateOption();
|
|
376
391
|
});
|
|
@@ -183,19 +183,26 @@ _8_9_1.test.describe('HTO User Flow Tests', () => {
|
|
|
183
183
|
await (0, test_1.expect)(operateTabHomePage.editVariableSpinner).not.toBeVisible({
|
|
184
184
|
timeout: 180000,
|
|
185
185
|
});
|
|
186
|
+
// Operate confirms the update with a filtered /v2/variables/search, then
|
|
187
|
+
// immediately reloads the whole list -- and that second read can still
|
|
188
|
+
// hit a stale replica. Trace evidence from a failing run: the filtered
|
|
189
|
+
// query returned "updatedValue" at 02:48:05.682, the list query 90ms
|
|
190
|
+
// later returned "testValue", and Operate stopped polling variables, so
|
|
191
|
+
// the panel stayed pinned to the old value and a passive wait could
|
|
192
|
+
// never recover. Re-assert across page reloads instead.
|
|
193
|
+
await (0, UtilitiesPage_1.assertPageTextWithRetry)(operateTab, '"updatedValue"');
|
|
186
194
|
await (0, test_1.expect)(operateTab.getByText('"testValue"')).not.toBeVisible({
|
|
187
195
|
timeout: 60000,
|
|
188
196
|
});
|
|
189
|
-
await (0, test_1.expect)(operateTab.getByText('"updatedValue"')).toBeVisible({
|
|
190
|
-
timeout: 90000,
|
|
191
|
-
});
|
|
192
197
|
await operateTabAppsPage.clickCamundaApps();
|
|
193
198
|
await operateTabAppsPage.clickTasklist(clusterName);
|
|
194
199
|
await operateTabTaskPanelPage.openTask(processName);
|
|
195
200
|
await (0, test_1.expect)(operateTab.getByText('testVariable')).toBeVisible({
|
|
196
201
|
timeout: 60000,
|
|
197
202
|
});
|
|
198
|
-
|
|
203
|
+
// Tasklist reads the same eventually-consistent variable store Operate
|
|
204
|
+
// just served stale, so give this the same reload-and-re-assert budget.
|
|
205
|
+
await (0, UtilitiesPage_1.assertPageTextWithRetry)(operateTab, '"updatedValue"');
|
|
199
206
|
await (0, test_1.expect)(operateTab.getByText('"testValue"')).not.toBeVisible();
|
|
200
207
|
});
|
|
201
208
|
});
|
|
@@ -389,6 +389,16 @@ _8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
389
389
|
});
|
|
390
390
|
await modelerCreatePage.enterDiagramName(processName);
|
|
391
391
|
await (0, sleep_1.sleep)(10000);
|
|
392
|
+
// The file rename propagates into `bpmn:process@name`, but the canvas
|
|
393
|
+
// serialises its own stale in-memory copy back on the first edit after
|
|
394
|
+
// the rename, so the process deploys as the template default "New BPMN
|
|
395
|
+
// diagram" and `clickProcessInstanceLink(processName)` never matches a
|
|
396
|
+
// row. Set the name on the canvas model, where no later save reverts it.
|
|
397
|
+
await modelerCreatePage.clickCanvas();
|
|
398
|
+
await modelerCreatePage.clickGeneralPropertiesPanel();
|
|
399
|
+
await modelerCreatePage.clickNameInput();
|
|
400
|
+
await modelerCreatePage.fillNamedInput(processName);
|
|
401
|
+
await modelerCreatePage.clickStartEventElement();
|
|
392
402
|
await modelerCreatePage.clickAppendElementButton();
|
|
393
403
|
await modelerCreatePage.clickIntermediateBoundaryEvent();
|
|
394
404
|
await modelerCreatePage.clickChangeTypeButton();
|