@camunda/e2e-test-suite 0.0.809 → 0.0.810
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.
|
@@ -9,6 +9,8 @@ declare class FormJsPage {
|
|
|
9
9
|
readonly textField: Locator;
|
|
10
10
|
readonly documentPreview: Locator;
|
|
11
11
|
readonly keyInput: Locator;
|
|
12
|
+
readonly fieldLabelInput: Locator;
|
|
13
|
+
readonly formIdInput: Locator;
|
|
12
14
|
readonly uploadMultipleFilesToggle: Locator;
|
|
13
15
|
readonly documentReferenceInput: Locator;
|
|
14
16
|
readonly generalPanel: Locator;
|
|
@@ -25,6 +27,8 @@ declare class FormJsPage {
|
|
|
25
27
|
clickGenerateFormButton(): Promise<void>;
|
|
26
28
|
dragAndDrop(source: Locator, target: Locator): Promise<void>;
|
|
27
29
|
fillKeyInput(key: string): Promise<void>;
|
|
30
|
+
fillFieldLabel(label: string): Promise<void>;
|
|
31
|
+
fillFormId(id: string): Promise<void>;
|
|
28
32
|
enableUploadMultipleFiles(): Promise<void>;
|
|
29
33
|
filldocumentReferenceInput(key: string): Promise<void>;
|
|
30
34
|
clickGeneralPropertiesPanel(): Promise<void>;
|
|
@@ -13,6 +13,8 @@ class FormJsPage {
|
|
|
13
13
|
textField;
|
|
14
14
|
documentPreview;
|
|
15
15
|
keyInput;
|
|
16
|
+
fieldLabelInput;
|
|
17
|
+
formIdInput;
|
|
16
18
|
uploadMultipleFilesToggle;
|
|
17
19
|
documentReferenceInput;
|
|
18
20
|
generalPanel;
|
|
@@ -33,6 +35,10 @@ class FormJsPage {
|
|
|
33
35
|
this.filePicker = page.locator('button[data-field-type="filepicker"]');
|
|
34
36
|
this.textField = page.locator('button[data-field-type="textfield"]');
|
|
35
37
|
this.keyInput = page.getByRole('textbox', { name: 'key' });
|
|
38
|
+
this.fieldLabelInput = page.locator('#bio-properties-panel-label');
|
|
39
|
+
// Form-root "Form ID" entry in the form-js editor properties panel; the
|
|
40
|
+
// BPMN start-event link uses a different entry ("formId"), so no collision.
|
|
41
|
+
this.formIdInput = page.locator('#bio-properties-panel-id');
|
|
36
42
|
this.uploadMultipleFilesToggle = page.locator('div[data-entry-id="multiple"] .bio-properties-panel-toggle-switch__switcher');
|
|
37
43
|
this.documentReferenceInput = page.getByRole('textbox', {
|
|
38
44
|
name: 'document reference',
|
|
@@ -89,6 +95,23 @@ class FormJsPage {
|
|
|
89
95
|
await (0, test_1.expect)(this.keyInput).toHaveValue(key, { timeout: 20000 });
|
|
90
96
|
await (0, sleep_1.sleep)(1000);
|
|
91
97
|
}
|
|
98
|
+
async fillFieldLabel(label) {
|
|
99
|
+
// "Field label" is a contenteditable (FEEL-capable) editor, not an <input>,
|
|
100
|
+
// so assert its text content rather than a form value.
|
|
101
|
+
await this.fieldLabelInput.fill(label, { timeout: 60000 });
|
|
102
|
+
await (0, test_1.expect)(this.fieldLabelInput).toContainText(label, { timeout: 20000 });
|
|
103
|
+
await (0, sleep_1.sleep)(1000);
|
|
104
|
+
}
|
|
105
|
+
async fillFormId(id) {
|
|
106
|
+
// On a new form the General group is collapsed; expand it so the form-root
|
|
107
|
+
// "Form ID" input is visible before filling.
|
|
108
|
+
if (!(await this.formIdInput.isVisible())) {
|
|
109
|
+
await this.clickGeneralPropertiesPanel();
|
|
110
|
+
}
|
|
111
|
+
await this.formIdInput.fill(id, { timeout: 60000 });
|
|
112
|
+
await (0, test_1.expect)(this.formIdInput).toHaveValue(id, { timeout: 20000 });
|
|
113
|
+
await (0, sleep_1.sleep)(1000);
|
|
114
|
+
}
|
|
92
115
|
async enableUploadMultipleFiles() {
|
|
93
116
|
await this.uploadMultipleFilesToggle.click({ timeout: 60000 });
|
|
94
117
|
}
|
|
@@ -219,6 +219,7 @@ declare class ModelerCreatePage {
|
|
|
219
219
|
expandPublicationSection(): Promise<void>;
|
|
220
220
|
enablePublicAccessIfDisabled(): Promise<void>;
|
|
221
221
|
clickPublicationTab(): Promise<void>;
|
|
222
|
+
ensureCopyPublicLinkButtonVisible(): Promise<void>;
|
|
222
223
|
clickCopyPublicLinkButton(): Promise<void>;
|
|
223
224
|
getPublicationLink(): Promise<string>;
|
|
224
225
|
assertFormEmbedded(): Promise<void>;
|
|
@@ -219,8 +219,8 @@ class ModelerCreatePage {
|
|
|
219
219
|
name: 'Toggle public access',
|
|
220
220
|
});
|
|
221
221
|
this.publicationTab = page.getByRole('tab', { name: 'Publication' });
|
|
222
|
-
this.copyPublicLinkButton = page.getByRole('
|
|
223
|
-
name: 'Copy
|
|
222
|
+
this.copyPublicLinkButton = page.getByRole('textbox', {
|
|
223
|
+
name: 'Copy to clipboard',
|
|
224
224
|
});
|
|
225
225
|
this.closeButton = page.getByRole('button', { name: 'Close' });
|
|
226
226
|
this.rbaEnabledDeployedDialog = page.getByRole('dialog', {
|
|
@@ -1230,7 +1230,7 @@ class ModelerCreatePage {
|
|
|
1230
1230
|
await this.startEventElement.click({ timeout: 90000 });
|
|
1231
1231
|
await (0, sleep_1.sleep)(1000);
|
|
1232
1232
|
await this.expandFormsSection();
|
|
1233
|
-
await this.formLinkTypeOptions.selectOption('
|
|
1233
|
+
await this.formLinkTypeOptions.selectOption('camunda-form-linked');
|
|
1234
1234
|
await this.fillFormIdInput(formId);
|
|
1235
1235
|
if (isPublic) {
|
|
1236
1236
|
await this.enablePublicAccessIfDisabled();
|
|
@@ -1265,21 +1265,35 @@ class ModelerCreatePage {
|
|
|
1265
1265
|
},
|
|
1266
1266
|
});
|
|
1267
1267
|
}
|
|
1268
|
+
async ensureCopyPublicLinkButtonVisible() {
|
|
1269
|
+
await this.clickPublicationTab();
|
|
1270
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1271
|
+
const isVisible = await this.copyPublicLinkButton.isVisible();
|
|
1272
|
+
if (isVisible) {
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
await this.page.reload();
|
|
1276
|
+
await this.page.waitForLoadState('load');
|
|
1277
|
+
await this.clickStartEventElement();
|
|
1278
|
+
await this.clickPublicationTab();
|
|
1279
|
+
}
|
|
1280
|
+
await (0, test_1.expect)(this.copyPublicLinkButton).toBeVisible({ timeout: 60000 });
|
|
1281
|
+
}
|
|
1268
1282
|
async clickCopyPublicLinkButton() {
|
|
1283
|
+
await this.ensureCopyPublicLinkButtonVisible();
|
|
1269
1284
|
await this.copyPublicLinkButton.click({ timeout: 60000 });
|
|
1270
1285
|
}
|
|
1271
1286
|
async getPublicationLink() {
|
|
1272
|
-
await this.
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
await
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
return clipboardText;
|
|
1287
|
+
await this.ensureCopyPublicLinkButtonVisible();
|
|
1288
|
+
const codeLocator = this.copyPublicLinkButton.locator('code');
|
|
1289
|
+
// The publication tab polls every 3s for active links; wait until the URL
|
|
1290
|
+
// is present in the DOM before reading it to avoid a race with re-renders.
|
|
1291
|
+
await (0, test_1.expect)(codeLocator).toContainText(/https?:\/\//, { timeout: 60000 });
|
|
1292
|
+
const linkText = await codeLocator.innerText({ timeout: 10000 });
|
|
1293
|
+
const link = linkText.trim();
|
|
1294
|
+
(0, test_1.expect)(link).toMatch(/^https?:\/\//);
|
|
1295
|
+
console.log('Captured public link:', link);
|
|
1296
|
+
return link;
|
|
1283
1297
|
}
|
|
1284
1298
|
async assertFormEmbedded() {
|
|
1285
1299
|
await (0, test_1.expect)(this.formLinkedSuccessMessage).toBeVisible({ timeout: 15000 });
|
|
@@ -15,7 +15,6 @@ const UtilitiesPage_1 = require("../../pages/8.9/UtilitiesPage");
|
|
|
15
15
|
const deleteOrg_1 = require("../../utils/deleteOrg");
|
|
16
16
|
const sleep_1 = require("../../utils/sleep");
|
|
17
17
|
const mailSlurpClient_1 = require("../../utils/mailSlurpClient");
|
|
18
|
-
const resetSession_1 = require("../../utils/resetSession");
|
|
19
18
|
const users_1 = require("../../utils/users");
|
|
20
19
|
const testUser = (0, users_1.getTestUser)('eleventhUser');
|
|
21
20
|
_8_9_1.test.describe.configure({ mode: 'parallel' });
|
|
@@ -415,12 +414,16 @@ _8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
415
414
|
await (0, UtilitiesPage_1.assertLocatorVisibleWithRetry)(operateProcessInstancePage, operateProcessInstancePage.completedIcon, 'Completed icon', 60000, false, 5);
|
|
416
415
|
});
|
|
417
416
|
});
|
|
418
|
-
|
|
419
|
-
_8_9_1.test.skip('Form.js Integration with User Task and Public Form @tasklistV1', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, browser, }) => {
|
|
417
|
+
(0, _8_9_1.test)('Form.js Integration with User Task and Public Form @tasklistV1', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, taskDetailsPage, taskPanelPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, browser, }) => {
|
|
420
418
|
_8_9_1.test.slow();
|
|
421
419
|
const randomString = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
422
420
|
const processName = 'User_Task_Process_With_Public_Form' + randomString;
|
|
423
421
|
const formName = 'Public form' + randomString;
|
|
422
|
+
// Unique per run so repeated runs in the shared project never collide and
|
|
423
|
+
// the start-event link resolves to exactly one form.
|
|
424
|
+
const publicFormId = 'Public_Form_' + randomString;
|
|
425
|
+
const publicFormFieldKey = 'Public_Form_Field_' + randomString;
|
|
426
|
+
const publicFormSubmission = 'Test submission from public link';
|
|
424
427
|
await _8_9_1.test.step('Navigate to Web Modeler', async () => {
|
|
425
428
|
await (0, test_1.expect)(homePage.camundaComponentsButton).toBeVisible({
|
|
426
429
|
timeout: 120000,
|
|
@@ -439,10 +442,17 @@ _8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
439
442
|
await modelerHomePage.clickFormOption();
|
|
440
443
|
await modelerHomePage.enterFormName(formName);
|
|
441
444
|
await (0, sleep_1.sleep)(10000);
|
|
445
|
+
// Set the form's own ID so the start-event link resolves to a deployed
|
|
446
|
+
// form; otherwise the public form 404s.
|
|
447
|
+
await formJsPage.fillFormId(publicFormId);
|
|
442
448
|
await formJsPage.dragAndDrop(formJsPage.textField, formJsPage.formEditor);
|
|
443
449
|
await formJsPage.clickGeneralPropertiesPanel();
|
|
444
|
-
await formJsPage.
|
|
450
|
+
await formJsPage.fillFieldLabel(publicFormFieldKey);
|
|
451
|
+
await formJsPage.fillKeyInput(publicFormFieldKey);
|
|
445
452
|
await (0, sleep_1.sleep)(10000);
|
|
453
|
+
// Deploy the form as its own cluster resource so Tasklist can serve the
|
|
454
|
+
// public start form; the BPMN deploy alone does not include it.
|
|
455
|
+
await formJsPage.deployForm(clusterName);
|
|
446
456
|
});
|
|
447
457
|
await _8_9_1.test.step('Add A BPMN Template To The Project', async () => {
|
|
448
458
|
await modelerHomePage.clickProjectBreadcrumb();
|
|
@@ -451,7 +461,7 @@ _8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
451
461
|
});
|
|
452
462
|
await _8_9_1.test.step('Create BPMN Diagram with a User Task with an embedded AI Generated Form and Start Process Instance', async () => {
|
|
453
463
|
await modelerCreatePage.modelCamundaUserTaskDiagram(processName, processName);
|
|
454
|
-
await modelerCreatePage.linkFormToStartEvent(
|
|
464
|
+
await modelerCreatePage.linkFormToStartEvent(publicFormId, true);
|
|
455
465
|
await modelerCreatePage.deployDiagram(clusterName);
|
|
456
466
|
await (0, sleep_1.sleep)(5000);
|
|
457
467
|
});
|
|
@@ -462,45 +472,49 @@ _8_9_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
462
472
|
publicFormLink = await modelerCreatePage.getPublicationLink();
|
|
463
473
|
console.log('Captured public link:', publicFormLink);
|
|
464
474
|
});
|
|
465
|
-
await _8_9_1.test.step('
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
await
|
|
470
|
-
await
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
await
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
await
|
|
492
|
-
await
|
|
493
|
-
await operateTabAppsPage.clickTasklist(clusterName);
|
|
494
|
-
await operateTabTaskPanelPage.openTask(processName);
|
|
495
|
-
await operateTabTaskDetailsPage.clickAssignToMeButton();
|
|
496
|
-
await (0, test_1.expect)(operateTabTaskDetailsPage.assignedToMeText).toBeVisible({
|
|
475
|
+
await _8_9_1.test.step('Access public form anonymously and submit', async () => {
|
|
476
|
+
// A public start form must be reachable without authentication, so open
|
|
477
|
+
// it in a fresh context; the main session stays logged in for the task
|
|
478
|
+
// completion step below.
|
|
479
|
+
const anonContext = await browser.newContext();
|
|
480
|
+
const anonPage = await anonContext.newPage();
|
|
481
|
+
const anonTaskDetailsPage = new TaskDetailsPage_1.TaskDetailsPage(anonPage);
|
|
482
|
+
console.log('Navigating to public form link:', publicFormLink);
|
|
483
|
+
// Re-navigate until the form renders to absorb brief Tasklist import lag
|
|
484
|
+
// after deploy.
|
|
485
|
+
await (0, test_1.expect)(async () => {
|
|
486
|
+
await anonPage.goto(publicFormLink, { waitUntil: 'domcontentloaded' });
|
|
487
|
+
await (0, test_1.expect)(anonTaskDetailsPage.textInput).toBeVisible({
|
|
488
|
+
timeout: 15000,
|
|
489
|
+
});
|
|
490
|
+
}).toPass({ timeout: 120000, intervals: [5000, 10000, 15000] });
|
|
491
|
+
await anonTaskDetailsPage.fillTextInput(publicFormSubmission);
|
|
492
|
+
await anonTaskDetailsPage.clickSubmitButton();
|
|
493
|
+
await (0, test_1.expect)(anonPage.getByRole('heading', { name: 'Success!' })).toBeVisible({ timeout: 30000 });
|
|
494
|
+
await anonContext.close();
|
|
495
|
+
});
|
|
496
|
+
await _8_9_1.test.step('Complete User Task in Tasklist', async () => {
|
|
497
|
+
// The main session is still authenticated, so go straight to Tasklist.
|
|
498
|
+
await appsPage.clickCamundaApps();
|
|
499
|
+
await appsPage.clickTasklist(clusterName);
|
|
500
|
+
await taskPanelPage.openTask(processName);
|
|
501
|
+
await taskDetailsPage.clickAssignToMeButton();
|
|
502
|
+
await (0, test_1.expect)(taskDetailsPage.assignedToMeText).toBeVisible({
|
|
497
503
|
timeout: 60000,
|
|
498
504
|
});
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
await
|
|
503
|
-
await
|
|
505
|
+
// The user task has no form; verify the value submitted via the public
|
|
506
|
+
// form is carried into the task variable, then complete it. The variable
|
|
507
|
+
// value is a JSON string, so it is wrapped in quotes.
|
|
508
|
+
await (0, test_1.expect)(page.getByTitle(`${publicFormFieldKey} Value`)).toHaveValue(`"${publicFormSubmission}"`, { timeout: 30000 });
|
|
509
|
+
await taskDetailsPage.clickCompleteTaskButton();
|
|
510
|
+
});
|
|
511
|
+
await _8_9_1.test.step('Assert Process Instance is Completed in Operate', async () => {
|
|
512
|
+
await appsPage.clickCamundaApps();
|
|
513
|
+
await appsPage.clickOperate(clusterName);
|
|
514
|
+
await operateHomePage.clickProcessesTab();
|
|
515
|
+
await operateProcessesPage.clickProcessCompletedCheckbox();
|
|
516
|
+
await operateProcessesPage.clickProcessInstanceLink(processName);
|
|
517
|
+
await operateProcessInstancePage.assertProcessCompleteStatusWithRetry(40000);
|
|
504
518
|
});
|
|
505
519
|
});
|
|
506
520
|
(0, _8_9_1.test)('Conditional Events - Deploy, verify in Operate and verify process in Optimize dashboard @tasklistV2', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, }) => {
|