@camunda/e2e-test-suite 0.0.1232 → 0.0.1234
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/ModelerCreatePage.d.ts +1 -0
- package/dist/pages/8.10/ModelerCreatePage.js +30 -12
- package/dist/pages/8.10/OptimizeCollectionsPage.js +3 -1
- package/dist/pages/8.10/OptimizeDashboardPage.js +7 -1
- package/dist/pages/8.10/OptimizeHomePage.js +12 -2
- package/dist/pages/c8Run-8.10/OperateProcessInstancePage.d.ts +1 -0
- package/dist/pages/c8Run-8.10/OperateProcessInstancePage.js +32 -30
- package/dist/pages/c8Run-8.10/OperateProcessesPage.js +2 -3
- package/dist/resources/agentic_ai/ai-agent-chat-with-tools_gemini_vertex.bpmn +1 -1
- package/package.json +1 -1
- package/resources/agentic_ai/ai-agent-chat-with-tools_gemini_vertex.bpmn +1 -1
|
@@ -225,6 +225,7 @@ declare class ModelerCreatePage {
|
|
|
225
225
|
embedForm(formName: string): Promise<void>;
|
|
226
226
|
openDetailsPanelIfCollapsed(): Promise<void>;
|
|
227
227
|
fillStartEventVariablesForDocHandling(zeebeUrl: string, zeebeClientId: string, zeebeClientSecret: string): Promise<void>;
|
|
228
|
+
private expandOutputMappingEntry;
|
|
228
229
|
fillZeebeClientId(clientId: string): Promise<void>;
|
|
229
230
|
fillZeebeSecretValue(zeebeSecret: string): Promise<void>;
|
|
230
231
|
fillZeebeRestValue(zeebeUrl: string): Promise<void>;
|
|
@@ -1856,11 +1856,35 @@ class ModelerCreatePage {
|
|
|
1856
1856
|
await this.fillZeebeClientId(zeebeClientId);
|
|
1857
1857
|
await (0, sleep_1.sleep)(1000);
|
|
1858
1858
|
}
|
|
1859
|
+
// Each Output mapping row is a collapsible properties-panel entry whose
|
|
1860
|
+
// header *toggles* on click, so a single blind click is not idempotent: when
|
|
1861
|
+
// the panel re-renders while the click is in flight — it does, right after
|
|
1862
|
+
// the preceding FEEL editor commits its value — the entry ends up collapsed
|
|
1863
|
+
// again and its editor keeps a zero-size box. That is what reported
|
|
1864
|
+
// `expect(#bio-properties-panel-StartEvent_1-output-2-source div)
|
|
1865
|
+
// .toBeVisible()` timing out with "unexpected value hidden" for a full 60s
|
|
1866
|
+
// while the trace screenshot showed zeebeRestAdress and zeebeSecret open and
|
|
1867
|
+
// zeebeClientId collapsed. Ask for the state instead of assuming it: only
|
|
1868
|
+
// click while the editor is still hidden, and re-check after each click.
|
|
1869
|
+
async expandOutputMappingEntry(header, editor) {
|
|
1870
|
+
const maxAttempts = 5;
|
|
1871
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1872
|
+
if (await editor.isVisible().catch(() => false)) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
await header.click();
|
|
1876
|
+
const opened = await editor
|
|
1877
|
+
.waitFor({ state: 'visible', timeout: 15000 })
|
|
1878
|
+
.then(() => true)
|
|
1879
|
+
.catch(() => false);
|
|
1880
|
+
if (opened) {
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
await (0, test_1.expect)(editor).toBeVisible({ timeout: 60000 });
|
|
1885
|
+
}
|
|
1859
1886
|
async fillZeebeClientId(clientId) {
|
|
1860
|
-
await this.zeebeClientIdVariable.
|
|
1861
|
-
await (0, test_1.expect)(this.variableAssignmentValueTextboxThirdVariable).toBeVisible({
|
|
1862
|
-
timeout: 60000,
|
|
1863
|
-
});
|
|
1887
|
+
await this.expandOutputMappingEntry(this.zeebeClientIdVariable, this.variableAssignmentValueTextboxThirdVariable);
|
|
1864
1888
|
await this.variableAssignmentValueTextboxThirdVariable.click();
|
|
1865
1889
|
await (0, sleep_1.sleep)(1000);
|
|
1866
1890
|
await this.variableAssignmentValueTextboxThirdVariable.fill('');
|
|
@@ -1868,10 +1892,7 @@ class ModelerCreatePage {
|
|
|
1868
1892
|
await (0, test_1.expect)(this.variableAssignmentValueTextboxThirdVariable).toHaveText(clientId);
|
|
1869
1893
|
}
|
|
1870
1894
|
async fillZeebeSecretValue(zeebeSecret) {
|
|
1871
|
-
await this.zeebeSecretVariable.
|
|
1872
|
-
await (0, test_1.expect)(this.variableAssignmentValueTextboxSecondVariable).toBeVisible({
|
|
1873
|
-
timeout: 60000,
|
|
1874
|
-
});
|
|
1895
|
+
await this.expandOutputMappingEntry(this.zeebeSecretVariable, this.variableAssignmentValueTextboxSecondVariable);
|
|
1875
1896
|
await this.variableAssignmentValueTextboxSecondVariable.click();
|
|
1876
1897
|
await (0, sleep_1.sleep)(1000);
|
|
1877
1898
|
await this.variableAssignmentValueTextboxSecondVariable.fill('');
|
|
@@ -1879,10 +1900,7 @@ class ModelerCreatePage {
|
|
|
1879
1900
|
await (0, test_1.expect)(this.variableAssignmentValueTextboxSecondVariable).toHaveText(zeebeSecret);
|
|
1880
1901
|
}
|
|
1881
1902
|
async fillZeebeRestValue(zeebeUrl) {
|
|
1882
|
-
await this.zeebeRestAddressVariable.
|
|
1883
|
-
await (0, test_1.expect)(this.variableAssignmentValueTextbox).toBeVisible({
|
|
1884
|
-
timeout: 60000,
|
|
1885
|
-
});
|
|
1903
|
+
await this.expandOutputMappingEntry(this.zeebeRestAddressVariable, this.variableAssignmentValueTextbox);
|
|
1886
1904
|
await this.variableAssignmentValueTextbox.click();
|
|
1887
1905
|
await (0, sleep_1.sleep)(1000);
|
|
1888
1906
|
await this.variableAssignmentValueTextbox.fill('');
|
|
@@ -33,8 +33,10 @@ class OptimizeCollectionsPage {
|
|
|
33
33
|
.or(page.getByRole('button', { name: 'Collection', exact: true }));
|
|
34
34
|
this.modalCloseButton = page.locator('button').filter({ hasText: /^Close$/ });
|
|
35
35
|
this.processReport = page.getByText('Process Report').first();
|
|
36
|
+
// See OptimizeHomePage: Optimize's Design System navigation moved this
|
|
37
|
+
// link out of the top banner into the left sidebar.
|
|
36
38
|
this.collectionsLink = page
|
|
37
|
-
.getByRole('
|
|
39
|
+
.getByRole('navigation', { name: 'Main navigation' })
|
|
38
40
|
.getByRole('link', { name: 'Collections' });
|
|
39
41
|
this.collectionNameInput = page
|
|
40
42
|
.getByRole('dialog')
|
|
@@ -7,7 +7,13 @@ class OptimizeDashboardPage {
|
|
|
7
7
|
filterTable;
|
|
8
8
|
constructor(page) {
|
|
9
9
|
this.page = page;
|
|
10
|
-
|
|
10
|
+
// Optimize's Design System EntityList replaced the Carbon table toolbar
|
|
11
|
+
// search (placeholder "Filter table") with a plain input whose placeholder
|
|
12
|
+
// is the `home.search.name` translation, "Search for name...". With the
|
|
13
|
+
// old placeholder `clickFilterTable` waited out its 120s on every one of
|
|
14
|
+
// the five attempts, which is what reported "Process link in Optimize
|
|
15
|
+
// assertion failed after 5 attempts".
|
|
16
|
+
this.filterTable = page.getByPlaceholder(/Search for name/i);
|
|
11
17
|
}
|
|
12
18
|
async clickFilterTable() {
|
|
13
19
|
await this.filterTable.click({ timeout: 120000 });
|
|
@@ -31,9 +31,19 @@ class OptimizeHomePage {
|
|
|
31
31
|
filterTableInput;
|
|
32
32
|
constructor(page) {
|
|
33
33
|
this.page = page;
|
|
34
|
-
|
|
34
|
+
// Optimize's Design System EntityList replaced the Carbon table toolbar
|
|
35
|
+
// search (placeholder "Filter table") with a plain input whose placeholder
|
|
36
|
+
// is the `home.search.name` translation, "Search for name...". Matching on
|
|
37
|
+
// the old placeholder resolved to nothing, so `filterTableToProcess` below
|
|
38
|
+
// silently fell through and every polling round asserted against the
|
|
39
|
+
// unfiltered — and now paginated — definition table.
|
|
40
|
+
this.filterTableInput = page.getByPlaceholder(/Search for name/i);
|
|
41
|
+
// The same navigation rollout moved Dashboards/Collections out of the top
|
|
42
|
+
// banner into a left sidebar (`<nav aria-label="Main navigation">`), and
|
|
43
|
+
// the legacy banner navigation was deleted outright, so a banner-scoped
|
|
44
|
+
// link can never resolve again.
|
|
35
45
|
this.collectionsLink = page
|
|
36
|
-
.getByRole('
|
|
46
|
+
.getByRole('navigation', { name: 'Main navigation' })
|
|
37
47
|
.getByRole('link', { name: 'Collections' });
|
|
38
48
|
this.dashboardLink = page.getByRole('link', { name: 'Dashboards' });
|
|
39
49
|
this.modalCloseButton = page.locator('button').filter({ hasText: /^Close$/ });
|
|
@@ -11,6 +11,7 @@ declare class OperateProcessInstancePage {
|
|
|
11
11
|
constructor(page: Page);
|
|
12
12
|
connectorResultVariableName(name: string): Promise<Locator>;
|
|
13
13
|
connectorResultVariableValue(variableName: string): Promise<Locator>;
|
|
14
|
+
private assertInstanceStatusIcon;
|
|
14
15
|
completedIconAssertion(): Promise<void>;
|
|
15
16
|
activeIconAssertion(): Promise<void>;
|
|
16
17
|
getProcessVariableValue(variableName: string): Promise<Locator>;
|
|
@@ -32,45 +32,47 @@ class OperateProcessInstancePage {
|
|
|
32
32
|
async connectorResultVariableValue(variableName) {
|
|
33
33
|
return await this.page.getByTestId(variableName).locator('td').last();
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
// The instance header renders the status the instance had when the page was
|
|
36
|
+
// loaded, so a status that flips afterwards -- ACTIVE once the instance is
|
|
37
|
+
// exported, COMPLETED once the last task finishes -- only becomes visible on
|
|
38
|
+
// a reload. Sitting out a 60-90s per-attempt timeout before reloading
|
|
39
|
+
// therefore buys nothing: the page under the wait can no longer change. Poll
|
|
40
|
+
// on a short cadence and reload between polls instead, so the status is
|
|
41
|
+
// picked up shortly after it lands rather than at the next minute boundary.
|
|
42
|
+
//
|
|
43
|
+
// The per-attempt timeout escalates rather than staying at its opening
|
|
44
|
+
// value: on a loaded c8Run runner the instance page itself can take longer
|
|
45
|
+
// than the first interval to render, and a fixed short interval would keep
|
|
46
|
+
// reloading a page that was about to show the icon. `deadlineMs` bounds the
|
|
47
|
+
// whole assertion, so a status that never arrives still fails after at least
|
|
48
|
+
// as long as the retry loop this replaces waited.
|
|
49
|
+
async assertInstanceStatusIcon(icon, status, deadlineMs) {
|
|
50
|
+
const attemptTimeouts = [15000, 15000, 30000, 30000, 60000];
|
|
51
|
+
const deadline = Date.now() + deadlineMs;
|
|
52
|
+
let attempt = 0;
|
|
53
|
+
let lastError;
|
|
54
|
+
while (Date.now() < deadline) {
|
|
39
55
|
try {
|
|
40
|
-
await (0, test_1.expect)(
|
|
41
|
-
timeout:
|
|
56
|
+
await (0, test_1.expect)(icon).toBeVisible({
|
|
57
|
+
timeout: attemptTimeouts[Math.min(attempt, attemptTimeouts.length - 1)],
|
|
42
58
|
});
|
|
43
|
-
return;
|
|
59
|
+
return;
|
|
44
60
|
}
|
|
45
61
|
catch (error) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.log(
|
|
62
|
+
lastError = error;
|
|
63
|
+
attempt++;
|
|
64
|
+
console.log(`${status} icon not visible yet (attempt ${attempt}). Reloading...`);
|
|
49
65
|
await this.page.reload();
|
|
50
|
-
await (0, sleep_1.sleep)(10000);
|
|
51
66
|
}
|
|
52
67
|
}
|
|
53
|
-
throw new Error(
|
|
68
|
+
throw new Error(`${status} icon not visible after ${deadlineMs}ms and ${attempt} ` +
|
|
69
|
+
`reload(s): ${String(lastError)}`);
|
|
70
|
+
}
|
|
71
|
+
async completedIconAssertion() {
|
|
72
|
+
await this.assertInstanceStatusIcon(this.completedIcon, 'COMPLETED', 420000);
|
|
54
73
|
}
|
|
55
74
|
async activeIconAssertion() {
|
|
56
|
-
|
|
57
|
-
const maxRetries = 3;
|
|
58
|
-
while (retryCount < maxRetries) {
|
|
59
|
-
try {
|
|
60
|
-
await (0, test_1.expect)(this.activeIcon).toBeVisible({
|
|
61
|
-
timeout: 90000,
|
|
62
|
-
});
|
|
63
|
-
return; // Exit the function if the expectation is met
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
// If the active icon isn't found, reload the page and try again
|
|
67
|
-
retryCount++;
|
|
68
|
-
console.log(`Attempt ${retryCount} failed. Retrying...`);
|
|
69
|
-
await this.page.reload();
|
|
70
|
-
await (0, sleep_1.sleep)(10000);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
throw new Error(`Active icon not visible after ${maxRetries} attempts.`);
|
|
75
|
+
await this.assertInstanceStatusIcon(this.activeIcon, 'ACTIVE', 300000);
|
|
74
76
|
}
|
|
75
77
|
async getProcessVariableValue(variableName) {
|
|
76
78
|
return await this.page
|
|
@@ -97,11 +97,10 @@ class OperateProcessesPage {
|
|
|
97
97
|
return; // Exit the function if the click is successful
|
|
98
98
|
}
|
|
99
99
|
catch (error) {
|
|
100
|
-
//
|
|
100
|
+
// The next iteration opens with its own reload, so reloading and
|
|
101
|
+
// sleeping here only parks the worker for 10s on top of it.
|
|
101
102
|
retryCount++;
|
|
102
103
|
console.log(`Attempt ${retryCount} failed. Retrying...`);
|
|
103
|
-
await this.page.reload();
|
|
104
|
-
await (0, sleep_1.sleep)(10000);
|
|
105
104
|
}
|
|
106
105
|
}
|
|
107
106
|
throw new Error(`Failed to click on process instance link after ${maxRetries} attempts.`);
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
source="You are a helpful, generic chat agent which can answer a wide amount of questions based on your knowledge and an optional set of available tools. If tools are provided, you should prefer them instead of guessing an answer. You can call the same tool multiple times by providing different input values. Don't guess any tools which were not explicitely configured. If no tool matches the request, try to generate an answer. If you're not able to find a good answer, return with a message stating why you're not able to. If you are prompted to interact with a person, never guess contact details, but use available user/person lookup tools instead and return with an error if you're not able to look up appropriate data. Thinking, step by step, before you execute your tools, you think using the template `<thinking><context></context><reflection></reflection></thinking>`"
|
|
44
44
|
target="data.systemPrompt.prompt" />
|
|
45
45
|
<zeebe:input
|
|
46
|
-
source="="Generate a single sentence in the following exact format, using
|
|
46
|
+
source="="Generate a single sentence in the following exact format, always using a new random city and country each time: The current date and time in {City, Country}, is approximately {h:mm AM/PM} on {Month day, year}. But only with the sentence/format as above, nothing else""
|
|
47
47
|
target="data.userPrompt.prompt" />
|
|
48
48
|
<zeebe:input
|
|
49
49
|
source="=if (is defined(followUpInput) or is defined(followUpDocuments)) then followUpDocuments else inputDocuments"
|
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
source="You are a helpful, generic chat agent which can answer a wide amount of questions based on your knowledge and an optional set of available tools. If tools are provided, you should prefer them instead of guessing an answer. You can call the same tool multiple times by providing different input values. Don't guess any tools which were not explicitely configured. If no tool matches the request, try to generate an answer. If you're not able to find a good answer, return with a message stating why you're not able to. If you are prompted to interact with a person, never guess contact details, but use available user/person lookup tools instead and return with an error if you're not able to look up appropriate data. Thinking, step by step, before you execute your tools, you think using the template `<thinking><context></context><reflection></reflection></thinking>`"
|
|
44
44
|
target="data.systemPrompt.prompt" />
|
|
45
45
|
<zeebe:input
|
|
46
|
-
source="="Generate a single sentence in the following exact format, using
|
|
46
|
+
source="="Generate a single sentence in the following exact format, always using a new random city and country each time: The current date and time in {City, Country}, is approximately {h:mm AM/PM} on {Month day, year}. But only with the sentence/format as above, nothing else""
|
|
47
47
|
target="data.userPrompt.prompt" />
|
|
48
48
|
<zeebe:input
|
|
49
49
|
source="=if (is defined(followUpInput) or is defined(followUpDocuments)) then followUpDocuments else inputDocuments"
|