@camunda/e2e-test-suite 0.0.810 → 0.0.812
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/OptimizeCollectionsPage.d.ts +13 -0
- package/dist/pages/8.10/OptimizeCollectionsPage.js +105 -0
- package/dist/tests/8.10/optimize-collections-ui.spec.d.ts +1 -0
- package/dist/tests/8.10/optimize-collections-ui.spec.js +46 -0
- package/dist/utils/apiHelpers.js +10 -4
- package/package.json +1 -1
|
@@ -4,14 +4,27 @@ declare class OptimizeCollectionsPage {
|
|
|
4
4
|
readonly collectionsPageHeader: Locator;
|
|
5
5
|
readonly createNewButton: Locator;
|
|
6
6
|
readonly reportOption: Locator;
|
|
7
|
+
readonly collectionOption: Locator;
|
|
7
8
|
readonly modalCloseButton: Locator;
|
|
8
9
|
readonly processReport: Locator;
|
|
9
10
|
readonly collectionsLink: Locator;
|
|
11
|
+
readonly collectionNameInput: Locator;
|
|
12
|
+
readonly createCollectionConfirmButton: Locator;
|
|
13
|
+
readonly collectionContextMenuButton: Locator;
|
|
14
|
+
readonly editContextMenuOption: Locator;
|
|
15
|
+
readonly deleteContextMenuOption: Locator;
|
|
16
|
+
readonly confirmDeleteButton: Locator;
|
|
10
17
|
constructor(page: Page);
|
|
11
18
|
clickCollectionsLink(): Promise<void>;
|
|
12
19
|
clickCreateNewButton(): Promise<void>;
|
|
13
20
|
clickCreateNewButtonWithRetry(): Promise<void>;
|
|
14
21
|
clickReportOption(): Promise<void>;
|
|
15
22
|
clickMostRecentProcessReport(reportName: string): Promise<void>;
|
|
23
|
+
createCollection(name: string): Promise<void>;
|
|
24
|
+
finalizeCollectionCreationIfNeeded(): Promise<void>;
|
|
25
|
+
assertCollectionVisible(name: string): Promise<void>;
|
|
26
|
+
renameCollection(newName: string): Promise<void>;
|
|
27
|
+
deleteCollection(): Promise<void>;
|
|
28
|
+
assertCollectionNotVisible(name: string): Promise<void>;
|
|
16
29
|
}
|
|
17
30
|
export { OptimizeCollectionsPage };
|
|
@@ -8,9 +8,16 @@ class OptimizeCollectionsPage {
|
|
|
8
8
|
collectionsPageHeader;
|
|
9
9
|
createNewButton;
|
|
10
10
|
reportOption;
|
|
11
|
+
collectionOption;
|
|
11
12
|
modalCloseButton;
|
|
12
13
|
processReport;
|
|
13
14
|
collectionsLink;
|
|
15
|
+
collectionNameInput;
|
|
16
|
+
createCollectionConfirmButton;
|
|
17
|
+
collectionContextMenuButton;
|
|
18
|
+
editContextMenuOption;
|
|
19
|
+
deleteContextMenuOption;
|
|
20
|
+
confirmDeleteButton;
|
|
14
21
|
constructor(page) {
|
|
15
22
|
this.page = page;
|
|
16
23
|
this.collectionsPageHeader = page.getByRole('heading', {
|
|
@@ -21,11 +28,48 @@ class OptimizeCollectionsPage {
|
|
|
21
28
|
exact: true,
|
|
22
29
|
});
|
|
23
30
|
this.reportOption = page.getByText('Report', { exact: true });
|
|
31
|
+
this.collectionOption = page
|
|
32
|
+
.getByRole('menuitem', { name: 'Collection', exact: true })
|
|
33
|
+
.or(page.getByRole('button', { name: 'Collection', exact: true }));
|
|
24
34
|
this.modalCloseButton = page.locator('button').filter({ hasText: /^Close$/ });
|
|
25
35
|
this.processReport = page.getByText('Process Report').first();
|
|
26
36
|
this.collectionsLink = page
|
|
27
37
|
.getByRole('banner')
|
|
28
38
|
.getByRole('link', { name: 'Collections' });
|
|
39
|
+
this.collectionNameInput = page
|
|
40
|
+
.getByRole('dialog')
|
|
41
|
+
.getByRole('textbox')
|
|
42
|
+
.first();
|
|
43
|
+
this.createCollectionConfirmButton = page
|
|
44
|
+
.getByRole('dialog')
|
|
45
|
+
.getByRole('button', { name: /add data sources|create collection|save/i })
|
|
46
|
+
.or(page.locator('.cds--modal button.confirm.cds--btn--primary'))
|
|
47
|
+
.first();
|
|
48
|
+
this.collectionContextMenuButton = page
|
|
49
|
+
.locator('button.cds--overflow-menu')
|
|
50
|
+
.or(page.getByRole('button', {
|
|
51
|
+
name: /options|context menu|open menu|more|actions/i,
|
|
52
|
+
}))
|
|
53
|
+
.first();
|
|
54
|
+
this.editContextMenuOption = page
|
|
55
|
+
.getByRole('menuitem', { name: /edit/i })
|
|
56
|
+
.or(page.getByRole('button', { name: /edit/i }))
|
|
57
|
+
.or(page.locator('button.cds--overflow-menu-options__btn', {
|
|
58
|
+
hasText: /edit/i,
|
|
59
|
+
}))
|
|
60
|
+
.first();
|
|
61
|
+
this.deleteContextMenuOption = page
|
|
62
|
+
.getByRole('menuitem', { name: /delete/i })
|
|
63
|
+
.or(page.getByRole('button', { name: /delete/i }))
|
|
64
|
+
.or(page.locator('button.cds--overflow-menu-options__btn', {
|
|
65
|
+
hasText: /delete/i,
|
|
66
|
+
}))
|
|
67
|
+
.first();
|
|
68
|
+
this.confirmDeleteButton = page
|
|
69
|
+
.locator('.cds--modal button.confirm')
|
|
70
|
+
.or(page.locator('.Deleter button.confirm'))
|
|
71
|
+
.or(page.getByRole('dialog').getByRole('button', { name: /delete/i }))
|
|
72
|
+
.first();
|
|
29
73
|
}
|
|
30
74
|
async clickCollectionsLink() {
|
|
31
75
|
await (0, test_1.expect)(this.collectionsLink).toBeVisible({ timeout: 60000 });
|
|
@@ -64,5 +108,66 @@ class OptimizeCollectionsPage {
|
|
|
64
108
|
async clickMostRecentProcessReport(reportName) {
|
|
65
109
|
await this.page.getByText(reportName).click({ timeout: 60000 });
|
|
66
110
|
}
|
|
111
|
+
async createCollection(name) {
|
|
112
|
+
await this.clickCreateNewButton();
|
|
113
|
+
await (0, test_1.expect)(this.collectionOption).toBeVisible({ timeout: 30000 });
|
|
114
|
+
await this.collectionOption.click({ timeout: 30000 });
|
|
115
|
+
await (0, test_1.expect)(this.collectionNameInput).toBeVisible({ timeout: 30000 });
|
|
116
|
+
await this.collectionNameInput.click();
|
|
117
|
+
await this.collectionNameInput.fill(name);
|
|
118
|
+
await (0, test_1.expect)(this.createCollectionConfirmButton).toBeVisible({
|
|
119
|
+
timeout: 30000,
|
|
120
|
+
});
|
|
121
|
+
await this.createCollectionConfirmButton.click({ timeout: 30000 });
|
|
122
|
+
await this.finalizeCollectionCreationIfNeeded();
|
|
123
|
+
}
|
|
124
|
+
async finalizeCollectionCreationIfNeeded() {
|
|
125
|
+
const addSourceModal = this.page.getByRole('dialog', {
|
|
126
|
+
name: /add source/i,
|
|
127
|
+
});
|
|
128
|
+
if (await addSourceModal.isVisible({ timeout: 15000 }).catch(() => false)) {
|
|
129
|
+
const createCollectionButton = addSourceModal.getByRole('button', {
|
|
130
|
+
name: /^create collection$/i,
|
|
131
|
+
});
|
|
132
|
+
await (0, test_1.expect)(createCollectionButton).toBeVisible({ timeout: 30000 });
|
|
133
|
+
await createCollectionButton.click({ timeout: 30000 });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async assertCollectionVisible(name) {
|
|
137
|
+
await (0, test_1.expect)(this.page
|
|
138
|
+
.getByRole('heading', { name })
|
|
139
|
+
.or(this.page.getByText(name))
|
|
140
|
+
.first()).toBeVisible({ timeout: 60000 });
|
|
141
|
+
}
|
|
142
|
+
async renameCollection(newName) {
|
|
143
|
+
await (0, test_1.expect)(this.collectionContextMenuButton).toBeVisible({
|
|
144
|
+
timeout: 30000,
|
|
145
|
+
});
|
|
146
|
+
await this.collectionContextMenuButton.click({ timeout: 30000 });
|
|
147
|
+
await (0, test_1.expect)(this.editContextMenuOption).toBeVisible({ timeout: 30000 });
|
|
148
|
+
await this.editContextMenuOption.click({ timeout: 30000 });
|
|
149
|
+
await (0, test_1.expect)(this.collectionNameInput).toBeVisible({ timeout: 30000 });
|
|
150
|
+
await this.collectionNameInput.click();
|
|
151
|
+
await this.collectionNameInput.fill(newName);
|
|
152
|
+
await (0, test_1.expect)(this.createCollectionConfirmButton).toBeVisible({
|
|
153
|
+
timeout: 30000,
|
|
154
|
+
});
|
|
155
|
+
await this.createCollectionConfirmButton.click({ timeout: 30000 });
|
|
156
|
+
}
|
|
157
|
+
async deleteCollection() {
|
|
158
|
+
await (0, test_1.expect)(this.collectionContextMenuButton).toBeVisible({
|
|
159
|
+
timeout: 30000,
|
|
160
|
+
});
|
|
161
|
+
await this.collectionContextMenuButton.click({ timeout: 30000 });
|
|
162
|
+
await (0, test_1.expect)(this.deleteContextMenuOption).toBeVisible({ timeout: 30000 });
|
|
163
|
+
await this.deleteContextMenuOption.click({ timeout: 30000 });
|
|
164
|
+
await (0, test_1.expect)(this.confirmDeleteButton).toBeVisible({ timeout: 30000 });
|
|
165
|
+
await this.confirmDeleteButton.click({ timeout: 30000 });
|
|
166
|
+
}
|
|
167
|
+
async assertCollectionNotVisible(name) {
|
|
168
|
+
await (0, test_1.expect)(this.page.getByText(name).first()).toBeHidden({
|
|
169
|
+
timeout: 60000,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
67
172
|
}
|
|
68
173
|
exports.OptimizeCollectionsPage = OptimizeCollectionsPage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_1 = require("@playwright/test");
|
|
4
|
+
const _8_10_1 = require("../../fixtures/8.10");
|
|
5
|
+
const _setup_1 = require("../../test-setup.js");
|
|
6
|
+
const UtilitiesPage_1 = require("../../pages/8.10/UtilitiesPage");
|
|
7
|
+
const users_1 = require("../../utils/users");
|
|
8
|
+
const testUser = (0, users_1.getTestUser)('twentySecondUser');
|
|
9
|
+
const clusterName = 'Test Cluster';
|
|
10
|
+
_8_10_1.test.describe.configure({ mode: 'parallel' });
|
|
11
|
+
_8_10_1.test.describe('Optimize Collections Lifecycle UI Tests @optimize-collections-ui @8.10', () => {
|
|
12
|
+
_8_10_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
|
|
13
|
+
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, testUser, (testInfo.workerIndex + 1) * 1000);
|
|
14
|
+
});
|
|
15
|
+
_8_10_1.test.afterEach(async ({ page }, testInfo) => {
|
|
16
|
+
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
17
|
+
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
18
|
+
});
|
|
19
|
+
(0, _8_10_1.test)('Create, rename and delete a collection', async ({ appsPage, optimizeHomePage, optimizeCollectionsPage, }) => {
|
|
20
|
+
_8_10_1.test.slow();
|
|
21
|
+
const collectionName = 'E2E Collection ' + (await (0, _setup_1.generateRandomStringAsync)(5));
|
|
22
|
+
const renamedCollectionName = 'E2E Collection Renamed ' + (await (0, _setup_1.generateRandomStringAsync)(5));
|
|
23
|
+
await _8_10_1.test.step('Navigate to Optimize from the Camunda apps menu', async () => {
|
|
24
|
+
await appsPage.clickCamundaApps();
|
|
25
|
+
await appsPage.clickOptimize(clusterName);
|
|
26
|
+
await test_1.expect
|
|
27
|
+
.poll(async () => optimizeHomePage.optimizeBanner.isVisible({ timeout: 5000 }), { timeout: 120000 })
|
|
28
|
+
.toBe(true);
|
|
29
|
+
});
|
|
30
|
+
await _8_10_1.test.step('Open the Collections page', async () => {
|
|
31
|
+
await optimizeHomePage.clickCollectionsLink();
|
|
32
|
+
});
|
|
33
|
+
await _8_10_1.test.step('Create a new collection and verify it is created', async () => {
|
|
34
|
+
await optimizeCollectionsPage.createCollection(collectionName);
|
|
35
|
+
await optimizeCollectionsPage.assertCollectionVisible(collectionName);
|
|
36
|
+
});
|
|
37
|
+
await _8_10_1.test.step('Rename the collection and verify the new name', async () => {
|
|
38
|
+
await optimizeCollectionsPage.renameCollection(renamedCollectionName);
|
|
39
|
+
await optimizeCollectionsPage.assertCollectionVisible(renamedCollectionName);
|
|
40
|
+
});
|
|
41
|
+
await _8_10_1.test.step('Delete the collection and verify it is removed', async () => {
|
|
42
|
+
await optimizeCollectionsPage.deleteCollection();
|
|
43
|
+
await optimizeCollectionsPage.assertCollectionNotVisible(renamedCollectionName);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
package/dist/utils/apiHelpers.js
CHANGED
|
@@ -568,14 +568,20 @@ async function getOptimizeCookieSm(page) {
|
|
|
568
568
|
const optimizeUrl = process.env.CAMUNDA_OPTIMIZE_BASE_URL;
|
|
569
569
|
const username = 'demo';
|
|
570
570
|
const password = process.env.DISTRO_QA_E2E_TESTS_IDENTITY_FIRSTUSER_PASSWORD;
|
|
571
|
-
const maxLoginAttempts =
|
|
571
|
+
const maxLoginAttempts = 6;
|
|
572
572
|
// Upgrade scenarios trigger rolling restarts of Optimize; page.goto can
|
|
573
|
-
// briefly receive a 5xx
|
|
574
|
-
// the #username selector to time
|
|
573
|
+
// briefly receive a 5xx (nginx "503 Service Temporarily Unavailable") and the
|
|
574
|
+
// Keycloak login form never renders, causing the #username selector to time
|
|
575
|
+
// out. A 5xx does not reject page.goto, so detect it from the response status
|
|
576
|
+
// and retry immediately instead of burning the full waitForSelector timeout,
|
|
577
|
+
// widening the readiness window until Optimize finishes restarting.
|
|
575
578
|
let lastLoginError;
|
|
576
579
|
for (let attempt = 1; attempt <= maxLoginAttempts; attempt++) {
|
|
577
580
|
try {
|
|
578
|
-
await page.goto(optimizeUrl, { timeout: 30000 });
|
|
581
|
+
const response = await page.goto(optimizeUrl, { timeout: 30000 });
|
|
582
|
+
if (response && response.status() >= 500) {
|
|
583
|
+
throw new Error(`getOptimizeCookieSm: Optimize returned ${response.status()} on load (service not ready yet)`);
|
|
584
|
+
}
|
|
579
585
|
await page.waitForSelector('#username', { timeout: 30000 });
|
|
580
586
|
await page.fill('#username', username);
|
|
581
587
|
await page.fill('#password', password);
|