@camunda/e2e-test-suite 0.0.1027 → 0.0.1028
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.
|
@@ -159,7 +159,10 @@ declare class ModelerCreatePage {
|
|
|
159
159
|
clickMarketPlaceButton(): Promise<void>;
|
|
160
160
|
completeDeploymentEndpointConfiguration(): Promise<void>;
|
|
161
161
|
completePlayConfiguration(): Promise<void>;
|
|
162
|
-
|
|
162
|
+
revealChangeElementTemplate(option: Locator, searchTerm: string): Promise<boolean>;
|
|
163
|
+
private isVisibleWithin;
|
|
164
|
+
private openChangeElementPopup;
|
|
165
|
+
private clickChangeElementTemplateOption;
|
|
163
166
|
clickWebhookMessageStartEventConnectorOption(): Promise<void>;
|
|
164
167
|
clickWebhookIdInput(): Promise<void>;
|
|
165
168
|
clearWebhookIdInput(): Promise<void>;
|
|
@@ -1128,76 +1128,93 @@ class ModelerCreatePage {
|
|
|
1128
1128
|
}
|
|
1129
1129
|
}
|
|
1130
1130
|
}
|
|
1131
|
-
//
|
|
1132
|
-
//
|
|
1133
|
-
//
|
|
1134
|
-
// result list
|
|
1131
|
+
// Two independent paths put a connector template into the popup's queryable
|
|
1132
|
+
// DOM slice, and neither is reliable alone: selecting the "Reusable assets"
|
|
1133
|
+
// tab renders the template entries directly, while searching flattens the
|
|
1134
|
+
// result list. Probe the option after each step and stop at the first one
|
|
1135
|
+
// that worked, then keep re-issuing the filter while the popup stays open:
|
|
1136
|
+
// the project's connector-template list is fetched asynchronously, so a
|
|
1137
|
+
// filter typed before it lands renders "0 results found" and a single typed
|
|
1138
|
+
// filter never picks the template up afterwards.
|
|
1135
1139
|
// Use pressSequentially (not fill): the popup syncs its search state from a
|
|
1136
1140
|
// keyup listener only, and fill() dispatches just an input event, so the
|
|
1137
1141
|
// filter never applies and the unfiltered BPMN tab keeps rendering.
|
|
1138
|
-
async
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
// hid) with the template still absent from .djs-popup-results, so the
|
|
1144
|
-
// tab click runs first and the search backs it up.
|
|
1145
|
-
const hasTabs = await this.changeElementTabStrip
|
|
1146
|
-
.isVisible({ timeout: 5000 })
|
|
1147
|
-
.catch(() => false);
|
|
1148
|
-
if (hasTabs) {
|
|
1142
|
+
async revealChangeElementTemplate(option, searchTerm) {
|
|
1143
|
+
if (await this.isVisibleWithin(option, 5000)) {
|
|
1144
|
+
return true;
|
|
1145
|
+
}
|
|
1146
|
+
if (await this.isVisibleWithin(this.changeElementTabStrip, 5000)) {
|
|
1149
1147
|
// A failed tab click leaves the search path intact, so do not throw.
|
|
1150
1148
|
await this.reusableAssetsTab.click({ timeout: 30000 }).catch(() => { });
|
|
1149
|
+
if (await this.isVisibleWithin(option, 15000)) {
|
|
1150
|
+
return true;
|
|
1151
|
+
}
|
|
1151
1152
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1153
|
+
if (!(await this.isVisibleWithin(this.changeElementSearchInput, 5000))) {
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1156
|
+
const deadline = Date.now() + 90000;
|
|
1157
|
+
do {
|
|
1158
|
+
await this.changeElementSearchInput.click();
|
|
1159
|
+
await this.changeElementSearchInput.fill('');
|
|
1160
|
+
await this.changeElementSearchInput.pressSequentially(searchTerm, {
|
|
1161
|
+
delay: 50,
|
|
1162
|
+
});
|
|
1163
|
+
if (await this.isVisibleWithin(option, 15000)) {
|
|
1164
|
+
return true;
|
|
1165
|
+
}
|
|
1166
|
+
} while (Date.now() < deadline);
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
async isVisibleWithin(locator, timeout) {
|
|
1170
|
+
return locator
|
|
1171
|
+
.waitFor({ state: 'visible', timeout })
|
|
1172
|
+
.then(() => true)
|
|
1154
1173
|
.catch(() => false);
|
|
1155
|
-
|
|
1174
|
+
}
|
|
1175
|
+
// The specs reach the Marketplace through this popup's own empty-state link,
|
|
1176
|
+
// and the import modal closes the popup behind it, so the popup is routinely
|
|
1177
|
+
// gone by the time a template is clicked. Reopen it against the element being
|
|
1178
|
+
// replaced first: filtering a closed popup finds no search input and the
|
|
1179
|
+
// option assertion then times out against a popup that was never on screen.
|
|
1180
|
+
async openChangeElementPopup(element) {
|
|
1181
|
+
if (await this.isVisibleWithin(this.changeElementSearchInput, 5000)) {
|
|
1156
1182
|
return;
|
|
1157
1183
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
await
|
|
1161
|
-
|
|
1162
|
-
});
|
|
1163
|
-
// The popup hides its tab strip while searching. Wait on that as a
|
|
1164
|
-
// readiness signal, but do not assert it: with the tab already selected
|
|
1165
|
-
// the template is reachable whether or not the search registered.
|
|
1166
|
-
await (0, test_1.expect)(this.changeElementTabStrip)
|
|
1167
|
-
.toBeHidden({ timeout: 30000 })
|
|
1168
|
-
.catch(() => { });
|
|
1184
|
+
// The context pad only renders for a selected element, so "Change element"
|
|
1185
|
+
// would otherwise never appear.
|
|
1186
|
+
await (0, test_1.expect)(element).toBeVisible({ timeout: 60000 });
|
|
1187
|
+
await element.click({ force: true, timeout: 30000 });
|
|
1188
|
+
await this.changeTypeButton.click({ force: true, timeout: 30000 });
|
|
1169
1189
|
}
|
|
1170
|
-
async
|
|
1190
|
+
async clickChangeElementTemplateOption(option, element, searchTerm) {
|
|
1171
1191
|
const maxRetries = 3;
|
|
1192
|
+
let lastError;
|
|
1172
1193
|
for (let retries = 0; retries < maxRetries; retries++) {
|
|
1173
1194
|
try {
|
|
1174
|
-
if (retries
|
|
1175
|
-
await this.filterChangeElementPopup('Webhook Message Start Event Connector');
|
|
1176
|
-
await this.webhookMessageStartEventConnectorOption.click({
|
|
1177
|
-
timeout: 30000,
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
|
-
else {
|
|
1195
|
+
if (retries > 0) {
|
|
1181
1196
|
await this.page.reload();
|
|
1182
|
-
//
|
|
1183
|
-
//
|
|
1184
|
-
|
|
1185
|
-
await (0, test_1.expect)(this.startEventElement).toBeVisible({ timeout: 60000 });
|
|
1186
|
-
await this.startEventElement.click({ force: true, timeout: 30000 });
|
|
1187
|
-
await this.changeTypeButton.click({ force: true, timeout: 30000 });
|
|
1188
|
-
await this.filterChangeElementPopup('Webhook Message Start Event Connector');
|
|
1189
|
-
await this.webhookMessageStartEventConnectorOption.click({
|
|
1190
|
-
timeout: 90000,
|
|
1191
|
-
});
|
|
1197
|
+
// domcontentloaded is more reliable than networkidle for Modeler,
|
|
1198
|
+
// which maintains persistent background connections (SSE/WebSocket).
|
|
1199
|
+
await this.page.waitForLoadState('domcontentloaded');
|
|
1192
1200
|
}
|
|
1201
|
+
await this.openChangeElementPopup(element);
|
|
1202
|
+
if (!(await this.revealChangeElementTemplate(option, searchTerm))) {
|
|
1203
|
+
throw new Error('The connector template never appeared in the change-element popup.');
|
|
1204
|
+
}
|
|
1205
|
+
await option.click({ timeout: 30000 });
|
|
1193
1206
|
return;
|
|
1194
1207
|
}
|
|
1195
1208
|
catch (error) {
|
|
1209
|
+
lastError = error;
|
|
1196
1210
|
console.error(`Click attempt ${retries + 1} failed: ${error}`);
|
|
1197
|
-
await
|
|
1211
|
+
await (0, sleep_1.sleep)(10000);
|
|
1198
1212
|
}
|
|
1199
1213
|
}
|
|
1200
|
-
throw new Error(`Failed to click the
|
|
1214
|
+
throw new Error(`Failed to click the connector template after ${maxRetries} attempts: ${lastError}`);
|
|
1215
|
+
}
|
|
1216
|
+
async clickWebhookMessageStartEventConnectorOption() {
|
|
1217
|
+
await this.clickChangeElementTemplateOption(this.webhookMessageStartEventConnectorOption, this.startEventElement, 'Webhook');
|
|
1201
1218
|
}
|
|
1202
1219
|
async clickWebhookIdInput() {
|
|
1203
1220
|
await this.webhookIdInput.click();
|
|
@@ -1354,33 +1371,7 @@ class ModelerCreatePage {
|
|
|
1354
1371
|
await this.appendViaPopup('append-none-intermediate-throwing', ['append-events', 'append-intermediate-throw-events'], 'Intermediate throw event');
|
|
1355
1372
|
}
|
|
1356
1373
|
async clickIntermediateWebhookConnectorOption() {
|
|
1357
|
-
|
|
1358
|
-
for (let i = 0; i < max; i++) {
|
|
1359
|
-
try {
|
|
1360
|
-
// Filter the popup to surface the webhook connector: it sits in the
|
|
1361
|
-
// "Reusable assets" tab, which the popup only flattens into the result
|
|
1362
|
-
// list while a search is active.
|
|
1363
|
-
await this.filterChangeElementPopup('Webhook');
|
|
1364
|
-
await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
|
|
1365
|
-
timeout: 30000,
|
|
1366
|
-
});
|
|
1367
|
-
await this.intermediateWebhookConnectorOption.click({ timeout: 30000 });
|
|
1368
|
-
return;
|
|
1369
|
-
}
|
|
1370
|
-
catch (err) {
|
|
1371
|
-
console.error(`clickIntermediateWebhookConnectorOption attempt ${i + 1} failed: ${err}`);
|
|
1372
|
-
if (i === max - 1)
|
|
1373
|
-
throw err;
|
|
1374
|
-
await this.page.reload();
|
|
1375
|
-
// domcontentloaded is more reliable than networkidle for Modeler
|
|
1376
|
-
// which maintains persistent background connections (SSE/WebSocket).
|
|
1377
|
-
await this.page.waitForLoadState('domcontentloaded');
|
|
1378
|
-
// Wait for modeler canvas to render after reload before re-selecting
|
|
1379
|
-
await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
|
|
1380
|
-
await this.secondElement.click({ force: true, timeout: 30000 });
|
|
1381
|
-
await this.changeTypeButton.click({ force: true, timeout: 30000 });
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1374
|
+
await this.clickChangeElementTemplateOption(this.intermediateWebhookConnectorOption, this.secondElement, 'Webhook');
|
|
1384
1375
|
}
|
|
1385
1376
|
async clickCorrelationKeyProcessInput() {
|
|
1386
1377
|
await this.correlationKeyProcessInput.click({ timeout: 60000 });
|
|
@@ -98,7 +98,7 @@ SM_8_10_1.test.describe('Connectors User Flow Tests @tasklistV2', () => {
|
|
|
98
98
|
await modelerCreatePage.clickStartEventElement();
|
|
99
99
|
await modelerCreatePage.clickChangeTypeButton();
|
|
100
100
|
try {
|
|
101
|
-
await modelerCreatePage.
|
|
101
|
+
await modelerCreatePage.revealChangeElementTemplate(modelerCreatePage.webhookMessageStartEventConnectorOption, 'Webhook');
|
|
102
102
|
await (0, test_1.expect)(modelerCreatePage.webhookMessageStartEventConnectorOption).toBeVisible({
|
|
103
103
|
timeout: 15000,
|
|
104
104
|
});
|
|
@@ -212,7 +212,9 @@ SM_8_10_1.test.describe('Connectors User Flow Tests @tasklistV2', () => {
|
|
|
212
212
|
// Probe for the template this flow needs: an intermediate event's
|
|
213
213
|
// change-element list never offers the message start event connector,
|
|
214
214
|
// so probing for that one always fell through to the marketplace.
|
|
215
|
-
|
|
215
|
+
// 'Webhook' is the filter both webhook flows share; the entry is then
|
|
216
|
+
// picked by its template id, so a broader term cannot mis-select.
|
|
217
|
+
await modelerCreatePage.revealChangeElementTemplate(modelerCreatePage.intermediateWebhookConnectorOption, 'Webhook');
|
|
216
218
|
await (0, test_1.expect)(modelerCreatePage.intermediateWebhookConnectorOption).toBeVisible({
|
|
217
219
|
timeout: 15000,
|
|
218
220
|
});
|