@camunda/e2e-test-suite 0.0.1279 → 0.0.1280
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.
|
@@ -227,7 +227,9 @@ declare class ModelerCreatePage {
|
|
|
227
227
|
retries?: number;
|
|
228
228
|
settleMs?: number;
|
|
229
229
|
openPanel?: boolean;
|
|
230
|
+
elementId?: string;
|
|
230
231
|
}): Promise<void>;
|
|
232
|
+
private ensureElementSelected;
|
|
231
233
|
clickCloseDetailsPanel(): Promise<void>;
|
|
232
234
|
clickOpenDetailsPanel(): Promise<void>;
|
|
233
235
|
}
|
|
@@ -1843,6 +1843,9 @@ class ModelerCreatePage {
|
|
|
1843
1843
|
if (openPanel) {
|
|
1844
1844
|
await this.clickOpenDetailsPanel();
|
|
1845
1845
|
}
|
|
1846
|
+
if (options?.elementId) {
|
|
1847
|
+
await this.ensureElementSelected(elementToClick, options.elementId);
|
|
1848
|
+
}
|
|
1846
1849
|
await this.openAuthenticationPanel();
|
|
1847
1850
|
let lastError;
|
|
1848
1851
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
@@ -1856,12 +1859,37 @@ class ModelerCreatePage {
|
|
|
1856
1859
|
}
|
|
1857
1860
|
catch (err) {
|
|
1858
1861
|
lastError = err;
|
|
1862
|
+
// The stale-selection restore can land after ensureElementSelected
|
|
1863
|
+
// has already confirmed the target, detaching the field mid-fill.
|
|
1864
|
+
if (options?.elementId) {
|
|
1865
|
+
await this.ensureElementSelected(elementToClick, options.elementId);
|
|
1866
|
+
}
|
|
1859
1867
|
await this.openAuthenticationPanel();
|
|
1860
1868
|
await (0, sleep_1.sleep)(settleMs);
|
|
1861
1869
|
}
|
|
1862
1870
|
}
|
|
1863
1871
|
throw new Error(`Failed to set OAuth 2.0 token endpoint after ${retries} attempt(s). Last error: ${String(lastError)}`);
|
|
1864
1872
|
}
|
|
1873
|
+
// After a page reload, reopening the Details panel can restore the
|
|
1874
|
+
// selection from before the reload (and scroll the canvas to it), so the
|
|
1875
|
+
// panel shows a different element than the one just clicked. The target may
|
|
1876
|
+
// then sit under the panel, so re-select it with a DOM click that the panel
|
|
1877
|
+
// cannot intercept.
|
|
1878
|
+
async ensureElementSelected(element, elementId) {
|
|
1879
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
1880
|
+
await (0, sleep_1.sleep)(1000);
|
|
1881
|
+
const selectedId = await this.elemendIdInput
|
|
1882
|
+
.inputValue({ timeout: 10000 })
|
|
1883
|
+
.catch(() => '');
|
|
1884
|
+
if (selectedId === elementId) {
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
await element.dispatchEvent('click');
|
|
1888
|
+
}
|
|
1889
|
+
await (0, test_1.expect)(this.elemendIdInput).toHaveValue(elementId, {
|
|
1890
|
+
timeout: 10000,
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1865
1893
|
async clickCloseDetailsPanel() {
|
|
1866
1894
|
await this.closeDetailsPanel.click({ timeout: 30000 });
|
|
1867
1895
|
}
|
|
@@ -566,10 +566,10 @@ async function modelAndRunConnectorsDocHandlingDiagram(modelerCreatePage, modele
|
|
|
566
566
|
// closed before their shape can be clicked and reopened afterwards.
|
|
567
567
|
await (0, sleep_1.sleep)(2000);
|
|
568
568
|
await modelerCreatePage.clickCloseDetailsPanel();
|
|
569
|
-
await modelerCreatePage.setOAuthTokenEndpoint(restTaskHit('Activity_0iyt4gv'), endpoint, { openPanel: true });
|
|
569
|
+
await modelerCreatePage.setOAuthTokenEndpoint(restTaskHit('Activity_0iyt4gv'), endpoint, { openPanel: true, elementId: 'Activity_0iyt4gv' });
|
|
570
570
|
await (0, sleep_1.sleep)(2000);
|
|
571
571
|
await modelerCreatePage.clickCloseDetailsPanel();
|
|
572
|
-
await modelerCreatePage.setOAuthTokenEndpoint(restTaskHit('Activity_1oiegam'), endpoint, { openPanel: true });
|
|
572
|
+
await modelerCreatePage.setOAuthTokenEndpoint(restTaskHit('Activity_1oiegam'), endpoint, { openPanel: true, elementId: 'Activity_1oiegam' });
|
|
573
573
|
await (0, sleep_1.sleep)(2000);
|
|
574
574
|
await modelerCreatePage.runProcessInstance('', tenant);
|
|
575
575
|
}
|
|
@@ -49,6 +49,31 @@ async function createCancellationBatch(api, processId) {
|
|
|
49
49
|
(0, assertions_1.assertRequiredFields)(json, ['batchOperationKey']);
|
|
50
50
|
return String(json.batchOperationKey);
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Suspends a batch that may already have run to completion.
|
|
54
|
+
*
|
|
55
|
+
* The engine drops a finished batch from its state, so suspending one is
|
|
56
|
+
* rejected with 404 NOT_FOUND rather than 409. A 404 is accepted only after
|
|
57
|
+
* the search store confirms the batch finished, so a batch that never existed
|
|
58
|
+
* still fails.
|
|
59
|
+
*/
|
|
60
|
+
async function suspendBatch(api, batchKey) {
|
|
61
|
+
const suspend = await api.post('/batch-operations/{batchOperationKey}/suspension', { params: { batchOperationKey: batchKey }, body: {}, tenant: 'none' });
|
|
62
|
+
await (0, assertions_1.assertStatusIn)(suspend, [204, 404, 409], 'a batch that has already finished cannot be suspended');
|
|
63
|
+
if (suspend.status() === 404) {
|
|
64
|
+
const body = (await suspend.json());
|
|
65
|
+
(0, test_1.expect)(String(body.detail)).toContain(`Expected to suspend a batch operation with key '${batchKey}', but no such batch operation was found`);
|
|
66
|
+
await (0, eventually_1.eventually)(async () => {
|
|
67
|
+
const lookup = await api.get('/batch-operations/{batchOperationKey}', {
|
|
68
|
+
params: { batchOperationKey: batchKey },
|
|
69
|
+
tenant: 'none',
|
|
70
|
+
});
|
|
71
|
+
const batch = (await (0, assertions_1.assertOk)(lookup));
|
|
72
|
+
(0, test_1.expect)(['COMPLETED', 'PARTIALLY_COMPLETED']).toContain(batch.state);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return suspend;
|
|
76
|
+
}
|
|
52
77
|
api_1.test.describe('Batch operations', () => {
|
|
53
78
|
(0, api_1.test)('creates a cancellation batch and cancels its instances', async ({ api, resources, }) => {
|
|
54
79
|
const { processId, instanceKeys } = await seedInstances(api, resources, 3);
|
|
@@ -129,8 +154,7 @@ api_1.test.describe('Batch operations', () => {
|
|
|
129
154
|
// A larger batch keeps the operation in flight long enough to suspend.
|
|
130
155
|
const { processId } = await seedInstances(api, resources, 5);
|
|
131
156
|
const batchKey = await createCancellationBatch(api, processId);
|
|
132
|
-
const suspend = await api
|
|
133
|
-
await (0, assertions_1.assertStatusIn)(suspend, [204, 409], 'a batch that has already finished cannot be suspended');
|
|
157
|
+
const suspend = await suspendBatch(api, batchKey);
|
|
134
158
|
if (suspend.status() === 204) {
|
|
135
159
|
await (0, eventually_1.eventually)(async () => {
|
|
136
160
|
const lookup = await api.get('/batch-operations/{batchOperationKey}', {
|
|
@@ -155,8 +179,7 @@ api_1.test.describe('Batch operations', () => {
|
|
|
155
179
|
(0, api_1.test)('cancels a suspended batch', async ({ api, resources }) => {
|
|
156
180
|
const { processId } = await seedInstances(api, resources, 5);
|
|
157
181
|
const batchKey = await createCancellationBatch(api, processId);
|
|
158
|
-
const suspend = await api
|
|
159
|
-
await (0, assertions_1.assertStatusIn)(suspend, [204, 409], 'a batch that has already finished cannot be suspended');
|
|
182
|
+
const suspend = await suspendBatch(api, batchKey);
|
|
160
183
|
if (suspend.status() === 204) {
|
|
161
184
|
const cancel = await api.post('/batch-operations/{batchOperationKey}/cancellation', { params: { batchOperationKey: batchKey }, body: {}, tenant: 'none' });
|
|
162
185
|
await (0, assertions_1.assertStatusIn)(cancel, [204], 'cancellation is acknowledged');
|