@camunda/e2e-test-suite 0.0.857 → 0.0.858
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/ModelerCreatePage.js +1 -1
- package/dist/pages/8.10/ModelerHomePage.js +25 -8
- package/dist/tests/8.10/access-user-role-management.spec.js +2 -4
- package/dist/tests/8.10/web-modeler-user-flows.spec.js +24 -21
- package/dist/utils/fileUpload.d.ts +21 -0
- package/dist/utils/fileUpload.js +49 -15
- package/package.json +1 -1
|
@@ -223,7 +223,7 @@ class ModelerCreatePage {
|
|
|
223
223
|
this.copyPublicLinkButton = page.getByRole('button', {
|
|
224
224
|
name: 'Copy to clipboard',
|
|
225
225
|
});
|
|
226
|
-
this.closeButton = page.getByRole('button', { name: 'Close' });
|
|
226
|
+
this.closeButton = page.getByRole('button', { name: 'Close', exact: true });
|
|
227
227
|
this.rbaEnabledDeployedDialog = page.getByRole('dialog', {
|
|
228
228
|
name: 'Process successfully deployed',
|
|
229
229
|
});
|
|
@@ -101,19 +101,36 @@ class ModelerHomePage {
|
|
|
101
101
|
// is not yet in edit mode as fill() runs, leaving the project named
|
|
102
102
|
// "New project". Re-enter until the field reflects the requested name.
|
|
103
103
|
//
|
|
104
|
-
// Once the rename commits, the editable input unmounts and the
|
|
105
|
-
// renders as
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
104
|
+
// Once the rename commits, the editable input unmounts and the name
|
|
105
|
+
// renders as static text: on the projects list as a `[title="<name>"]`
|
|
106
|
+
// link, and on the project detail page (where this inline rename runs) as
|
|
107
|
+
// the breadcrumb project button's text. Matching only `[title]` missed the
|
|
108
|
+
// detail-page case, so after a successful rename the retry kept clicking a
|
|
109
|
+
// `[data-test="editable-input"]` that had already unmounted and hung for
|
|
110
|
+
// the full click timeout. Treat either committed-name rendering as success,
|
|
111
|
+
// and wait for it after Enter — the breadcrumb briefly shows "Loading..."
|
|
112
|
+
// until the change is persisted.
|
|
113
|
+
const committedProjectName = this.page
|
|
114
|
+
.getByTitle(name, { exact: true })
|
|
115
|
+
.or(this.page
|
|
116
|
+
.locator('[data-test="breadcrumb-project-menu"]')
|
|
117
|
+
.filter({ hasText: name }));
|
|
109
118
|
await (0, test_1.expect)(async () => {
|
|
110
|
-
if (await
|
|
119
|
+
if (await committedProjectName.first().isVisible()) {
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
|
-
await this.projectNameInput.click({ timeout:
|
|
122
|
+
await this.projectNameInput.click({ timeout: 15000 });
|
|
114
123
|
await this.projectNameInput.fill(name);
|
|
115
|
-
|
|
124
|
+
// Confirm the value actually landed in the edit field before committing;
|
|
125
|
+
// if fill() ran before edit mode was active the input stays empty/default
|
|
126
|
+
// and this fails, so toPass retries with a fresh click.
|
|
116
127
|
await (0, test_1.expect)(this.projectNameInput).toHaveValue(name, { timeout: 5000 });
|
|
128
|
+
await this.projectNameInput.press('Enter');
|
|
129
|
+
await (0, sleep_1.sleep)(1000);
|
|
130
|
+
// Reload so the check reflects the PERSISTED server state, not the
|
|
131
|
+
// optimistic client render that can silently revert to "New project".
|
|
132
|
+
await this.page.reload();
|
|
133
|
+
await (0, test_1.expect)(committedProjectName.first()).toBeVisible({ timeout: 15000 });
|
|
117
134
|
}).toPass({ timeout: 120000 });
|
|
118
135
|
}
|
|
119
136
|
async enterIdpApplicationName(name) {
|
|
@@ -129,8 +129,7 @@ _8_10_1.test.describe('User Roles User Flow', () => {
|
|
|
129
129
|
await modelerCreatePage.clickCloseButton();
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
|
-
|
|
133
|
-
_8_10_1.test.skip('Analyst Role User Flow', async ({ page, modelerHomePage, appsPage, homePage, clusterPage, clusterDetailsPage, browser, consoleOrganizationsPage, settingsPage, operateHomePage, ocIdentityHomePage, taskPanelPage, optimizeHomePage, modelerCreatePage, }) => {
|
|
132
|
+
(0, _8_10_1.test)('Analyst Role User Flow', async ({ page, modelerHomePage, appsPage, homePage, clusterPage, clusterDetailsPage, browser, consoleOrganizationsPage, settingsPage, operateHomePage, ocIdentityHomePage, taskPanelPage, optimizeHomePage, modelerCreatePage, }) => {
|
|
134
133
|
_8_10_1.test.slow();
|
|
135
134
|
const randomString = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
136
135
|
const processName = 'User Roles User Flow' + randomString;
|
|
@@ -221,8 +220,7 @@ _8_10_1.test.describe('User Roles User Flow', () => {
|
|
|
221
220
|
await modelerCreatePage.clickCloseButton();
|
|
222
221
|
});
|
|
223
222
|
});
|
|
224
|
-
|
|
225
|
-
_8_10_1.test.skip('Admin Role User Flow', async ({ page, modelerHomePage, appsPage, homePage, clusterPage, clusterDetailsPage, browser, consoleOrganizationsPage, settingsPage, operateHomePage, ocIdentityHomePage, taskPanelPage, optimizeHomePage, modelerCreatePage, }) => {
|
|
223
|
+
(0, _8_10_1.test)('Admin Role User Flow', async ({ page, modelerHomePage, appsPage, homePage, clusterPage, clusterDetailsPage, browser, consoleOrganizationsPage, settingsPage, operateHomePage, ocIdentityHomePage, taskPanelPage, optimizeHomePage, modelerCreatePage, }) => {
|
|
226
224
|
_8_10_1.test.slow();
|
|
227
225
|
const randomString = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
228
226
|
const processName = 'User Roles User Flow' + randomString;
|
|
@@ -6,9 +6,8 @@ const TaskPanelPage_1 = require("../../pages/8.10/TaskPanelPage");
|
|
|
6
6
|
const TaskDetailsPage_1 = require("../../pages/8.10/TaskDetailsPage");
|
|
7
7
|
const AppsPage_1 = require("../../pages/8.10/AppsPage");
|
|
8
8
|
const OperateProcessInstancePage_1 = require("../../pages/8.10/OperateProcessInstancePage");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// import {OptimizeDashboardPage} from '../../pages/8.10/OptimizeDashboardPage';
|
|
9
|
+
const OptimizeHomePage_1 = require("../../pages/8.10/OptimizeHomePage");
|
|
10
|
+
const OptimizeDashboardPage_1 = require("../../pages/8.10/OptimizeDashboardPage");
|
|
12
11
|
const fileUpload_1 = require("../../utils/fileUpload");
|
|
13
12
|
const _setup_1 = require("../../test-setup.js");
|
|
14
13
|
const UtilitiesPage_1 = require("../../pages/8.10/UtilitiesPage");
|
|
@@ -408,9 +407,13 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
408
407
|
});
|
|
409
408
|
(0, _8_10_1.test)('Conditional Events - Deploy, verify in Operate and verify process in Optimize dashboard @tasklistV2', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, }) => {
|
|
410
409
|
_8_10_1.test.slow();
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
410
|
+
const suffix = await (0, _setup_1.generateRandomStringAsync)(5);
|
|
411
|
+
const diagramName = `Conditional_Events_All_${suffix}`;
|
|
412
|
+
const bpmnFileName = `${diagramName}.bpmn`;
|
|
413
|
+
const processName = `Conditional Events Auto-Run ${suffix}`;
|
|
414
|
+
const bpmnContent = (0, fileUpload_1.readResourceFile)('Conditional_Events_All.bpmn')
|
|
415
|
+
.replaceAll('conditional-events-auto-process', `conditional-events-auto-process-${suffix}`)
|
|
416
|
+
.replace('Conditional Events Auto-Run Demo', processName);
|
|
414
417
|
await _8_10_1.test.step('Navigate to Web Modeler', async () => {
|
|
415
418
|
await (0, test_1.expect)(homePage.camundaComponentsButton).toBeVisible({
|
|
416
419
|
timeout: 120000,
|
|
@@ -425,11 +428,14 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
425
428
|
await modelerHomePage.clickCrossComponentProjectFolder();
|
|
426
429
|
await modelerHomePage.clickDiagramTypeDropdown();
|
|
427
430
|
await modelerHomePage.clickUploadFilesButton();
|
|
428
|
-
await (0, fileUpload_1.
|
|
431
|
+
await (0, fileUpload_1.uploadFileContent)(page, {
|
|
432
|
+
name: bpmnFileName,
|
|
433
|
+
buffer: Buffer.from(bpmnContent),
|
|
434
|
+
});
|
|
429
435
|
});
|
|
430
436
|
await _8_10_1.test.step('Open uploaded BPMN diagram', async () => {
|
|
431
437
|
await (0, sleep_1.sleep)(5000);
|
|
432
|
-
await modelerHomePage.clickProcessDiagram(
|
|
438
|
+
await modelerHomePage.clickProcessDiagram(diagramName);
|
|
433
439
|
});
|
|
434
440
|
await _8_10_1.test.step('Deploy and run process with variable', async () => {
|
|
435
441
|
const variables = '{"myVar": 8}';
|
|
@@ -442,23 +448,20 @@ _8_10_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
442
448
|
await modelerCreatePage.clickViewProcessInstanceLink();
|
|
443
449
|
const operateTabPromise = page.waitForEvent('popup', { timeout: 60000 });
|
|
444
450
|
const operateTab = await operateTabPromise;
|
|
445
|
-
// TODO: Uncomment when Optimize tests are re-enabled
|
|
446
|
-
// const operateTabAppsPage = new AppsPage(operateTab);
|
|
447
451
|
const operateProcessInstancePage = new OperateProcessInstancePage_1.OperateProcessInstancePage(operateTab);
|
|
448
452
|
await operateProcessInstancePage.closePopOverIfVisible();
|
|
449
453
|
await operateProcessInstancePage.assertProcessCompleteStatusWithRetry(60000, 15);
|
|
450
454
|
await operateProcessInstancePage.assertProcessVariableContainsText('myVar', '8');
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
// });
|
|
455
|
+
await _8_10_1.test.step('Navigate to Optimize and verify process in dashboard', async () => {
|
|
456
|
+
const operateTabAppsPage = new AppsPage_1.AppsPage(operateTab);
|
|
457
|
+
await operateTabAppsPage.clickCamundaApps();
|
|
458
|
+
await operateTabAppsPage.clickOptimize(clusterName);
|
|
459
|
+
const optimizeHomePage = new OptimizeHomePage_1.OptimizeHomePage(operateTab);
|
|
460
|
+
const optimizeDashboardPage = new OptimizeDashboardPage_1.OptimizeDashboardPage(operateTab);
|
|
461
|
+
await optimizeHomePage.clickDashboardLink();
|
|
462
|
+
await (0, sleep_1.sleep)(60000);
|
|
463
|
+
await optimizeDashboardPage.processLinkAssertion(processName, 5);
|
|
464
|
+
});
|
|
462
465
|
});
|
|
463
466
|
});
|
|
464
467
|
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Page } from '@playwright/test';
|
|
3
|
+
type InMemoryFile = {
|
|
4
|
+
name: string;
|
|
5
|
+
mimeType?: string;
|
|
6
|
+
buffer: Buffer;
|
|
7
|
+
};
|
|
2
8
|
/**
|
|
3
9
|
* Uploads a file to the file input in the provided page.
|
|
4
10
|
* @param page The Playwright page object.
|
|
@@ -6,3 +12,18 @@ import { Page } from '@playwright/test';
|
|
|
6
12
|
* @throws Will throw an error if the file doesn't exist.
|
|
7
13
|
*/
|
|
8
14
|
export declare function uploadFile(page: Page, fileNames: string | string[]): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Uploads in-memory file content to the file input in the provided page.
|
|
17
|
+
* Use this to upload generated content (e.g. a fixture rewritten with a
|
|
18
|
+
* unique process id/name) without writing a temporary file to disk.
|
|
19
|
+
* @param page The Playwright page object.
|
|
20
|
+
* @param files The file(s) to upload, each with a name and buffer.
|
|
21
|
+
*/
|
|
22
|
+
export declare function uploadFileContent(page: Page, files: InMemoryFile | InMemoryFile[]): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Reads a fixture from the resources directory as a UTF-8 string.
|
|
25
|
+
* @param fileName The file name relative to the resources directory.
|
|
26
|
+
* @throws Will throw an error if the file doesn't exist.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readResourceFile(fileName: string): string;
|
|
29
|
+
export {};
|
package/dist/utils/fileUpload.js
CHANGED
|
@@ -3,9 +3,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.uploadFile = void 0;
|
|
6
|
+
exports.readResourceFile = exports.uploadFileContent = exports.uploadFile = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
async function setInputFilesWithFallback(page, files) {
|
|
10
|
+
const isPathList = files.every((file) => typeof file === 'string');
|
|
11
|
+
const payload = isPathList
|
|
12
|
+
? files
|
|
13
|
+
: files.map((file) => ({
|
|
14
|
+
name: file.name,
|
|
15
|
+
mimeType: file.mimeType ?? 'application/xml',
|
|
16
|
+
buffer: file.buffer,
|
|
17
|
+
}));
|
|
18
|
+
try {
|
|
19
|
+
await page.locator('input[type="file"]').setInputFiles(payload);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
try {
|
|
23
|
+
await page.getByLabel('Upload files').setInputFiles(payload);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
await page.getByLabel('Upload documents').setInputFiles(payload);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
9
30
|
/**
|
|
10
31
|
* Uploads a file to the file input in the provided page.
|
|
11
32
|
* @param page The Playwright page object.
|
|
@@ -20,19 +41,32 @@ async function uploadFile(page, fileNames) {
|
|
|
20
41
|
}
|
|
21
42
|
});
|
|
22
43
|
console.log('Uploading files:', filePaths);
|
|
23
|
-
|
|
24
|
-
const fileInput = await page.locator('input[type="file"]');
|
|
25
|
-
await fileInput.setInputFiles(filePaths);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
try {
|
|
29
|
-
const fileInput = await page.getByLabel('Upload files');
|
|
30
|
-
await fileInput.setInputFiles(filePaths);
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
const fileInput = await page.getByLabel('Upload documents');
|
|
34
|
-
await fileInput.setInputFiles(filePaths);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
44
|
+
await setInputFilesWithFallback(page, filePaths);
|
|
37
45
|
}
|
|
38
46
|
exports.uploadFile = uploadFile;
|
|
47
|
+
/**
|
|
48
|
+
* Uploads in-memory file content to the file input in the provided page.
|
|
49
|
+
* Use this to upload generated content (e.g. a fixture rewritten with a
|
|
50
|
+
* unique process id/name) without writing a temporary file to disk.
|
|
51
|
+
* @param page The Playwright page object.
|
|
52
|
+
* @param files The file(s) to upload, each with a name and buffer.
|
|
53
|
+
*/
|
|
54
|
+
async function uploadFileContent(page, files) {
|
|
55
|
+
const inMemoryFiles = Array.isArray(files) ? files : [files];
|
|
56
|
+
console.log('Uploading in-memory files:', inMemoryFiles.map((file) => file.name));
|
|
57
|
+
await setInputFilesWithFallback(page, inMemoryFiles);
|
|
58
|
+
}
|
|
59
|
+
exports.uploadFileContent = uploadFileContent;
|
|
60
|
+
/**
|
|
61
|
+
* Reads a fixture from the resources directory as a UTF-8 string.
|
|
62
|
+
* @param fileName The file name relative to the resources directory.
|
|
63
|
+
* @throws Will throw an error if the file doesn't exist.
|
|
64
|
+
*/
|
|
65
|
+
function readResourceFile(fileName) {
|
|
66
|
+
const filePath = path_1.default.resolve(__dirname, '../resources', fileName);
|
|
67
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
68
|
+
throw new Error(`File not found: ${filePath}`);
|
|
69
|
+
}
|
|
70
|
+
return fs_1.default.readFileSync(filePath, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
exports.readResourceFile = readResourceFile;
|