@camunda/e2e-test-suite 0.0.1442 → 0.0.1444

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.
Files changed (123) hide show
  1. package/.github/c8_versions.json +1 -0
  2. package/README.md +2 -0
  3. package/dist/fixtures/SM-8.11.d.ts +77 -0
  4. package/dist/fixtures/SM-8.11.js +176 -0
  5. package/dist/pages/8.7/ModelerCreatePage.js +21 -0
  6. package/dist/pages/SM-8.11/Authorization.d.ts +39 -0
  7. package/dist/pages/SM-8.11/Authorization.js +349 -0
  8. package/dist/pages/SM-8.11/ClusterDetailsPage.d.ts +8 -0
  9. package/dist/pages/SM-8.11/ClusterDetailsPage.js +65 -0
  10. package/dist/pages/SM-8.11/ClusterPage.d.ts +11 -0
  11. package/dist/pages/SM-8.11/ClusterPage.js +37 -0
  12. package/dist/pages/SM-8.11/ConnectorMarketplacePage.d.ts +27 -0
  13. package/dist/pages/SM-8.11/ConnectorMarketplacePage.js +187 -0
  14. package/dist/pages/SM-8.11/ConnectorSettingsPage.d.ts +41 -0
  15. package/dist/pages/SM-8.11/ConnectorSettingsPage.js +153 -0
  16. package/dist/pages/SM-8.11/ConnectorTemplatePage.d.ts +11 -0
  17. package/dist/pages/SM-8.11/ConnectorTemplatePage.js +34 -0
  18. package/dist/pages/SM-8.11/FormJsPage.d.ts +33 -0
  19. package/dist/pages/SM-8.11/FormJsPage.js +109 -0
  20. package/dist/pages/SM-8.11/HomePage.d.ts +20 -0
  21. package/dist/pages/SM-8.11/HomePage.js +49 -0
  22. package/dist/pages/SM-8.11/IdentityTenantPage.d.ts +53 -0
  23. package/dist/pages/SM-8.11/IdentityTenantPage.js +264 -0
  24. package/dist/pages/SM-8.11/IdentityUsersPage.d.ts +92 -0
  25. package/dist/pages/SM-8.11/IdentityUsersPage.js +485 -0
  26. package/dist/pages/SM-8.11/KeycloakAdminPage.d.ts +17 -0
  27. package/dist/pages/SM-8.11/KeycloakAdminPage.js +78 -0
  28. package/dist/pages/SM-8.11/KeycloakLoginPage.d.ts +12 -0
  29. package/dist/pages/SM-8.11/KeycloakLoginPage.js +32 -0
  30. package/dist/pages/SM-8.11/KeycloakUtils.d.ts +17 -0
  31. package/dist/pages/SM-8.11/KeycloakUtils.js +94 -0
  32. package/dist/pages/SM-8.11/LoginPage.d.ts +21 -0
  33. package/dist/pages/SM-8.11/LoginPage.js +112 -0
  34. package/dist/pages/SM-8.11/ManagementIdentityPage.d.ts +44 -0
  35. package/dist/pages/SM-8.11/ManagementIdentityPage.js +176 -0
  36. package/dist/pages/SM-8.11/ModelerCreatePage.d.ts +238 -0
  37. package/dist/pages/SM-8.11/ModelerCreatePage.js +1950 -0
  38. package/dist/pages/SM-8.11/ModelerHomePage.d.ts +97 -0
  39. package/dist/pages/SM-8.11/ModelerHomePage.js +956 -0
  40. package/dist/pages/SM-8.11/NavigationPage.d.ts +58 -0
  41. package/dist/pages/SM-8.11/NavigationPage.js +389 -0
  42. package/dist/pages/SM-8.11/OCIdentityAuthorizationsPage.d.ts +10 -0
  43. package/dist/pages/SM-8.11/OCIdentityAuthorizationsPage.js +22 -0
  44. package/dist/pages/SM-8.11/OCIdentityClusterVariablesPage.d.ts +22 -0
  45. package/dist/pages/SM-8.11/OCIdentityClusterVariablesPage.js +120 -0
  46. package/dist/pages/SM-8.11/OCIdentityGroupsPage.d.ts +39 -0
  47. package/dist/pages/SM-8.11/OCIdentityGroupsPage.js +154 -0
  48. package/dist/pages/SM-8.11/OCIdentityHomePage.d.ts +23 -0
  49. package/dist/pages/SM-8.11/OCIdentityHomePage.js +115 -0
  50. package/dist/pages/SM-8.11/OCIdentityMappingRulesPage.d.ts +23 -0
  51. package/dist/pages/SM-8.11/OCIdentityMappingRulesPage.js +116 -0
  52. package/dist/pages/SM-8.11/OCIdentityRolesPage.d.ts +61 -0
  53. package/dist/pages/SM-8.11/OCIdentityRolesPage.js +433 -0
  54. package/dist/pages/SM-8.11/OCTenantPage.d.ts +73 -0
  55. package/dist/pages/SM-8.11/OCTenantPage.js +399 -0
  56. package/dist/pages/SM-8.11/OperateHomePage.d.ts +26 -0
  57. package/dist/pages/SM-8.11/OperateHomePage.js +139 -0
  58. package/dist/pages/SM-8.11/OperateProcessInstancePage.d.ts +30 -0
  59. package/dist/pages/SM-8.11/OperateProcessInstancePage.js +276 -0
  60. package/dist/pages/SM-8.11/OperateProcessesPage.d.ts +38 -0
  61. package/dist/pages/SM-8.11/OperateProcessesPage.js +383 -0
  62. package/dist/pages/SM-8.11/OptimizeCollectionsPage.d.ts +17 -0
  63. package/dist/pages/SM-8.11/OptimizeCollectionsPage.js +62 -0
  64. package/dist/pages/SM-8.11/OptimizeDashboardPage.d.ts +14 -0
  65. package/dist/pages/SM-8.11/OptimizeDashboardPage.js +63 -0
  66. package/dist/pages/SM-8.11/OptimizeHomePage.d.ts +19 -0
  67. package/dist/pages/SM-8.11/OptimizeHomePage.js +76 -0
  68. package/dist/pages/SM-8.11/OptimizeReportPage.d.ts +50 -0
  69. package/dist/pages/SM-8.11/OptimizeReportPage.js +209 -0
  70. package/dist/pages/SM-8.11/PlayPage.d.ts +47 -0
  71. package/dist/pages/SM-8.11/PlayPage.js +389 -0
  72. package/dist/pages/SM-8.11/ProcessApplicationPage.d.ts +35 -0
  73. package/dist/pages/SM-8.11/ProcessApplicationPage.js +340 -0
  74. package/dist/pages/SM-8.11/SettingsPage.d.ts +12 -0
  75. package/dist/pages/SM-8.11/SettingsPage.js +34 -0
  76. package/dist/pages/SM-8.11/TaskDetailsPage.d.ts +70 -0
  77. package/dist/pages/SM-8.11/TaskDetailsPage.js +273 -0
  78. package/dist/pages/SM-8.11/TaskPanelPage.d.ts +29 -0
  79. package/dist/pages/SM-8.11/TaskPanelPage.js +320 -0
  80. package/dist/pages/SM-8.11/TaskProcessesPage.d.ts +15 -0
  81. package/dist/pages/SM-8.11/TaskProcessesPage.js +77 -0
  82. package/dist/pages/SM-8.11/UtilitiesPage.d.ts +38 -0
  83. package/dist/pages/SM-8.11/UtilitiesPage.js +573 -0
  84. package/dist/pages/SM-8.11/optimizeReportUtils.d.ts +6 -0
  85. package/dist/pages/SM-8.11/optimizeReportUtils.js +77 -0
  86. package/dist/tests/SM-8.11/cluster-management-user-flows.spec.d.ts +1 -0
  87. package/dist/tests/SM-8.11/cluster-management-user-flows.spec.js +48 -0
  88. package/dist/tests/SM-8.11/cluster-variables.spec.d.ts +1 -0
  89. package/dist/tests/SM-8.11/cluster-variables.spec.js +226 -0
  90. package/dist/tests/SM-8.11/connectors-user-flows.spec.d.ts +1 -0
  91. package/dist/tests/SM-8.11/connectors-user-flows.spec.js +307 -0
  92. package/dist/tests/SM-8.11/document-handling-user-flows.spec.d.ts +1 -0
  93. package/dist/tests/SM-8.11/document-handling-user-flows.spec.js +174 -0
  94. package/dist/tests/SM-8.11/hto-user-flows.spec.d.ts +1 -0
  95. package/dist/tests/SM-8.11/hto-user-flows.spec.js +410 -0
  96. package/dist/tests/SM-8.11/hub-web-modeler-smoke.spec.d.ts +1 -0
  97. package/dist/tests/SM-8.11/hub-web-modeler-smoke.spec.js +24 -0
  98. package/dist/tests/SM-8.11/identity-user-flows.spec.d.ts +1 -0
  99. package/dist/tests/SM-8.11/identity-user-flows.spec.js +220 -0
  100. package/dist/tests/SM-8.11/license-key-user-flows.spec.d.ts +1 -0
  101. package/dist/tests/SM-8.11/license-key-user-flows.spec.js +461 -0
  102. package/dist/tests/SM-8.11/login.spec.d.ts +1 -0
  103. package/dist/tests/SM-8.11/login.spec.js +24 -0
  104. package/dist/tests/SM-8.11/migration-path-user-flows.spec.d.ts +1 -0
  105. package/dist/tests/SM-8.11/migration-path-user-flows.spec.js +263 -0
  106. package/dist/tests/SM-8.11/mt-enabled-user-flows.spec.d.ts +1 -0
  107. package/dist/tests/SM-8.11/mt-enabled-user-flows.spec.js +607 -0
  108. package/dist/tests/SM-8.11/optimize-user-flows.spec.d.ts +1 -0
  109. package/dist/tests/SM-8.11/optimize-user-flows.spec.js +505 -0
  110. package/dist/tests/SM-8.11/play.spec.d.ts +1 -0
  111. package/dist/tests/SM-8.11/play.spec.js +144 -0
  112. package/dist/tests/SM-8.11/rba-enabled-user-flows.spec.d.ts +1 -0
  113. package/dist/tests/SM-8.11/rba-enabled-user-flows.spec.js +712 -0
  114. package/dist/tests/SM-8.11/smoke-tests.spec.d.ts +1 -0
  115. package/dist/tests/SM-8.11/smoke-tests.spec.js +167 -0
  116. package/dist/tests/SM-8.11/test-setup.spec.d.ts +1 -0
  117. package/dist/tests/SM-8.11/test-setup.spec.js +24 -0
  118. package/dist/tests/SM-8.11/topology-orchestration-smoke.spec.d.ts +1 -0
  119. package/dist/tests/SM-8.11/topology-orchestration-smoke.spec.js +58 -0
  120. package/dist/tests/SM-8.11/web-modeler-user-flows.spec.d.ts +1 -0
  121. package/dist/tests/SM-8.11/web-modeler-user-flows.spec.js +223 -0
  122. package/package.json +1 -1
  123. package/playwright.config.ts +21 -0
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectorMarketplacePage = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ const BrowseAllConnectorMarketplacePage_1 = require("../BrowseAllConnectorMarketplacePage");
6
+ const sleep_1 = require("../../utils/sleep");
7
+ class ConnectorMarketplacePage {
8
+ page;
9
+ browseAllConnectorMarketplacePage;
10
+ connectorName;
11
+ legacyMarketplaceDialog;
12
+ searchForConnectorTextbox;
13
+ downloadToProjectButton;
14
+ addToProjectButton;
15
+ replaceResourceButton;
16
+ saveAsCopyButton;
17
+ cancelButton;
18
+ marketplaceErrorMessage;
19
+ noResultsMessage;
20
+ constructor(page) {
21
+ this.page = page;
22
+ this.browseAllConnectorMarketplacePage =
23
+ new BrowseAllConnectorMarketplacePage_1.BrowseAllConnectorMarketplacePage(page);
24
+ this.searchForConnectorTextbox =
25
+ this.browseAllConnectorMarketplacePage.searchForConnectorTextbox
26
+ .or(page.getByPlaceholder('Search for a connector'))
27
+ .first();
28
+ this.legacyMarketplaceDialog = page
29
+ .getByRole('dialog', { name: 'Browse Marketplace connectors' })
30
+ .or(page.getByRole('dialog', { name: 'Discover Connectors Dialog' }))
31
+ .first();
32
+ this.downloadToProjectButton = page
33
+ .getByRole('button', { name: 'Download to project' })
34
+ .first();
35
+ this.cancelButton = page.getByRole('button', { name: 'Cancel' });
36
+ this.addToProjectButton = page.getByRole('button', {
37
+ name: 'Add to project',
38
+ });
39
+ this.replaceResourceButton = page.getByRole('button', {
40
+ name: 'Replace resource',
41
+ });
42
+ this.saveAsCopyButton = page.getByRole('button', { name: 'Save as copy' });
43
+ this.marketplaceErrorMessage = page.getByText('an error occurred, please try again later');
44
+ this.noResultsMessage = page.getByText('find a match for your search phrase');
45
+ }
46
+ async clickSearchForConnectorTextbox() {
47
+ await this.searchForConnectorTextbox.click({ timeout: 60000 });
48
+ await (0, sleep_1.sleep)(2000);
49
+ }
50
+ async fillSearchForConnectorTextbox(connectorName) {
51
+ this.connectorName = connectorName;
52
+ await this.searchForConnectorTextbox.fill(connectorName, { timeout: 60000 });
53
+ await (0, sleep_1.sleep)(2000);
54
+ }
55
+ async clickDownloadToProjectButton() {
56
+ await this.getLegacyDownloadButton().click({ timeout: 60000 });
57
+ }
58
+ async clickCancelButton() {
59
+ await this.cancelButton.click({ timeout: 30000 });
60
+ }
61
+ async clickReplaceResourceButton() {
62
+ await this.replaceResourceButton.click({ timeout: 30000 });
63
+ }
64
+ async waitForConnectorSearchResults() {
65
+ if (await this.browseAllConnectorMarketplacePage.isOpen()) {
66
+ await this.browseAllConnectorMarketplacePage.waitForConnectorSearchResult(this.connectorName);
67
+ return;
68
+ }
69
+ const MAX_RETRIES = 4;
70
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
71
+ const downloadButton = this.getLegacyDownloadButton();
72
+ await (0, test_1.expect)(downloadButton
73
+ .or(this.marketplaceErrorMessage)
74
+ .or(this.noResultsMessage)).toBeVisible({ timeout: 60000 });
75
+ if (await downloadButton.isVisible()) {
76
+ return;
77
+ }
78
+ console.log(`Marketplace search attempt ${attempt} of ${MAX_RETRIES} returned an error or no results. Retrying search...`);
79
+ if (attempt < MAX_RETRIES) {
80
+ // The marketplace search API returns transient 5xx. Back off for
81
+ // growing intervals before re-issuing the query so a short outage
82
+ // self-heals instead of burning all attempts inside a few seconds.
83
+ await (0, sleep_1.sleep)(attempt * 5000);
84
+ const searchText = await this.searchForConnectorTextbox.inputValue();
85
+ await this.searchForConnectorTextbox.clear();
86
+ await (0, sleep_1.sleep)(2000);
87
+ await this.searchForConnectorTextbox.fill(searchText);
88
+ await (0, sleep_1.sleep)(2000);
89
+ }
90
+ }
91
+ throw new Error('Marketplace connector search failed after retries due to persistent error or no matching results');
92
+ }
93
+ async downloadConnectorToProject() {
94
+ if (await this.browseAllConnectorMarketplacePage.isOpen()) {
95
+ await this.browseAllConnectorMarketplacePage.importConnectorToProject(this.connectorName);
96
+ return;
97
+ }
98
+ await this.clickDownloadToProjectButton();
99
+ if (await this.confirmImport()) {
100
+ return;
101
+ }
102
+ // The modal is up but rendered none of the known import actions. Dismiss it
103
+ // so it does not block the next click on the diagram, then fail here:
104
+ // continuing would leave the diagram's connector template unresolved
105
+ // ("Template: Not found") and only surface 60s later as a missing
106
+ // properties-panel group, pointing at the wrong step.
107
+ if (await this.cancelButton.isVisible().catch(() => false)) {
108
+ await this.cancelButton.click({ timeout: 20000 });
109
+ throw new Error('Connector import modal offered no import action ("Add to project", "Replace resource" or "Save as copy"); the import was abandoned.');
110
+ }
111
+ // Hub imported without asking for confirmation, so the write is in flight
112
+ // here too.
113
+ await this.waitForImportToSettle();
114
+ }
115
+ // Hub's import modal labels its primary button after the project state:
116
+ // "Add to project" when the template is new to the project, "Replace
117
+ // resource" when the same template is already there, "Save as copy" on a
118
+ // conflicting version. Probe them in order and click the one actually
119
+ // rendered; clicking "Cancel" instead abandons the import and leaves the
120
+ // diagram's connector template unresolved ("Template: Not found"), which
121
+ // only surfaces much later as a missing properties-panel group.
122
+ async confirmImport() {
123
+ const importButtons = [
124
+ this.addToProjectButton,
125
+ this.replaceResourceButton,
126
+ this.saveAsCopyButton,
127
+ ];
128
+ // Carbon animates the modal in, so a click issued mid-transition is
129
+ // rejected ("element is not stable") and by the next Playwright retry the
130
+ // button can already be gone; keep probing the labels until one click
131
+ // actually lands instead of burning the whole budget on a single button.
132
+ const deadline = Date.now() + 45000;
133
+ do {
134
+ for (const button of importButtons) {
135
+ if (!(await button.isVisible().catch(() => false))) {
136
+ continue;
137
+ }
138
+ // Register the waiter before the click: the write can be acknowledged
139
+ // before the modal finishes unmounting.
140
+ const templateWritten = this.page
141
+ .waitForResponse((response) => response.request().method() === 'POST' &&
142
+ response.url().includes('/internal/files'), { timeout: 30000 })
143
+ .catch(() => null);
144
+ const clicked = await button
145
+ .click({ timeout: 5000 })
146
+ .then(() => true)
147
+ .catch(() => false);
148
+ if (!clicked) {
149
+ continue;
150
+ }
151
+ await (0, test_1.expect)(button).toBeHidden({ timeout: 60000 });
152
+ const written = await templateWritten;
153
+ // A rejected write leaves the project without the template just like
154
+ // an aborted one, so surface the status here instead of letting it
155
+ // resurface 60s later as a missing "Authentication" group in
156
+ // ModelerCreatePage.
157
+ if (written && !written.ok()) {
158
+ throw new Error(`Connector template import failed: writing it into the project returned HTTP ${written.status()}.`);
159
+ }
160
+ await this.waitForImportToSettle();
161
+ return true;
162
+ }
163
+ await (0, sleep_1.sleep)(1000);
164
+ } while (Date.now() < deadline);
165
+ return false;
166
+ }
167
+ // Hub unmounts the ImportModal as soon as the click is handled, but writes the
168
+ // template into the project with a POST that is still in flight at that point.
169
+ // Returning right after the button hides let the caller's `page.reload()`
170
+ // abort that write ~20ms later, leaving the project's connector-template list
171
+ // empty and every templated task on the diagram at "Template: Not found" --
172
+ // the properties panel then never renders the "Authentication" group.
173
+ async waitForImportToSettle() {
174
+ await this.page.waitForLoadState('networkidle').catch(() => { });
175
+ }
176
+ getLegacyDownloadButton() {
177
+ if (!this.connectorName) {
178
+ return this.downloadToProjectButton;
179
+ }
180
+ return this.legacyMarketplaceDialog
181
+ .getByText(this.connectorName, { exact: true })
182
+ .first()
183
+ .locator('xpath=ancestor::*[.//button[normalize-space()="Download to project"]][1]')
184
+ .getByRole('button', { name: 'Download to project' });
185
+ }
186
+ }
187
+ exports.ConnectorMarketplacePage = ConnectorMarketplacePage;
@@ -0,0 +1,41 @@
1
+ import { Page, Locator } from '@playwright/test';
2
+ declare class ConnectorSettingsPage {
3
+ private page;
4
+ readonly urlInput: Locator;
5
+ readonly resultExpressionInput: Locator;
6
+ readonly authenticationTypeDropdown: Locator;
7
+ readonly usernameInput: Locator;
8
+ readonly passwordInput: Locator;
9
+ readonly methodTypeDropdown: Locator;
10
+ readonly resultVariableInput: Locator;
11
+ readonly bearerTokenInput: Locator;
12
+ readonly authenticationTab: Locator;
13
+ readonly outputMappingTab: Locator;
14
+ readonly httpEndpointTab: Locator;
15
+ readonly correlationTab: Locator;
16
+ readonly inputTab: Locator;
17
+ readonly webhookConfigurationTab: Locator;
18
+ constructor(page: Page);
19
+ clickUrlInput(): Promise<void>;
20
+ fillUrlInput(url: string): Promise<void>;
21
+ clickResultExpressionInput(): Promise<void>;
22
+ fillResultExpressionInput(resultExpression: string): Promise<void>;
23
+ selectAuthenticationType(authentication: string): Promise<void>;
24
+ clickUsernameInput(): Promise<void>;
25
+ fillUsernameInput(username: string): Promise<void>;
26
+ clickPasswordInput(): Promise<void>;
27
+ fillPasswordInput(password: string): Promise<void>;
28
+ selectMethodType(method: string): Promise<void>;
29
+ clickResultVariableInput(): Promise<void>;
30
+ fillResultVariableInput(variable: string): Promise<void>;
31
+ clickBearerTokenInput(): Promise<void>;
32
+ fillBearerTokenInput(token: string): Promise<void>;
33
+ private clickTabWithRetry;
34
+ clickAuthenticationTab(): Promise<void>;
35
+ clickOutputMappingTab(): Promise<void>;
36
+ clickHTTPEndpointTab(): Promise<void>;
37
+ clickCorrelationTab(): Promise<void>;
38
+ clickInputTab(): Promise<void>;
39
+ clickWebhookConfigurationTab(): Promise<void>;
40
+ }
41
+ export { ConnectorSettingsPage };
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectorSettingsPage = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ class ConnectorSettingsPage {
6
+ page;
7
+ urlInput;
8
+ resultExpressionInput;
9
+ authenticationTypeDropdown;
10
+ usernameInput;
11
+ passwordInput;
12
+ methodTypeDropdown;
13
+ resultVariableInput;
14
+ bearerTokenInput;
15
+ authenticationTab;
16
+ outputMappingTab;
17
+ httpEndpointTab;
18
+ correlationTab;
19
+ inputTab;
20
+ webhookConfigurationTab;
21
+ constructor(page) {
22
+ this.page = page;
23
+ this.urlInput = page.getByLabel('URL');
24
+ this.resultExpressionInput = page.getByLabel('Result expression');
25
+ this.authenticationTypeDropdown = page.getByLabel('Type');
26
+ this.usernameInput = page.getByLabel('Username');
27
+ this.passwordInput = page.getByLabel('Password', { exact: true });
28
+ this.methodTypeDropdown = page.getByLabel('Method');
29
+ this.resultVariableInput = page.getByLabel('Result variable');
30
+ this.bearerTokenInput = page.getByLabel('Bearer token');
31
+ this.authenticationTab = page
32
+ .locator('div')
33
+ .filter({ hasText: /^Authentication$/ })
34
+ .first();
35
+ this.outputMappingTab = page
36
+ .locator('div')
37
+ .filter({ hasText: /^Output mapping$/ })
38
+ .first();
39
+ this.httpEndpointTab = page
40
+ .locator('div')
41
+ .filter({ hasText: /^HTTP endpoint$/ })
42
+ .first();
43
+ this.correlationTab = page
44
+ .locator('div')
45
+ .filter({ hasText: /^Correlation$/ })
46
+ .first();
47
+ this.inputTab = page
48
+ .locator('div')
49
+ .filter({ hasText: /^Input$/ })
50
+ .first();
51
+ this.webhookConfigurationTab = page
52
+ .locator('div')
53
+ .filter({ hasText: /^Webhook configuration$/ })
54
+ .first();
55
+ }
56
+ async clickUrlInput() {
57
+ try {
58
+ await this.urlInput.click({ timeout: 60000 });
59
+ }
60
+ catch {
61
+ await this.httpEndpointTab.click();
62
+ await this.urlInput.click({ timeout: 60000 });
63
+ }
64
+ }
65
+ async fillUrlInput(url) {
66
+ await this.urlInput.fill(url);
67
+ await (0, test_1.expect)(this.page.getByText('URL must not be empty.')).not.toBeVisible({ timeout: 30000 });
68
+ }
69
+ async clickResultExpressionInput() {
70
+ try {
71
+ await this.resultExpressionInput.click();
72
+ }
73
+ catch {
74
+ await this.clickOutputMappingTab();
75
+ await this.resultExpressionInput.click();
76
+ }
77
+ }
78
+ async fillResultExpressionInput(resultExpression) {
79
+ await this.resultExpressionInput.fill(resultExpression);
80
+ }
81
+ async selectAuthenticationType(authentication) {
82
+ await this.authenticationTypeDropdown.selectOption(authentication);
83
+ }
84
+ async clickUsernameInput() {
85
+ await this.usernameInput.click({ timeout: 30000 });
86
+ }
87
+ async fillUsernameInput(username) {
88
+ await this.usernameInput.fill(username, { timeout: 30000 });
89
+ await (0, test_1.expect)(this.page.getByText('Username must not be empty.')).not.toBeVisible({ timeout: 30000 });
90
+ }
91
+ async clickPasswordInput() {
92
+ await this.passwordInput.click();
93
+ }
94
+ async fillPasswordInput(password) {
95
+ await this.passwordInput.fill(password);
96
+ await (0, test_1.expect)(this.page.getByText('Password must not be empty.')).not.toBeVisible({ timeout: 30000 });
97
+ }
98
+ async selectMethodType(method) {
99
+ await this.methodTypeDropdown.selectOption(method, { timeout: 60000 });
100
+ }
101
+ async clickResultVariableInput() {
102
+ await this.resultVariableInput.click();
103
+ }
104
+ async fillResultVariableInput(variable) {
105
+ await this.resultVariableInput.fill(variable);
106
+ }
107
+ async clickBearerTokenInput() {
108
+ await this.bearerTokenInput.click({ timeout: 30000 });
109
+ }
110
+ async fillBearerTokenInput(token) {
111
+ await this.bearerTokenInput.fill(token);
112
+ await (0, test_1.expect)(this.page.getByText('Bearer token must not be empty.')).not.toBeVisible({ timeout: 30000 });
113
+ }
114
+ // Connector settings tabs can take several seconds to render on slower clusters
115
+ // after the element type is changed. Each clickXxxTab method retries with a
116
+ // reload-free wait so a single slow render doesn't cause a hard timeout failure.
117
+ async clickTabWithRetry(tab, tabName, maxAttempts = 3) {
118
+ let lastError;
119
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
120
+ try {
121
+ await (0, test_1.expect)(tab).toBeVisible({ timeout: 30000 });
122
+ await tab.click({ timeout: 30000 });
123
+ return;
124
+ }
125
+ catch (err) {
126
+ lastError = err;
127
+ console.warn(`clickTabWithRetry: "${tabName}" attempt ${attempt + 1}/${maxAttempts} failed: ${err instanceof Error ? err.message : err}`);
128
+ }
129
+ }
130
+ throw lastError instanceof Error
131
+ ? lastError
132
+ : new Error(`Tab "${tabName}" not clickable after ${maxAttempts} attempts`);
133
+ }
134
+ async clickAuthenticationTab() {
135
+ await this.clickTabWithRetry(this.authenticationTab, 'Authentication');
136
+ }
137
+ async clickOutputMappingTab() {
138
+ await this.clickTabWithRetry(this.outputMappingTab, 'Output mapping');
139
+ }
140
+ async clickHTTPEndpointTab() {
141
+ await this.clickTabWithRetry(this.httpEndpointTab, 'HTTP endpoint');
142
+ }
143
+ async clickCorrelationTab() {
144
+ await this.clickTabWithRetry(this.correlationTab, 'Correlation');
145
+ }
146
+ async clickInputTab() {
147
+ await this.clickTabWithRetry(this.inputTab, 'Input');
148
+ }
149
+ async clickWebhookConfigurationTab() {
150
+ await this.clickTabWithRetry(this.webhookConfigurationTab, 'Webhook configuration');
151
+ }
152
+ }
153
+ exports.ConnectorSettingsPage = ConnectorSettingsPage;
@@ -0,0 +1,11 @@
1
+ import { Page, Locator } from '@playwright/test';
2
+ declare class ConnectorTemplatePage {
3
+ private page;
4
+ readonly publishToOrgButton: Locator;
5
+ readonly publishButton: Locator;
6
+ constructor(page: Page);
7
+ clickPublishToOrgButton(): Promise<void>;
8
+ clickPublishButton(): Promise<void>;
9
+ publishConnector(): Promise<void>;
10
+ }
11
+ export { ConnectorTemplatePage };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectorTemplatePage = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ class ConnectorTemplatePage {
6
+ page;
7
+ publishToOrgButton;
8
+ publishButton;
9
+ constructor(page) {
10
+ this.page = page;
11
+ this.publishButton = page.getByRole('button', {
12
+ name: 'Publish',
13
+ exact: true,
14
+ });
15
+ this.publishToOrgButton = page.locator('[data-test="publish-to-org"]');
16
+ }
17
+ async clickPublishToOrgButton() {
18
+ await this.publishToOrgButton.click({ timeout: 90000 });
19
+ }
20
+ async clickPublishButton() {
21
+ await this.publishButton.click({ timeout: 90000 });
22
+ }
23
+ async publishConnector() {
24
+ try {
25
+ await (0, test_1.expect)(this.publishToOrgButton).toBeVisible({ timeout: 15000 });
26
+ }
27
+ catch (error) {
28
+ return;
29
+ }
30
+ await this.clickPublishToOrgButton();
31
+ await this.clickPublishButton();
32
+ }
33
+ }
34
+ exports.ConnectorTemplatePage = ConnectorTemplatePage;
@@ -0,0 +1,33 @@
1
+ import { Page, Locator } from '@playwright/test';
2
+ declare class FormJsPage {
3
+ private page;
4
+ readonly aiFormGeneratorButton: Locator;
5
+ readonly formRequestInput: Locator;
6
+ readonly generateFormButton: Locator;
7
+ readonly formEditor: Locator;
8
+ readonly filePicker: Locator;
9
+ readonly generalPanel: Locator;
10
+ readonly keyInput: Locator;
11
+ readonly uploadMultipleFilesToggle: Locator;
12
+ readonly documentReferenceInput: Locator;
13
+ readonly documentPreview: Locator;
14
+ readonly deployDialog: Locator;
15
+ readonly deployFormButton: Locator;
16
+ readonly deployModalSubmitButton: Locator;
17
+ readonly deploySuccessNotification: Locator;
18
+ constructor(page: Page);
19
+ clickAIFormGeneratorButton(): Promise<void>;
20
+ clickFormRequestInput(): Promise<void>;
21
+ fillFormRequestInput(formRequest: string): Promise<void>;
22
+ clickGenerateFormButton(): Promise<void>;
23
+ dragAndDrop(source: Locator, target: Locator): Promise<void>;
24
+ clickGeneralPropertiesPanel(): Promise<void>;
25
+ fillKeyInput(key: string): Promise<void>;
26
+ enableUploadMultipleFiles(): Promise<void>;
27
+ filldocumentReferenceInput(key: string): Promise<void>;
28
+ clickDeployFormButton(): Promise<void>;
29
+ clickDeployModalSubmitButton(): Promise<void>;
30
+ selectOnlyThisResource(): Promise<void>;
31
+ deployForm(): Promise<void>;
32
+ }
33
+ export { FormJsPage };
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormJsPage = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ const modelerCluster_1 = require("../../utils/modelerCluster");
6
+ const hubDeployDialog_1 = require("../../utils/hubDeployDialog");
7
+ class FormJsPage {
8
+ page;
9
+ aiFormGeneratorButton;
10
+ formRequestInput;
11
+ generateFormButton;
12
+ formEditor;
13
+ filePicker;
14
+ generalPanel;
15
+ keyInput;
16
+ uploadMultipleFilesToggle;
17
+ documentReferenceInput;
18
+ documentPreview;
19
+ deployDialog;
20
+ deployFormButton;
21
+ deployModalSubmitButton;
22
+ deploySuccessNotification;
23
+ constructor(page) {
24
+ this.page = page;
25
+ this.aiFormGeneratorButton = page.getByRole('button', {
26
+ name: 'AI Form Generator',
27
+ });
28
+ this.formRequestInput = page.getByPlaceholder('A form for an american standard loan request');
29
+ this.generateFormButton = page.getByRole('button', { name: 'Generate form' });
30
+ this.formEditor = page.getByLabel('Form Definition');
31
+ this.filePicker = page.locator('button[data-field-type="filepicker"]');
32
+ this.generalPanel = page.locator('[data-group-id="group-general"]').first();
33
+ this.keyInput = page.getByRole('textbox', { name: 'key' });
34
+ this.uploadMultipleFilesToggle = page.locator('div[data-entry-id="multiple"] .bio-properties-panel-toggle-switch__switcher');
35
+ this.documentReferenceInput = page.getByRole('textbox', {
36
+ name: 'document reference',
37
+ });
38
+ this.documentPreview = page.locator('button[data-field-type="documentPreview"]');
39
+ this.deployDialog = page.getByRole('dialog');
40
+ // The Design System shell renders none of Carbon's cds-- classes, so the
41
+ // editor's Deploy button, the dialog's submit and the success toast are all
42
+ // matched by role and text instead -- which resolves on both shells.
43
+ // .first(): once the deploy dialog is open its submit carries the same
44
+ // accessible name; the editor's button is the earlier one in the DOM.
45
+ this.deployFormButton = page
46
+ .getByRole('button', { name: 'Deploy', exact: true })
47
+ .first();
48
+ this.deployModalSubmitButton = this.deployDialog
49
+ .getByRole('button', { name: 'Deploy', exact: true })
50
+ .or(page.locator('button[data-modal-primary-focus="true"][type="submit"]'))
51
+ .first();
52
+ this.deploySuccessNotification = page.getByText('Form deployed!').first();
53
+ }
54
+ async clickAIFormGeneratorButton() {
55
+ await this.aiFormGeneratorButton.click();
56
+ }
57
+ async clickFormRequestInput() {
58
+ await this.formRequestInput.click();
59
+ }
60
+ async fillFormRequestInput(formRequest) {
61
+ await this.formRequestInput.fill(formRequest);
62
+ }
63
+ async clickGenerateFormButton() {
64
+ await this.generateFormButton.click();
65
+ }
66
+ async dragAndDrop(source, target) {
67
+ await source.waitFor();
68
+ await target.waitFor();
69
+ await source.dragTo(target);
70
+ }
71
+ async clickGeneralPropertiesPanel() {
72
+ await this.generalPanel.click({ timeout: 60000 });
73
+ }
74
+ async fillKeyInput(key) {
75
+ await this.keyInput.fill(key, { timeout: 60000 });
76
+ }
77
+ async enableUploadMultipleFiles() {
78
+ await this.uploadMultipleFilesToggle.click({ timeout: 60000 });
79
+ }
80
+ async filldocumentReferenceInput(key) {
81
+ await this.documentReferenceInput.fill(key, { timeout: 60000 });
82
+ }
83
+ async clickDeployFormButton() {
84
+ await this.deployFormButton.click({ timeout: 60000 });
85
+ }
86
+ async clickDeployModalSubmitButton() {
87
+ await this.deployModalSubmitButton.click({ timeout: 60000 });
88
+ }
89
+ // Since camunda/camunda-hub#25831 a form lives inside a process application,
90
+ // and Hub scopes Deploy to that application unless the scope is narrowed --
91
+ // deployProcessApplication, not deployFile, so the "Form deployed!" toast
92
+ // never fires. Narrowing the scope keeps this a form-deploy test instead of
93
+ // silently turning it into a process-application deploy. Since
94
+ // camunda/camunda-hub#29791 Hub preselects "Only this resource" when
95
+ // deploying from a file, so the shared helper's already-selected guard is
96
+ // what keeps this from reopening the preselected scope select and failing.
97
+ async selectOnlyThisResource() {
98
+ await (0, hubDeployDialog_1.selectOnlyThisResourceInDialog)(this.page, this.deployDialog);
99
+ }
100
+ async deployForm() {
101
+ await this.clickDeployFormButton();
102
+ await (0, test_1.expect)(this.deployDialog).toBeVisible({ timeout: 30000 });
103
+ await (0, modelerCluster_1.selectModelerCluster)(this.deployDialog);
104
+ await this.selectOnlyThisResource();
105
+ await this.clickDeployModalSubmitButton();
106
+ await (0, test_1.expect)(this.deploySuccessNotification).toBeVisible({ timeout: 30000 });
107
+ }
108
+ }
109
+ exports.FormJsPage = FormJsPage;
@@ -0,0 +1,20 @@
1
+ import { Page, Locator } from '@playwright/test';
2
+ declare class HomePage {
3
+ private page;
4
+ readonly dashboardTab: Locator;
5
+ readonly clusterTab: Locator;
6
+ readonly organizationTab: Locator;
7
+ readonly organizationViewTitle: Locator;
8
+ readonly welcomeMessage: Locator;
9
+ readonly informationDialog: Locator;
10
+ readonly camundaAppsButton: Locator;
11
+ readonly camundaComponentsButton: Locator;
12
+ constructor(page: Page);
13
+ clickClusters(): Promise<void>;
14
+ clickDashboard(): Promise<void>;
15
+ clickOrganization(): Promise<void>;
16
+ closeInformationDialog(): Promise<void>;
17
+ clickCamundaComponents(): Promise<void>;
18
+ clickCamundaApps(): Promise<void>;
19
+ }
20
+ export { HomePage };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HomePage = void 0;
4
+ class HomePage {
5
+ page;
6
+ dashboardTab;
7
+ clusterTab;
8
+ organizationTab;
9
+ organizationViewTitle;
10
+ welcomeMessage;
11
+ informationDialog;
12
+ camundaAppsButton;
13
+ camundaComponentsButton;
14
+ constructor(page) {
15
+ this.page = page;
16
+ this.dashboardTab = page.getByRole('link', { name: 'Dashboard' });
17
+ this.clusterTab = page.getByRole('link', { name: 'Clusters' });
18
+ this.organizationTab = page.getByRole('link', { name: 'Organization' });
19
+ this.organizationViewTitle = page.getByText('Organization Management');
20
+ this.welcomeMessage = page.getByText('Welcome, demo').first();
21
+ this.informationDialog = page.getByRole('button', {
22
+ name: 'Close this dialog',
23
+ });
24
+ this.camundaComponentsButton = page.getByLabel('Camunda components');
25
+ this.camundaAppsButton = page.getByLabel('Camunda apps');
26
+ }
27
+ async clickClusters() {
28
+ await this.clusterTab.click({ timeout: 90000 });
29
+ }
30
+ async clickDashboard() {
31
+ await this.dashboardTab.click({ timeout: 90000 });
32
+ }
33
+ async clickOrganization() {
34
+ await this.organizationTab.click({ timeout: 90000 });
35
+ }
36
+ async closeInformationDialog() {
37
+ const isLocalTest = process.env.LOCAL_TEST;
38
+ if (isLocalTest) {
39
+ await this.informationDialog.click();
40
+ }
41
+ }
42
+ async clickCamundaComponents() {
43
+ await this.camundaComponentsButton.click({ timeout: 90000 });
44
+ }
45
+ async clickCamundaApps() {
46
+ await this.camundaAppsButton.click({ timeout: 90000 });
47
+ }
48
+ }
49
+ exports.HomePage = HomePage;