@camunda/e2e-test-suite 0.0.111 → 0.0.113
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/fixtures/8.9.d.ts +2 -0
- package/dist/fixtures/8.9.js +4 -0
- package/dist/pages/8.8/ConnectorSettingsPage.js +3 -0
- package/dist/pages/8.8/FormJsPage.d.ts +1 -0
- package/dist/pages/8.8/FormJsPage.js +6 -0
- package/dist/pages/8.8/ModelerCreatePage.js +2 -6
- package/dist/pages/8.9/ClientCredentialsDetailsPage.d.ts +12 -0
- package/dist/pages/8.9/ClientCredentialsDetailsPage.js +36 -0
- package/dist/pages/8.9/ClusterDetailsPage.d.ts +4 -1
- package/dist/pages/8.9/ClusterDetailsPage.js +31 -1
- package/dist/tests/8.8/smoke-tests.spec.js +0 -1
- package/dist/tests/8.8/web-modeler-user-flows.spec.js +1 -0
- package/dist/tests/8.9/operate-access-flow.spec.d.ts +1 -0
- package/dist/tests/8.9/operate-access-flow.spec.js +49 -0
- package/package.json +1 -1
package/dist/fixtures/8.9.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ import { OCIdentityHomePage } from '../pages/8.9/OCIdentityHomePage';
|
|
|
32
32
|
import { OCIdentityMappingRulesPage } from '../pages/8.9/OCIdentityMappingRulesPage';
|
|
33
33
|
import { OCIdentityRolesPage } from '../pages/8.9/OCIdentityRolesPage';
|
|
34
34
|
import { OCIdentityAuthorizationsPage } from '../pages/8.9/OCIdentityAuthorizationsPage';
|
|
35
|
+
import { ClientCredentialsDetailsPage } from '../pages/8.9/ClientCredentialsDetailsPage';
|
|
35
36
|
type PlaywrightFixtures = {
|
|
36
37
|
makeAxeBuilder: () => AxeBuilder;
|
|
37
38
|
loginPage: LoginPage;
|
|
@@ -67,6 +68,7 @@ type PlaywrightFixtures = {
|
|
|
67
68
|
ocIdentityMappingRulesPage: OCIdentityMappingRulesPage;
|
|
68
69
|
ocIdentityRolesPage: OCIdentityRolesPage;
|
|
69
70
|
ocIdentityAuthorizationsPage: OCIdentityAuthorizationsPage;
|
|
71
|
+
clientCredentialsDetailsPage: ClientCredentialsDetailsPage;
|
|
70
72
|
overrideTrackingScripts: void;
|
|
71
73
|
};
|
|
72
74
|
declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & PlaywrightFixtures, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
package/dist/fixtures/8.9.js
CHANGED
|
@@ -39,6 +39,7 @@ const OCIdentityHomePage_1 = require("../pages/8.9/OCIdentityHomePage");
|
|
|
39
39
|
const OCIdentityMappingRulesPage_1 = require("../pages/8.9/OCIdentityMappingRulesPage");
|
|
40
40
|
const OCIdentityRolesPage_1 = require("../pages/8.9/OCIdentityRolesPage");
|
|
41
41
|
const OCIdentityAuthorizationsPage_1 = require("../pages/8.9/OCIdentityAuthorizationsPage");
|
|
42
|
+
const ClientCredentialsDetailsPage_1 = require("../pages/8.9/ClientCredentialsDetailsPage");
|
|
42
43
|
const test = test_1.test.extend({
|
|
43
44
|
makeAxeBuilder: async ({ page }, use) => {
|
|
44
45
|
const makeAxeBuilder = () => new playwright_1.default({ page }).withTags([
|
|
@@ -150,6 +151,9 @@ const test = test_1.test.extend({
|
|
|
150
151
|
ocIdentityGroupsPage: async ({ page }, use) => {
|
|
151
152
|
await use(new OCIdentityGroupsPage_1.OCIdentityGroupsPage(page));
|
|
152
153
|
},
|
|
154
|
+
clientCredentialsDetailsPage: async ({ page }, use) => {
|
|
155
|
+
await use(new ClientCredentialsDetailsPage_1.ClientCredentialsDetailsPage(page));
|
|
156
|
+
},
|
|
153
157
|
overrideTrackingScripts: [
|
|
154
158
|
async ({ context }, use) => {
|
|
155
159
|
await context.route('https://cmp.osano.com/16CVvwSNKHi9t1grQ/9403708a-488b-4f3b-aea6-613825dec79f/osano.js', (route) => route.fulfill({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConnectorSettingsPage = void 0;
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
|
+
const sleep_1 = require("../../utils/sleep");
|
|
5
6
|
class ConnectorSettingsPage {
|
|
6
7
|
page;
|
|
7
8
|
urlInput;
|
|
@@ -68,6 +69,7 @@ class ConnectorSettingsPage {
|
|
|
68
69
|
timeout: 120000,
|
|
69
70
|
force: true,
|
|
70
71
|
});
|
|
72
|
+
(0, test_1.expect)(await this.resultExpressionInput.textContent()).toEqual(resultExpression);
|
|
71
73
|
await this.page.waitForTimeout(1000);
|
|
72
74
|
}
|
|
73
75
|
async selectAuthenticationType(authentication) {
|
|
@@ -107,6 +109,7 @@ class ConnectorSettingsPage {
|
|
|
107
109
|
async fillResultVariableInput(variable) {
|
|
108
110
|
await this.resultVariableInput.fill(variable, { timeout: 90000 });
|
|
109
111
|
(0, test_1.expect)(await this.resultVariableInput.inputValue()).toEqual(variable);
|
|
112
|
+
await (0, sleep_1.sleep)(1000);
|
|
110
113
|
}
|
|
111
114
|
async clickBearerTokenInput() {
|
|
112
115
|
await this.bearerTokenInput.click({ timeout: 90000 });
|
|
@@ -12,6 +12,7 @@ declare class FormJsPage {
|
|
|
12
12
|
readonly uploadMultipleFilesToggle: Locator;
|
|
13
13
|
readonly documentReferenceInput: Locator;
|
|
14
14
|
readonly generalPanel: Locator;
|
|
15
|
+
readonly textFieldInForm: Locator;
|
|
15
16
|
constructor(page: Page);
|
|
16
17
|
generateAIForm(request?: string): Promise<void>;
|
|
17
18
|
clickAIFormGeneratorButton(): Promise<void>;
|
|
@@ -16,6 +16,7 @@ class FormJsPage {
|
|
|
16
16
|
uploadMultipleFilesToggle;
|
|
17
17
|
documentReferenceInput;
|
|
18
18
|
generalPanel;
|
|
19
|
+
textFieldInForm;
|
|
19
20
|
constructor(page) {
|
|
20
21
|
this.page = page;
|
|
21
22
|
this.aiFormGeneratorButton = page.getByRole('button', {
|
|
@@ -33,6 +34,9 @@ class FormJsPage {
|
|
|
33
34
|
});
|
|
34
35
|
this.generalPanel = page.getByTitle('General').first();
|
|
35
36
|
this.textField = page.locator('button[data-field-type="textfield"]');
|
|
37
|
+
this.textFieldInForm = page
|
|
38
|
+
.getByLabel('Form Definition')
|
|
39
|
+
.getByText('Text field');
|
|
36
40
|
}
|
|
37
41
|
async generateAIForm(request = 'Create a form with the following fields: 1. A text field with the label "Full Name" 2. A number with the label "Count" 3. A date input with the label "Date of birth"4. A Checkbox with the label "Agree"') {
|
|
38
42
|
await (0, test_1.expect)(this.aiFormGeneratorButton).toBeVisible({
|
|
@@ -65,6 +69,8 @@ class FormJsPage {
|
|
|
65
69
|
}
|
|
66
70
|
async fillKeyInput(key) {
|
|
67
71
|
await this.keyInput.fill(key, { timeout: 60000 });
|
|
72
|
+
await (0, test_1.expect)(this.keyInput).toHaveValue(key, { timeout: 20000 });
|
|
73
|
+
await (0, sleep_1.sleep)(1000);
|
|
68
74
|
}
|
|
69
75
|
async enableUploadMultipleFiles() {
|
|
70
76
|
await this.uploadMultipleFilesToggle.click({ timeout: 60000 });
|
|
@@ -523,12 +523,8 @@ class ModelerCreatePage {
|
|
|
523
523
|
});
|
|
524
524
|
await this.selectCluster(clusterName);
|
|
525
525
|
await this.clickDeploySubButtonWithRetry(clusterName);
|
|
526
|
-
await (0, test_1.expect)(this.viewProcessLink).toBeVisible({
|
|
527
|
-
|
|
528
|
-
});
|
|
529
|
-
await (0, test_1.expect)(this.viewProcessLink).toBeHidden({
|
|
530
|
-
timeout: 120000,
|
|
531
|
-
});
|
|
526
|
+
await (0, test_1.expect)(this.viewProcessLink).toBeVisible({ timeout: 30000 });
|
|
527
|
+
await (0, test_1.expect)(this.viewProcessLink).toBeHidden({ timeout: 30000 });
|
|
532
528
|
}
|
|
533
529
|
async clickStartInstanceMainButton() {
|
|
534
530
|
if (await this.startInstanceMainButton.isVisible({ timeout: 30000 })) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Page, Locator } from '@playwright/test';
|
|
2
|
+
declare class ClientCredentialsDetailsPage {
|
|
3
|
+
private page;
|
|
4
|
+
readonly operateUrlRow: Locator;
|
|
5
|
+
readonly operateUrlValue: Locator;
|
|
6
|
+
readonly clientNameHeading: (clientName: string) => Locator;
|
|
7
|
+
constructor(page: Page);
|
|
8
|
+
isOpen(clientName: string): Promise<void>;
|
|
9
|
+
getOperateUrl(): Promise<string>;
|
|
10
|
+
goBack(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export { ClientCredentialsDetailsPage };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientCredentialsDetailsPage = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
class ClientCredentialsDetailsPage {
|
|
6
|
+
page;
|
|
7
|
+
operateUrlRow;
|
|
8
|
+
operateUrlValue;
|
|
9
|
+
clientNameHeading;
|
|
10
|
+
constructor(page) {
|
|
11
|
+
this.page = page;
|
|
12
|
+
this.operateUrlRow = page.getByRole('cell', { name: 'Operate URL' });
|
|
13
|
+
this.operateUrlValue = this.operateUrlRow.getByRole('textbox');
|
|
14
|
+
this.clientNameHeading = (clientName) => page.getByRole('heading', { name: clientName });
|
|
15
|
+
}
|
|
16
|
+
async isOpen(clientName) {
|
|
17
|
+
await (0, test_1.expect)(this.clientNameHeading(clientName)).toBeVisible({
|
|
18
|
+
timeout: 30000,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async getOperateUrl() {
|
|
22
|
+
if (await this.operateUrlValue.isVisible({ timeout: 10000 }).catch(() => false)) {
|
|
23
|
+
return await this.operateUrlValue.inputValue();
|
|
24
|
+
}
|
|
25
|
+
const text = await this.page.innerText('body');
|
|
26
|
+
const match = text.match(/Operate URL\s*([\w:/.-]+\/?)/i);
|
|
27
|
+
if (!match || !match[1]) {
|
|
28
|
+
throw new Error('Operate URL not found in client credentials page');
|
|
29
|
+
}
|
|
30
|
+
return match[1];
|
|
31
|
+
}
|
|
32
|
+
async goBack() {
|
|
33
|
+
await this.page.goBack();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.ClientCredentialsDetailsPage = ClientCredentialsDetailsPage;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Page, Locator } from '@playwright/test';
|
|
2
|
+
import { ClientCredentialsDetailsPage } from './ClientCredentialsDetailsPage';
|
|
2
3
|
declare class ClusterDetailsPage {
|
|
3
4
|
private page;
|
|
4
5
|
readonly apiTab: Locator;
|
|
@@ -36,6 +37,7 @@ declare class ClusterDetailsPage {
|
|
|
36
37
|
readonly rbaEnabledMessage: Locator;
|
|
37
38
|
readonly authorizationsHeading: Locator;
|
|
38
39
|
readonly orchestrationClusterCheckbox: Locator;
|
|
40
|
+
readonly clientCredentialsLink: (clientCredentials: string) => Locator;
|
|
39
41
|
constructor(page: Page);
|
|
40
42
|
clickAPITab(): Promise<void>;
|
|
41
43
|
clickCreateClientButton(): Promise<void>;
|
|
@@ -50,7 +52,8 @@ declare class ClusterDetailsPage {
|
|
|
50
52
|
clickSettingsTab(): Promise<void>;
|
|
51
53
|
enableAuthorizations(): Promise<void>;
|
|
52
54
|
disableAuthorizations(): Promise<void>;
|
|
53
|
-
|
|
55
|
+
searchAndClickClientCredentialsLink(name: string): Promise<ClientCredentialsDetailsPage>;
|
|
56
|
+
deleteAPIClientsIfExist(name?: string): Promise<void>;
|
|
54
57
|
clickAlertsTab(): Promise<void>;
|
|
55
58
|
clickExpandButton(): Promise<void>;
|
|
56
59
|
clickCreateFirstAlertButton(): Promise<void>;
|
|
@@ -5,6 +5,7 @@ const test_1 = require("@playwright/test");
|
|
|
5
5
|
const sleep_1 = require("../../utils/sleep");
|
|
6
6
|
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
|
|
7
7
|
const expectLocatorWithRetry_1 = require("../../utils/assertionHelpers/expectLocatorWithRetry");
|
|
8
|
+
const ClientCredentialsDetailsPage_1 = require("./ClientCredentialsDetailsPage");
|
|
8
9
|
class ClusterDetailsPage {
|
|
9
10
|
page;
|
|
10
11
|
apiTab;
|
|
@@ -42,6 +43,7 @@ class ClusterDetailsPage {
|
|
|
42
43
|
rbaEnabledMessage;
|
|
43
44
|
authorizationsHeading;
|
|
44
45
|
orchestrationClusterCheckbox;
|
|
46
|
+
clientCredentialsLink;
|
|
45
47
|
constructor(page) {
|
|
46
48
|
this.page = page;
|
|
47
49
|
this.apiTab = page.getByRole('tab', { name: 'API' });
|
|
@@ -121,6 +123,7 @@ class ClusterDetailsPage {
|
|
|
121
123
|
this.orchestrationClusterCheckbox = page
|
|
122
124
|
.locator('label')
|
|
123
125
|
.filter({ hasText: /^Orchestration Cluster API$/ });
|
|
126
|
+
this.clientCredentialsLink = (clientCredentials) => page.getByRole('cell', { name: clientCredentials });
|
|
124
127
|
}
|
|
125
128
|
async clickAPITab() {
|
|
126
129
|
await (0, test_1.expect)(this.apiTab).toBeVisible({ timeout: 60000 });
|
|
@@ -225,7 +228,34 @@ class ClusterDetailsPage {
|
|
|
225
228
|
console.log('Toggle text elements not found or less than 2.');
|
|
226
229
|
}
|
|
227
230
|
}
|
|
228
|
-
async
|
|
231
|
+
async searchAndClickClientCredentialsLink(name) {
|
|
232
|
+
await (0, test_1.expect)(this.clientsList.first()).toBeVisible({ timeout: 60000 });
|
|
233
|
+
const clientLink = this.clientCredentialsLink(name);
|
|
234
|
+
await (0, test_1.expect)(clientLink).toBeVisible({ timeout: 30000 });
|
|
235
|
+
await clientLink.click();
|
|
236
|
+
const clientCredentialsDetailsPage = new ClientCredentialsDetailsPage_1.ClientCredentialsDetailsPage(this.page);
|
|
237
|
+
await clientCredentialsDetailsPage.isOpen(name);
|
|
238
|
+
return clientCredentialsDetailsPage;
|
|
239
|
+
}
|
|
240
|
+
async deleteAPIClientsIfExist(name) {
|
|
241
|
+
if (name) {
|
|
242
|
+
const row = this.clientsList.filter({ hasText: name });
|
|
243
|
+
const deleteButton = row.getByRole('button', { name: 'Delete' });
|
|
244
|
+
try {
|
|
245
|
+
await (0, test_1.expect)(deleteButton).toBeVisible({ timeout: 10000 });
|
|
246
|
+
await deleteButton.click();
|
|
247
|
+
await (0, test_1.expect)(this.dialog).toBeVisible();
|
|
248
|
+
await this.deleteSubButton.click();
|
|
249
|
+
await (0, test_1.expect)(this.page.getByText('Deleting...')).not.toBeVisible({
|
|
250
|
+
timeout: 10000,
|
|
251
|
+
});
|
|
252
|
+
await (0, test_1.expect)(row).not.toBeVisible();
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.warn(`No client row found for ${name} or deletion failed: ${error}`);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
229
259
|
await this.doDelete(this.dialog, 'API clients');
|
|
230
260
|
}
|
|
231
261
|
async clickAlertsTab() {
|
|
@@ -157,7 +157,6 @@ _8_8_1.test.describe('Smoke Tests', () => {
|
|
|
157
157
|
await _8_8_1.test.step('Create BPMN Diagram with REST Connector with Basic Auth and Start Process Instance', async () => {
|
|
158
158
|
await (0, UtilitiesPage_1.modelRestConnector)(modelerCreatePage, connectorSettingsPage, processName, 'https://camunda.proxy.beeceptor.com/pre-prod/basic-auth-test', 'basic', '{message:response.body.message}', 'result', { username: 'username', password: 'password' });
|
|
159
159
|
await modelerCreatePage.runProcessInstance(clusterName);
|
|
160
|
-
await (0, _setup_1.performBasicAuthPostRequest)('https://camunda.proxy.beeceptor.com/pre-prod/basic-auth-test', 'username', 'password');
|
|
161
160
|
});
|
|
162
161
|
await _8_8_1.test.step('View Process Instance in Operate, assert it completes and assert result expression', async () => {
|
|
163
162
|
await appsPage.clickCamundaApps();
|
|
@@ -427,6 +427,7 @@ _8_8_1.test.describe('Web Modeler User Flow Tests', () => {
|
|
|
427
427
|
await modelerHomePage.clickFormOption();
|
|
428
428
|
await modelerHomePage.enterFormName(formName);
|
|
429
429
|
await formJsPage.dragAndDrop(formJsPage.textField, formJsPage.formEditor);
|
|
430
|
+
await (0, test_1.expect)(formJsPage.textFieldInForm).toBeVisible();
|
|
430
431
|
await formJsPage.clickGeneralPropertiesPanel();
|
|
431
432
|
await formJsPage.fillKeyInput('Public_Form_Text_Field');
|
|
432
433
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_1 = require("@playwright/test");
|
|
4
|
+
const _8_9_1 = require("../../fixtures/8.9");
|
|
5
|
+
const UtilitiesPage_1 = require("../../pages/8.9/UtilitiesPage");
|
|
6
|
+
const _setup_1 = require("../../test-setup.js");
|
|
7
|
+
// This test covers the manual scenario: create a new API client via UI, copy the Operate URL, and verify the Operate endpoint denies unauthenticated access.
|
|
8
|
+
_8_9_1.test.describe.configure({ mode: 'parallel' });
|
|
9
|
+
_8_9_1.test.describe('Operate access requires authentication @tasklistV2', () => {
|
|
10
|
+
let clientName;
|
|
11
|
+
const clusterName = 'Test Cluster';
|
|
12
|
+
_8_9_1.test.afterEach(async ({ page, clusterDetailsPage }, testInfo) => {
|
|
13
|
+
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
14
|
+
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
15
|
+
await clusterDetailsPage.clickAPITab();
|
|
16
|
+
await clusterDetailsPage.deleteAPIClientsIfExist(clientName);
|
|
17
|
+
});
|
|
18
|
+
_8_9_1.test.beforeEach(async ({ page, loginPage }, testInfo) => {
|
|
19
|
+
await (0, UtilitiesPage_1.loginWithRetry)(page, loginPage, (testInfo.workerIndex + 1) * 1000);
|
|
20
|
+
});
|
|
21
|
+
(0, _8_9_1.test)('check that request POST /v2/process-definitions/search returns 401 without credentials', async ({ homePage, clusterPage, clusterDetailsPage, clientCredentialsDetailsPage, request, }) => {
|
|
22
|
+
clientName = `operate-deny-${await (0, _setup_1.generateRandomStringAsync)(5)}`;
|
|
23
|
+
await _8_9_1.test.step('Add API Client to Cluster', async () => {
|
|
24
|
+
await homePage.clickClusters();
|
|
25
|
+
await clusterPage.clickClusterLink(clusterName);
|
|
26
|
+
await clusterDetailsPage.clickAPITab();
|
|
27
|
+
await clusterDetailsPage.createAPIClient(clientName);
|
|
28
|
+
await clusterDetailsPage.clickCloseModalButton();
|
|
29
|
+
await (0, test_1.expect)(clusterDetailsPage.clientsList.filter({ hasText: clientName })).toBeVisible({ timeout: 6000 });
|
|
30
|
+
});
|
|
31
|
+
let operateUrl = '';
|
|
32
|
+
await _8_9_1.test.step('Capture Operate URL from client credentials page and close it', async () => {
|
|
33
|
+
await clusterDetailsPage.searchAndClickClientCredentialsLink(clientName);
|
|
34
|
+
operateUrl = await clientCredentialsDetailsPage.getOperateUrl();
|
|
35
|
+
(0, test_1.expect)(operateUrl).toMatch(/^https?:\/\//);
|
|
36
|
+
await clientCredentialsDetailsPage.goBack();
|
|
37
|
+
await clusterDetailsPage.clickAPITab();
|
|
38
|
+
});
|
|
39
|
+
await _8_9_1.test.step('POST search endpoint without auth should be rejected', async () => {
|
|
40
|
+
const sanitizedOperateUrl = operateUrl.replace(/\/$/, '');
|
|
41
|
+
const response = await request.post(`${sanitizedOperateUrl}/v2/process-definitions/search`, {
|
|
42
|
+
data: { filter: {}, size: 10 },
|
|
43
|
+
});
|
|
44
|
+
(0, test_1.expect)(response.status()).toBe(401);
|
|
45
|
+
const body = await response.text();
|
|
46
|
+
(0, test_1.expect)(body.length).toBe(0);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|