@camunda/e2e-test-suite 0.0.1004 → 0.0.1006
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.8/ModelerCreatePage.d.ts +2 -0
- package/dist/pages/8.8/ModelerCreatePage.js +39 -0
- package/dist/pages/SM-8.10/FormJsPage.js +13 -7
- package/dist/pages/SM-8.10/ManagementIdentityPage.js +16 -0
- package/dist/pages/SM-8.10/ModelerCreatePage.d.ts +6 -0
- package/dist/pages/SM-8.10/ModelerCreatePage.js +135 -31
- package/dist/pages/SM-8.10/ModelerHomePage.d.ts +5 -0
- package/dist/pages/SM-8.10/ModelerHomePage.js +73 -12
- package/dist/pages/SM-8.10/NavigationPage.d.ts +4 -0
- package/dist/pages/SM-8.10/NavigationPage.js +33 -2
- package/dist/pages/SM-8.10/PlayPage.js +24 -3
- package/dist/tests/8.8/hto-user-flows.spec.js +1 -4
- package/dist/tests/8.8/smoke-tests.spec.js +1 -4
- package/dist/tests/SM-8.10/hto-user-flows.spec.js +1 -4
- package/dist/tests/SM-8.10/identity-user-flows.spec.js +4 -1
- package/dist/tests/SM-8.10/migration-path-user-flows.spec.js +6 -6
- package/dist/tests/SM-8.10/play.spec.js +1 -4
- package/package.json +1 -1
|
@@ -42,6 +42,7 @@ declare class ModelerCreatePage {
|
|
|
42
42
|
readonly firstPlacedElement: Locator;
|
|
43
43
|
readonly secondPlacedElement: Locator;
|
|
44
44
|
readonly appendElementButton: Locator;
|
|
45
|
+
readonly appendIndicator: Locator;
|
|
45
46
|
readonly payloadInput: Locator;
|
|
46
47
|
readonly marketPlaceButton: Locator;
|
|
47
48
|
readonly publicHolidayConnectorOption: Locator;
|
|
@@ -176,6 +177,7 @@ declare class ModelerCreatePage {
|
|
|
176
177
|
clickFirstPlacedElement(): Promise<void>;
|
|
177
178
|
clickSecondPlacedElement(): Promise<void>;
|
|
178
179
|
clickSecondElement(): Promise<void>;
|
|
180
|
+
openAppendCreatePad(): Promise<void>;
|
|
179
181
|
clickAppendElementButton(): Promise<void>;
|
|
180
182
|
clickMarketPlaceButton(): Promise<void>;
|
|
181
183
|
clickPublicHolidayConnectorOption(): Promise<void>;
|
|
@@ -48,6 +48,7 @@ class ModelerCreatePage {
|
|
|
48
48
|
firstPlacedElement;
|
|
49
49
|
secondPlacedElement;
|
|
50
50
|
appendElementButton;
|
|
51
|
+
appendIndicator;
|
|
51
52
|
payloadInput;
|
|
52
53
|
marketPlaceButton;
|
|
53
54
|
publicHolidayConnectorOption;
|
|
@@ -120,6 +121,10 @@ class ModelerCreatePage {
|
|
|
120
121
|
this.appendElementButton = page
|
|
121
122
|
.locator('[class="djs-create-pad open djs-append-create-pad"]')
|
|
122
123
|
.first();
|
|
124
|
+
// Every element keeps an indicator overlay in the DOM and hides the ones
|
|
125
|
+
// that do not apply, so match on the visible call-to-action indicator —
|
|
126
|
+
// the one belonging to the currently selected element.
|
|
127
|
+
this.appendIndicator = page.locator('.djs-append-indicator.selected:visible');
|
|
123
128
|
this.appendTaskButton = page.getByRole('button', { name: 'Append task' });
|
|
124
129
|
this.changeTypeButton = page.getByRole('button', {
|
|
125
130
|
name: 'Change element',
|
|
@@ -510,6 +515,7 @@ class ModelerCreatePage {
|
|
|
510
515
|
else if (parentElement == 'parallelGateway') {
|
|
511
516
|
await this.clickSecondPlacedGateway();
|
|
512
517
|
}
|
|
518
|
+
await this.openAppendCreatePad();
|
|
513
519
|
await this.appendElementButton.hover();
|
|
514
520
|
await this.appendEndEventButton.click({ timeout: 120000 });
|
|
515
521
|
}
|
|
@@ -883,6 +889,13 @@ class ModelerCreatePage {
|
|
|
883
889
|
await this.endEventCanvas.click({ timeout: 60000 });
|
|
884
890
|
}
|
|
885
891
|
async clickConnectToOtherElementButton() {
|
|
892
|
+
// 'Connect to other element' is a create-pad entry
|
|
893
|
+
// (`data-entry-id="connect"`), so the pad has to be open before the entry
|
|
894
|
+
// exists at all. The element this is called on already has an outgoing
|
|
895
|
+
// sequence flow, which is exactly the case that no longer auto-opens the
|
|
896
|
+
// pad since improved-canvas 1.11.0 — go through the append indicator
|
|
897
|
+
// first, which is what clickAppendElementButton does (with its retries).
|
|
898
|
+
await this.clickAppendElementButton();
|
|
886
899
|
await (0, test_1.expect)(this.connectToOtherElementButton).toBeVisible({
|
|
887
900
|
timeout: 60000,
|
|
888
901
|
});
|
|
@@ -899,11 +912,35 @@ class ModelerCreatePage {
|
|
|
899
912
|
await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
|
|
900
913
|
await this.secondElement.click({ timeout: 60000 });
|
|
901
914
|
}
|
|
915
|
+
// Selecting an element does not open the append create pad on its own. The
|
|
916
|
+
// improved canvas gives the selected element a "+" overlay
|
|
917
|
+
// (.djs-append-indicator) instead, and only a mouseenter on that indicator
|
|
918
|
+
// opens the pad. The pad still opens by itself right after an append, and
|
|
919
|
+
// the indicator is hidden while the pad is open, so both lookups are
|
|
920
|
+
// best-effort and this is a no-op in that case.
|
|
921
|
+
async openAppendCreatePad() {
|
|
922
|
+
const padAlreadyOpen = await this.appendElementButton
|
|
923
|
+
.isVisible()
|
|
924
|
+
.catch(() => false);
|
|
925
|
+
if (padAlreadyOpen) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
const indicator = this.appendIndicator.first();
|
|
929
|
+
const indicatorShown = await indicator
|
|
930
|
+
.waitFor({ state: 'visible', timeout: 10000 })
|
|
931
|
+
.then(() => true)
|
|
932
|
+
.catch(() => false);
|
|
933
|
+
if (!indicatorShown) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
await indicator.hover({ force: true, timeout: 30000 });
|
|
937
|
+
}
|
|
902
938
|
async clickAppendElementButton() {
|
|
903
939
|
const maxRetries = 3;
|
|
904
940
|
for (let retries = 0; retries < maxRetries; retries++) {
|
|
905
941
|
try {
|
|
906
942
|
await this.page.waitForTimeout(1000);
|
|
943
|
+
await this.openAppendCreatePad();
|
|
907
944
|
await (0, test_1.expect)(this.appendElementButton).toBeVisible({ timeout: 10000 });
|
|
908
945
|
await this.appendElementButton.hover({ force: true });
|
|
909
946
|
return;
|
|
@@ -1117,6 +1154,7 @@ class ModelerCreatePage {
|
|
|
1117
1154
|
async clickFirstPlacedGateway() {
|
|
1118
1155
|
try {
|
|
1119
1156
|
await this.firstPlacedGateway.click({ timeout: 60000 });
|
|
1157
|
+
await this.openAppendCreatePad();
|
|
1120
1158
|
await (0, test_1.expect)(this.appendElementButton).toBeVisible({ timeout: 60000 });
|
|
1121
1159
|
}
|
|
1122
1160
|
catch (error) {
|
|
@@ -1153,6 +1191,7 @@ class ModelerCreatePage {
|
|
|
1153
1191
|
await this.page.reload();
|
|
1154
1192
|
await (0, sleep_1.sleep)(20000);
|
|
1155
1193
|
await this.clickFirstPlacedElement();
|
|
1194
|
+
await this.openAppendCreatePad();
|
|
1156
1195
|
await this.appendElementButton.hover();
|
|
1157
1196
|
}
|
|
1158
1197
|
await this.clickAppendGatewayButton();
|
|
@@ -36,13 +36,19 @@ class FormJsPage {
|
|
|
36
36
|
});
|
|
37
37
|
this.documentPreview = page.locator('button[data-field-type="documentPreview"]');
|
|
38
38
|
this.deployDialog = page.getByRole('dialog');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
.
|
|
39
|
+
// The Design System shell renders none of Carbon's cds-- classes, so the
|
|
40
|
+
// editor's Deploy button, the dialog's submit and the success toast are all
|
|
41
|
+
// matched by role and text instead -- which resolves on both shells.
|
|
42
|
+
// .first(): once the deploy dialog is open its submit carries the same
|
|
43
|
+
// accessible name; the editor's button is the earlier one in the DOM.
|
|
44
|
+
this.deployFormButton = page
|
|
45
|
+
.getByRole('button', { name: 'Deploy', exact: true })
|
|
46
|
+
.first();
|
|
47
|
+
this.deployModalSubmitButton = this.deployDialog
|
|
48
|
+
.getByRole('button', { name: 'Deploy', exact: true })
|
|
49
|
+
.or(page.locator('button[data-modal-primary-focus="true"][type="submit"]'))
|
|
50
|
+
.first();
|
|
51
|
+
this.deploySuccessNotification = page.getByText('Form deployed!').first();
|
|
46
52
|
}
|
|
47
53
|
async clickAIFormGeneratorButton() {
|
|
48
54
|
await this.aiFormGeneratorButton.click();
|
|
@@ -94,10 +94,26 @@ class ManagementIdentityPage {
|
|
|
94
94
|
await (0, test_1.expect)(this.demoUser).toBeVisible({ timeout: 60000 });
|
|
95
95
|
await this.demoUser.click({ timeout: 180000 });
|
|
96
96
|
}
|
|
97
|
+
// The assigned-roles table can come up with a stale row set shortly after the
|
|
98
|
+
// roles were assigned — run 32920068272 recorded `/api/users/<id>/roles`
|
|
99
|
+
// returning Optimize while the table repeated the neighbouring row's label —
|
|
100
|
+
// and it does not re-render on its own. Rebuild it from a fresh response
|
|
101
|
+
// between attempts before reporting the role as missing.
|
|
97
102
|
async clickDeleteAccessButton(accessToDelete) {
|
|
98
103
|
const roleRow = this.page
|
|
99
104
|
.locator(':text("' + accessToDelete + '")')
|
|
100
105
|
.first();
|
|
106
|
+
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
107
|
+
const rowVisible = await roleRow
|
|
108
|
+
.waitFor({ state: 'visible', timeout: 30000 })
|
|
109
|
+
.then(() => true)
|
|
110
|
+
.catch(() => false);
|
|
111
|
+
if (rowVisible) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
await this.page.reload({ waitUntil: 'domcontentloaded' });
|
|
115
|
+
await this.clickAssignedRolesTab();
|
|
116
|
+
}
|
|
101
117
|
await (0, test_1.expect)(roleRow, `No assigned role matching "${accessToDelete}" was found. The role may ` +
|
|
102
118
|
`already be removed, or its label may have changed in this version.`).toBeVisible({ timeout: 60000 });
|
|
103
119
|
await this.page
|
|
@@ -21,6 +21,10 @@ declare class ModelerCreatePage {
|
|
|
21
21
|
readonly diagramBreadcrumb: Locator;
|
|
22
22
|
readonly renameDiagramNameButton: Locator;
|
|
23
23
|
readonly diagramNameInput: Locator;
|
|
24
|
+
readonly moreActionsButton: Locator;
|
|
25
|
+
readonly renameMenuItem: Locator;
|
|
26
|
+
readonly renameInput: Locator;
|
|
27
|
+
readonly renameSubmitButton: Locator;
|
|
24
28
|
readonly variableInput: Locator;
|
|
25
29
|
readonly businessIdInput: Locator;
|
|
26
30
|
readonly embedFormButton: Locator;
|
|
@@ -113,6 +117,7 @@ declare class ModelerCreatePage {
|
|
|
113
117
|
private clickCreatePadEntry;
|
|
114
118
|
private appendViaPopup;
|
|
115
119
|
clickAppendTaskButton(): Promise<void>;
|
|
120
|
+
private padHoverTargets;
|
|
116
121
|
hoverOnLocator(locator: Locator, selector?: string): Promise<void>;
|
|
117
122
|
clickAppendGatewayButton(): Promise<void>;
|
|
118
123
|
setEngineVersion(version: string): Promise<void>;
|
|
@@ -136,6 +141,7 @@ declare class ModelerCreatePage {
|
|
|
136
141
|
fillJobTypeInput(name: string): Promise<void>;
|
|
137
142
|
clickDiagramBreadcrumb(): Promise<void>;
|
|
138
143
|
clickEditDiagramNameButton(): Promise<void>;
|
|
144
|
+
private legacyBreadcrumbPresent;
|
|
139
145
|
enterDiagramName(name: string): Promise<void>;
|
|
140
146
|
clickVariableInput(): Promise<void>;
|
|
141
147
|
fillVariableInput(variable: string): Promise<void>;
|
|
@@ -27,6 +27,10 @@ class ModelerCreatePage {
|
|
|
27
27
|
diagramBreadcrumb;
|
|
28
28
|
renameDiagramNameButton;
|
|
29
29
|
diagramNameInput;
|
|
30
|
+
moreActionsButton;
|
|
31
|
+
renameMenuItem;
|
|
32
|
+
renameInput;
|
|
33
|
+
renameSubmitButton;
|
|
30
34
|
variableInput;
|
|
31
35
|
businessIdInput;
|
|
32
36
|
embedFormButton;
|
|
@@ -107,7 +111,13 @@ class ModelerCreatePage {
|
|
|
107
111
|
this.processIdInput = page.getByLabel('ID', { exact: true });
|
|
108
112
|
this.elemendIdInput = page.getByLabel('ID', { exact: true });
|
|
109
113
|
this.startEventElement = page.locator('.djs-hit').first();
|
|
110
|
-
|
|
114
|
+
// The improved canvas exposes the append affordance of the selected element
|
|
115
|
+
// as an overlay indicator ("+" beside the shape) that stands in for the
|
|
116
|
+
// create pad's call-to-action entry; the `.djs-create-pad-icon` wrapper this
|
|
117
|
+
// used to hover is no longer rendered.
|
|
118
|
+
this.appendPreButton = page
|
|
119
|
+
.locator('.djs-append-indicator.selected')
|
|
120
|
+
.first();
|
|
111
121
|
this.appendTaskButton = page.getByRole('button', { name: 'Append task' });
|
|
112
122
|
this.appendAnythingEntry = page.locator('.djs-create-pad-entries [data-entry-id="append"]');
|
|
113
123
|
this.appendPopup = page.locator('.djs-popup.bpmn-append');
|
|
@@ -123,7 +133,18 @@ class ModelerCreatePage {
|
|
|
123
133
|
this.appendGatewayButton = page.getByRole('button', {
|
|
124
134
|
name: 'Append gateway',
|
|
125
135
|
});
|
|
126
|
-
|
|
136
|
+
// bpmn-js renders popup entries as <li role="option" data-id="..."> and
|
|
137
|
+
// binds the click handler to that li. getByText resolved the nested
|
|
138
|
+
// <span class="djs-popup-label"> instead, whose box kept failing the
|
|
139
|
+
// visible/stable actionability check inside the scrolling results list --
|
|
140
|
+
// which is why this timed out on some runs and not others. Target the li,
|
|
141
|
+
// by the data-id bpmn-js owns, with the role as a fallback. The suffix
|
|
142
|
+
// match covers both the append and change-element popups
|
|
143
|
+
// (append-* / replace-with-parallel-gateway).
|
|
144
|
+
this.parallelGatewayOption = page
|
|
145
|
+
.locator('.djs-popup-results [data-id$="parallel-gateway"]')
|
|
146
|
+
.or(page.getByRole('option', { name: /parallel gateway/i }))
|
|
147
|
+
.first();
|
|
127
148
|
this.dialog = page.getByRole('dialog');
|
|
128
149
|
this.startInstanceMainButton = page.getByRole('button', {
|
|
129
150
|
name: 'Run',
|
|
@@ -145,6 +166,10 @@ class ModelerCreatePage {
|
|
|
145
166
|
this.diagramBreadcrumb = page.locator('[data-test="breadcrumb-diagram"]');
|
|
146
167
|
this.renameDiagramNameButton = page.getByText('Rename');
|
|
147
168
|
this.diagramNameInput = page.locator('[data-test="editable-input"]');
|
|
169
|
+
this.moreActionsButton = page.getByRole('button', { name: 'More actions' });
|
|
170
|
+
this.renameMenuItem = page.getByRole('menuitem', { name: 'Rename' });
|
|
171
|
+
this.renameInput = page.locator('[data-test="rename-input"]');
|
|
172
|
+
this.renameSubmitButton = page.locator('[data-test="rename-submit"]');
|
|
148
173
|
this.variableInput = page.locator('[id="variables-json"]');
|
|
149
174
|
this.businessIdInput = page.locator('[id^="business-id-input"]');
|
|
150
175
|
this.embedFormButton = page.getByRole('button', { name: 'Link form' });
|
|
@@ -529,25 +554,75 @@ class ModelerCreatePage {
|
|
|
529
554
|
}
|
|
530
555
|
await this.appendViaPopup('append-task', ['append-tasks'], 'Task');
|
|
531
556
|
}
|
|
532
|
-
|
|
533
|
-
|
|
557
|
+
// The create pad is only mounted while the append affordance is engaged. An
|
|
558
|
+
// element without an outgoing flow gets the pad on selection, but one that
|
|
559
|
+
// already has an outgoing flow (the first gateway of a parallel branch) only
|
|
560
|
+
// gets the overlay indicator ("+" beside the shape), and the pad appears once
|
|
561
|
+
// that indicator is hovered. The indicator carries its element id in
|
|
562
|
+
// `data-element`, so key the hover on the current selection: hovering another
|
|
563
|
+
// element's indicator would open its pad and append to the wrong shape.
|
|
564
|
+
async padHoverTargets(locator, selector) {
|
|
565
|
+
if (!selector.includes('create-pad')) {
|
|
566
|
+
return [locator];
|
|
567
|
+
}
|
|
568
|
+
const selectedElementId = await this.page
|
|
569
|
+
.locator('.djs-element.selected')
|
|
570
|
+
.first()
|
|
571
|
+
.getAttribute('data-element-id', { timeout: 5000 })
|
|
572
|
+
.catch(() => null);
|
|
573
|
+
if (!selectedElementId) {
|
|
574
|
+
return [locator];
|
|
575
|
+
}
|
|
576
|
+
return [
|
|
534
577
|
this.page
|
|
535
|
-
.
|
|
536
|
-
.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
578
|
+
.locator(`.djs-append-indicator[data-element="${selectedElementId}"]`)
|
|
579
|
+
.first(),
|
|
580
|
+
locator,
|
|
581
|
+
];
|
|
582
|
+
}
|
|
583
|
+
async hoverOnLocator(locator, selector = '.djs-create-pad-entry') {
|
|
584
|
+
// Only visible entries count: both `page.waitForSelector` and `.first()`
|
|
585
|
+
// resolve a single DOM match, so an entry belonging to another element's
|
|
586
|
+
// closed pad would never satisfy `visible`.
|
|
587
|
+
const padEntry = this.page.locator(`${selector}:visible`).first();
|
|
588
|
+
let lastError = null;
|
|
589
|
+
// Promise.race leaves the losing branch pending, so when that branch later
|
|
590
|
+
// rejects nobody awaits it: the unhandled rejection fails the whole test
|
|
591
|
+
// with the loser's message ("Canvas not visible") before the callers'
|
|
592
|
+
// retries can recover. Poll the two states sequentially instead.
|
|
593
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
594
|
+
if (await padEntry.isVisible()) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
// bpmn-js opens the pad on mouseover, which does not re-fire while the
|
|
598
|
+
// pointer already rests on the trigger, so park it off-element on retries.
|
|
599
|
+
if (attempt > 1) {
|
|
600
|
+
await this.page.mouse.move(0, 0);
|
|
601
|
+
}
|
|
602
|
+
for (const target of await this.padHoverTargets(locator, selector)) {
|
|
603
|
+
const targetVisible = await target
|
|
604
|
+
.waitFor({ state: 'visible', timeout: 5000 })
|
|
605
|
+
.then(() => true)
|
|
606
|
+
.catch(() => false);
|
|
607
|
+
if (!targetVisible) {
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
// force: the append affordance of an element that already has an
|
|
611
|
+
// outgoing flow is drawn on top of that sequence flow, so the
|
|
612
|
+
// hit-target check resolves to the connection instead of the trigger.
|
|
613
|
+
await target.hover({ timeout: 10000, force: true }).catch((error) => {
|
|
614
|
+
lastError = error;
|
|
615
|
+
});
|
|
616
|
+
const padOpen = await padEntry
|
|
617
|
+
.waitFor({ state: 'visible', timeout: 10000 })
|
|
618
|
+
.then(() => true)
|
|
619
|
+
.catch(() => false);
|
|
620
|
+
if (padOpen) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
550
624
|
}
|
|
625
|
+
throw new Error(`Canvas pad entries "${selector}" did not open${lastError ? `: ${lastError}` : ''}`);
|
|
551
626
|
}
|
|
552
627
|
async clickAppendGatewayButton() {
|
|
553
628
|
await this.appendGatewayButton.click({ timeout: 90000 });
|
|
@@ -725,15 +800,51 @@ class ModelerCreatePage {
|
|
|
725
800
|
async fillJobTypeInput(name) {
|
|
726
801
|
await this.jobTypeInput.fill(name);
|
|
727
802
|
}
|
|
803
|
+
// Carbon renamed a diagram in three steps: click the diagram crumb, click
|
|
804
|
+
// "Rename" in the menu it opens, then type into the inline input. The Design
|
|
805
|
+
// System shell has no breadcrumb-diagram hook and drives the whole rename
|
|
806
|
+
// from enterDiagramName()'s dialog path, so these two steps have nothing to
|
|
807
|
+
// do there -- skip them instead of timing out on a hook that is gone.
|
|
728
808
|
async clickDiagramBreadcrumb() {
|
|
809
|
+
if (!(await this.legacyBreadcrumbPresent())) {
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
729
812
|
await this.diagramBreadcrumb.click({ timeout: 60000 });
|
|
730
813
|
}
|
|
731
814
|
async clickEditDiagramNameButton() {
|
|
815
|
+
if (!(await this.legacyBreadcrumbPresent())) {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
732
818
|
await this.renameDiagramNameButton.click();
|
|
733
819
|
}
|
|
820
|
+
async legacyBreadcrumbPresent() {
|
|
821
|
+
return this.diagramBreadcrumb
|
|
822
|
+
.waitFor({ state: 'visible', timeout: 5000 })
|
|
823
|
+
.then(() => true)
|
|
824
|
+
.catch(() => false);
|
|
825
|
+
}
|
|
826
|
+
// The Carbon editor renames the diagram through an inline editable input. The
|
|
827
|
+
// Design System editor has none: renaming moved to the breadcrumb's "More
|
|
828
|
+
// actions" > "Rename" dialog. Use whichever the deployed shell offers.
|
|
734
829
|
async enterDiagramName(name) {
|
|
735
|
-
await this.diagramNameInput
|
|
736
|
-
|
|
830
|
+
await this.diagramNameInput
|
|
831
|
+
.or(this.moreActionsButton)
|
|
832
|
+
.first()
|
|
833
|
+
.waitFor({ state: 'visible', timeout: 60000 });
|
|
834
|
+
if (await this.diagramNameInput.isVisible()) {
|
|
835
|
+
await this.diagramNameInput.fill(name, { timeout: 60000 });
|
|
836
|
+
await this.diagramNameInput.press('Enter', { timeout: 60000 });
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
// Two "More actions" buttons render here -- the project crumb's and the
|
|
840
|
+
// diagram's. first() is the diagram's; the Rename click fails loudly
|
|
841
|
+
// rather than renaming the wrong entity if that order ever changes.
|
|
842
|
+
await this.moreActionsButton.first().click();
|
|
843
|
+
await this.renameMenuItem.click();
|
|
844
|
+
await (0, test_1.expect)(this.renameInput).toBeVisible({ timeout: 10000 });
|
|
845
|
+
await this.renameInput.fill(name);
|
|
846
|
+
await this.renameSubmitButton.click();
|
|
847
|
+
await (0, test_1.expect)(this.renameInput).toBeHidden({ timeout: 10000 });
|
|
737
848
|
}
|
|
738
849
|
async clickVariableInput() {
|
|
739
850
|
await this.variableInput.click();
|
|
@@ -1092,16 +1203,9 @@ class ModelerCreatePage {
|
|
|
1092
1203
|
}
|
|
1093
1204
|
}
|
|
1094
1205
|
async clickAppendElementButton() {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
return; // Exit loop if successful
|
|
1099
|
-
}
|
|
1100
|
-
catch (error) {
|
|
1101
|
-
if (attempt === 3)
|
|
1102
|
-
throw error; // Rethrow after 3 failed attempts
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1206
|
+
// hoverOnLocator already retries the hover; a second retry layer here only
|
|
1207
|
+
// multiplied the worst-case wait.
|
|
1208
|
+
await this.hoverOnLocator(this.appendPreButton);
|
|
1105
1209
|
}
|
|
1106
1210
|
async clickParallelGatewayOption() {
|
|
1107
1211
|
await this.parallelGatewayOption.click({ timeout: 90000 });
|
|
@@ -5,6 +5,10 @@ declare class ModelerHomePage {
|
|
|
5
5
|
readonly modelerPageBanner: Locator;
|
|
6
6
|
readonly createNewProjectButton: Locator;
|
|
7
7
|
readonly projectNameInput: Locator;
|
|
8
|
+
readonly moreActionsButton: Locator;
|
|
9
|
+
readonly renameMenuItem: Locator;
|
|
10
|
+
readonly renameInput: Locator;
|
|
11
|
+
readonly renameSubmitButton: Locator;
|
|
8
12
|
readonly chooseBpmnTemplateButton: Locator;
|
|
9
13
|
readonly diagramTypeDropdown: Locator;
|
|
10
14
|
readonly bpmnTemplateOption: Locator;
|
|
@@ -37,6 +41,7 @@ declare class ModelerHomePage {
|
|
|
37
41
|
clickBpmnTemplateOption(): Promise<void>;
|
|
38
42
|
clickFormOption(): Promise<void>;
|
|
39
43
|
enterFormName(name: string): Promise<void>;
|
|
44
|
+
private renameViaMoreActions;
|
|
40
45
|
clickProjectBreadcrumb(): Promise<void>;
|
|
41
46
|
clickOpenOrganizationsButton(): Promise<void>;
|
|
42
47
|
clickManageButton(): Promise<void>;
|
|
@@ -10,6 +10,10 @@ class ModelerHomePage {
|
|
|
10
10
|
modelerPageBanner;
|
|
11
11
|
createNewProjectButton;
|
|
12
12
|
projectNameInput;
|
|
13
|
+
moreActionsButton;
|
|
14
|
+
renameMenuItem;
|
|
15
|
+
renameInput;
|
|
16
|
+
renameSubmitButton;
|
|
13
17
|
chooseBpmnTemplateButton;
|
|
14
18
|
diagramTypeDropdown;
|
|
15
19
|
bpmnTemplateOption;
|
|
@@ -31,9 +35,13 @@ class ModelerHomePage {
|
|
|
31
35
|
modalCloseButton;
|
|
32
36
|
constructor(page) {
|
|
33
37
|
this.page = page;
|
|
38
|
+
// Matches both Modeler shells -- see NavigationPage.modelerPageBanner for
|
|
39
|
+
// why the Design System branch excludes the /login href.
|
|
34
40
|
this.modelerPageBanner = page
|
|
35
|
-
.
|
|
36
|
-
.
|
|
41
|
+
.getByRole('link', { name: 'Camunda Modeler home' })
|
|
42
|
+
.and(page.locator(':not([href$="/login"])'))
|
|
43
|
+
.or(page.locator('a').filter({ hasText: 'Camunda logoModeler' }))
|
|
44
|
+
.first();
|
|
37
45
|
this.createNewProjectButton = page
|
|
38
46
|
.getByRole('button', {
|
|
39
47
|
name: 'Create new project',
|
|
@@ -42,6 +50,10 @@ class ModelerHomePage {
|
|
|
42
50
|
name: 'New project',
|
|
43
51
|
}));
|
|
44
52
|
this.projectNameInput = page.locator('[data-test="editable-input"]');
|
|
53
|
+
this.moreActionsButton = page.getByRole('button', { name: 'More actions' });
|
|
54
|
+
this.renameMenuItem = page.getByRole('menuitem', { name: 'Rename' });
|
|
55
|
+
this.renameInput = page.locator('[data-test="rename-input"]');
|
|
56
|
+
this.renameSubmitButton = page.locator('[data-test="rename-submit"]');
|
|
45
57
|
this.chooseBpmnTemplateButton = page.getByRole('button', {
|
|
46
58
|
name: 'Choose BPMN template',
|
|
47
59
|
});
|
|
@@ -52,7 +64,17 @@ class ModelerHomePage {
|
|
|
52
64
|
this.formTemplateOption = page
|
|
53
65
|
.locator('[data-test="create-form"]')
|
|
54
66
|
.getByText('Form');
|
|
55
|
-
|
|
67
|
+
// The Design System shell drops the breadcrumb-project hook. Its context
|
|
68
|
+
// breadcrumb is org / project / entity, so the project crumb is the second
|
|
69
|
+
// item -- scoped to the breadcrumb nav, never a bare nth() on the page.
|
|
70
|
+
this.projectBreadcrumb = page
|
|
71
|
+
.locator('[data-test="breadcrumb-project"]')
|
|
72
|
+
.or(page
|
|
73
|
+
.locator('nav[aria-label="Context navigation"] [data-slot="nav-breadcrumb-item"]')
|
|
74
|
+
.nth(1)
|
|
75
|
+
.getByRole('button')
|
|
76
|
+
.first())
|
|
77
|
+
.first();
|
|
56
78
|
this.openOrganizationsButton = page.getByLabel('Open Organizations');
|
|
57
79
|
this.manageButton = page.getByRole('button', { name: 'Manage' });
|
|
58
80
|
this.crossComponentProjectFolder = page
|
|
@@ -60,7 +82,12 @@ class ModelerHomePage {
|
|
|
60
82
|
exact: true,
|
|
61
83
|
})
|
|
62
84
|
.first();
|
|
63
|
-
|
|
85
|
+
// The Design System shell drops the breadcrumb-home hook and labels the
|
|
86
|
+
// same crumb "My organisation".
|
|
87
|
+
this.homeBreadcrumb = page
|
|
88
|
+
.locator('[data-test="breadcrumb-home"]')
|
|
89
|
+
.or(page.getByRole('button', { name: 'My organisation' }))
|
|
90
|
+
.first();
|
|
64
91
|
this.formNameInput = page.locator('[data-test="editable-input"]');
|
|
65
92
|
this.rows = page.getByRole('row');
|
|
66
93
|
this.licenseKeyTagNonProduction = page
|
|
@@ -90,11 +117,24 @@ class ModelerHomePage {
|
|
|
90
117
|
.catch(() => { });
|
|
91
118
|
await this.createNewProjectButton.click();
|
|
92
119
|
}
|
|
120
|
+
// The Carbon shell renames a project through an inline editable input on the
|
|
121
|
+
// project page. The Design System shell renders the name as a plain span and
|
|
122
|
+
// moved renaming behind "More actions" > "Rename", which opens a dialog. Wait
|
|
123
|
+
// for whichever affordance the deployed shell offers, then use that one --
|
|
124
|
+
// both images are still in circulation.
|
|
93
125
|
async enterNewProjectName(name) {
|
|
94
|
-
await
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
await this.projectNameInput
|
|
127
|
+
.or(this.moreActionsButton)
|
|
128
|
+
.first()
|
|
129
|
+
.waitFor({ state: 'visible', timeout: 30000 });
|
|
130
|
+
// Inline first: when the Carbon shell renders it, it is the whole flow.
|
|
131
|
+
if (await this.projectNameInput.isVisible()) {
|
|
132
|
+
await this.projectNameInput.click({ timeout: 60000 });
|
|
133
|
+
await this.projectNameInput.fill(name);
|
|
134
|
+
await this.projectNameInput.press('Enter');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
await this.renameViaMoreActions(name);
|
|
98
138
|
}
|
|
99
139
|
// Wait for the Modeler project workspace to become interactive. The caller
|
|
100
140
|
// arrives here via goToModeler(), which has already loaded and authenticated
|
|
@@ -242,11 +282,32 @@ class ModelerHomePage {
|
|
|
242
282
|
async clickFormOption() {
|
|
243
283
|
await this.formTemplateOption.click();
|
|
244
284
|
}
|
|
285
|
+
// Same shell split as enterNewProjectName: the Design System form editor has
|
|
286
|
+
// no inline editable input and renames through the breadcrumb's "More
|
|
287
|
+
// actions" > "Rename" dialog.
|
|
245
288
|
async enterFormName(name) {
|
|
246
|
-
await
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
289
|
+
await this.formNameInput
|
|
290
|
+
.or(this.moreActionsButton)
|
|
291
|
+
.first()
|
|
292
|
+
.waitFor({ state: 'visible', timeout: 30000 });
|
|
293
|
+
if (await this.formNameInput.isVisible()) {
|
|
294
|
+
await this.formNameInput.click({ timeout: 60000 });
|
|
295
|
+
await this.formNameInput.fill(name);
|
|
296
|
+
await this.formNameInput.press('Enter');
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
await this.renameViaMoreActions(name);
|
|
300
|
+
}
|
|
301
|
+
// The editors show two "More actions" buttons -- one for the project crumb
|
|
302
|
+
// and one for the entity being edited. first() is the entity's; the Rename
|
|
303
|
+
// click fails loudly rather than renaming the wrong thing if that changes.
|
|
304
|
+
async renameViaMoreActions(name) {
|
|
305
|
+
await this.moreActionsButton.first().click();
|
|
306
|
+
await this.renameMenuItem.click();
|
|
307
|
+
await (0, test_1.expect)(this.renameInput).toBeVisible({ timeout: 10000 });
|
|
308
|
+
await this.renameInput.fill(name);
|
|
309
|
+
await this.renameSubmitButton.click();
|
|
310
|
+
await (0, test_1.expect)(this.renameInput).toBeHidden({ timeout: 10000 });
|
|
250
311
|
}
|
|
251
312
|
async clickProjectBreadcrumb() {
|
|
252
313
|
await this.projectBreadcrumb.click({ timeout: 60000 });
|
|
@@ -35,6 +35,10 @@ declare class NavigationPage {
|
|
|
35
35
|
username?: string;
|
|
36
36
|
password?: string;
|
|
37
37
|
}): Promise<void>;
|
|
38
|
+
goToModelerWithoutAccess({ username, password, }?: {
|
|
39
|
+
username?: string;
|
|
40
|
+
password?: string;
|
|
41
|
+
}): Promise<void>;
|
|
38
42
|
goToKeycloak(maxRetries?: number): Promise<void>;
|
|
39
43
|
goToOCAdmin(sleepTimeout?: number, credentials?: {
|
|
40
44
|
username: string;
|
|
@@ -35,9 +35,19 @@ class NavigationPage {
|
|
|
35
35
|
.getByRole('link', { name: 'Camunda logo Operate' })
|
|
36
36
|
.or(page.getByRole('link', { name: 'Camunda Operate', exact: true }))
|
|
37
37
|
.first();
|
|
38
|
+
// Web Modeler renders the Design System nav shell (NavShellDs) whenever
|
|
39
|
+
// `design-system-enabled` is on -- its home link is
|
|
40
|
+
// aria-label="Camunda Modeler home" wrapping an aria-hidden logo, so the
|
|
41
|
+
// legacy shell's "Camunda logoModeler" text no longer exists. The
|
|
42
|
+
// unauthenticated shell reuses that aria-label pointing at /login, and
|
|
43
|
+
// waitForBanner() gates only on visibility, so exclude that href here:
|
|
44
|
+
// callers use this banner as the logged-in gate.
|
|
45
|
+
// Match either shell so the banner resolves with the flag on or off.
|
|
38
46
|
this.modelerPageBanner = page
|
|
39
|
-
.
|
|
40
|
-
.
|
|
47
|
+
.getByRole('link', { name: 'Camunda Modeler home' })
|
|
48
|
+
.and(page.locator(':not([href$="/login"])'))
|
|
49
|
+
.or(page.locator('a').filter({ hasText: 'Camunda logoModeler' }))
|
|
50
|
+
.first();
|
|
41
51
|
this.tasklistPageBanner = page.getByRole('link', {
|
|
42
52
|
name: 'Camunda logo Tasklist',
|
|
43
53
|
});
|
|
@@ -258,6 +268,27 @@ class NavigationPage {
|
|
|
258
268
|
}
|
|
259
269
|
await new LoginPage_1.LoginPage(this.page).login(username, password);
|
|
260
270
|
}
|
|
271
|
+
// Same reason as `goToOptimizeWithoutAccess`: a user whose Web Modeler role
|
|
272
|
+
// was removed never reaches a page carrying the Modeler banner — the OAuth
|
|
273
|
+
// round trip ends back on the Keycloak authorize URL — so `goTo` burns all 8
|
|
274
|
+
// attempts (~570s) and throws instead of letting the caller assert the denial.
|
|
275
|
+
// Navigate and log in only; the caller asserts what the denied page shows.
|
|
276
|
+
async goToModelerWithoutAccess({ username = IDENTITY_FIRSTUSER_USERNAME, password = IDENTITY_FIRSTUSER_PASSWORD, } = {}) {
|
|
277
|
+
await this.page.goto(MODELER_CONTEXT_PATH, {
|
|
278
|
+
timeout: 60000,
|
|
279
|
+
waitUntil: 'domcontentloaded',
|
|
280
|
+
});
|
|
281
|
+
let gatewayReloads = 0;
|
|
282
|
+
while (gatewayReloads < 8 && (await this.isGatewayErrorPage())) {
|
|
283
|
+
await (0, sleep_1.sleep)(constants_1._1_SECOND_IN_MS * 5);
|
|
284
|
+
await this.page.goto(MODELER_CONTEXT_PATH, {
|
|
285
|
+
timeout: 60000,
|
|
286
|
+
waitUntil: 'domcontentloaded',
|
|
287
|
+
});
|
|
288
|
+
gatewayReloads++;
|
|
289
|
+
}
|
|
290
|
+
await new LoginPage_1.LoginPage(this.page).login(username, password);
|
|
291
|
+
}
|
|
261
292
|
async goToKeycloak(maxRetries = 5) {
|
|
262
293
|
const keycloakUrl = process.env.KEYCLOAK_URL
|
|
263
294
|
? `${process.env.KEYCLOAK_URL}/auth`
|
|
@@ -30,9 +30,15 @@ class PlayPage {
|
|
|
30
30
|
constructor(page) {
|
|
31
31
|
this.page = page;
|
|
32
32
|
this.dialog = page.getByRole('dialog');
|
|
33
|
+
// Test mode labels this button with a <span class="sr-only">Complete job</span>
|
|
34
|
+
// rather than an aria-label, so getByLabel cannot see it -- its data-testid
|
|
35
|
+
// is element-scoped ("<elementId>-Complete job"). getByRole reads the
|
|
36
|
+
// accessible name, which the sr-only text and the legacy aria-label both
|
|
37
|
+
// supply, so this resolves on either shell.
|
|
33
38
|
this.completeJobButton = page
|
|
34
39
|
.getByTestId('diagram')
|
|
35
|
-
.
|
|
40
|
+
.getByRole('button', { name: 'Complete job' })
|
|
41
|
+
.first();
|
|
36
42
|
// Test mode renamed "scenario" to "test case" across this panel
|
|
37
43
|
// (camunda-hub a90fd06). Each label below accepts both wordings so the
|
|
38
44
|
// page object works either side of the rename.
|
|
@@ -42,8 +48,18 @@ class PlayPage {
|
|
|
42
48
|
this.runAllScenariosButton = page.getByRole('button', {
|
|
43
49
|
name: /^Run all (scenarios|test cases)$/i,
|
|
44
50
|
});
|
|
51
|
+
// The Design System confirmation is a Radix AlertDialog, so its role is
|
|
52
|
+
// "alertdialog" -- a distinct ARIA role that getByRole('dialog') does not
|
|
53
|
+
// match. Accept either role and identify it by its heading rather than an
|
|
54
|
+
// accessible name, which the DS dialog does not always expose.
|
|
45
55
|
this.confirmDeleteScenarioButton = page
|
|
46
|
-
.getByRole('
|
|
56
|
+
.getByRole('alertdialog')
|
|
57
|
+
.or(page.getByRole('dialog'))
|
|
58
|
+
.filter({
|
|
59
|
+
has: page.getByRole('heading', {
|
|
60
|
+
name: /^Delete (scenario|test case)$/i,
|
|
61
|
+
}),
|
|
62
|
+
})
|
|
47
63
|
.getByRole('button', { name: 'Delete', exact: true });
|
|
48
64
|
// After saving a scenario, the Scenarios panel is in detail-view mode.
|
|
49
65
|
// To get back to the list (where "Run all scenarios" lives in
|
|
@@ -82,9 +98,14 @@ class PlayPage {
|
|
|
82
98
|
// non-actionable toasts (see Notification.tsx in @camunda/c4-notifications).
|
|
83
99
|
// Anchor on the accessible role instead of the Carbon CSS class so the
|
|
84
100
|
// locator is resilient to Carbon version bumps.
|
|
101
|
+
// The Design System toast stack is an <ol> of plain <li> items with no
|
|
102
|
+
// role="alert" (the only alert role in Test mode belongs to the Copilot
|
|
103
|
+
// panel), so match the text as well as the legacy alert role.
|
|
85
104
|
this.scenarioSavedToast = page
|
|
86
105
|
.getByRole('alert')
|
|
87
|
-
.filter({ hasText: /(Scenario|Test case) saved/i })
|
|
106
|
+
.filter({ hasText: /(Scenario|Test case) saved/i })
|
|
107
|
+
.or(page.getByText(/(Scenario|Test case) saved/i))
|
|
108
|
+
.first();
|
|
88
109
|
this.loadingInstanceDetailsText = this.page.getByText('Loading instance details...');
|
|
89
110
|
this.retryButton = this.page.getByRole('button', { name: 'Retry' });
|
|
90
111
|
// New Play UI (8.10+): "Configure scenario" opens an input panel with a plain "Start" button.
|
|
@@ -311,10 +311,7 @@ _8_8_1.test.describe('HTO User Flow Tests', () => {
|
|
|
311
311
|
await (0, expectTextWithPagination_1.expectTextWithPagination)(page, processName + '2');
|
|
312
312
|
});
|
|
313
313
|
});
|
|
314
|
-
|
|
315
|
-
// https://github.com/camunda/c8-cross-component-e2e-tests/pull/3144
|
|
316
|
-
// Re-enable in the same change that lands #3144.
|
|
317
|
-
_8_8_1.test.skip('Zeebe User Task With Priority', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, taskPanelPage, taskDetailsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
314
|
+
(0, _8_8_1.test)('Zeebe User Task With Priority', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, taskPanelPage, taskDetailsPage, operateHomePage, operateProcessesPage, operateProcessInstancePage, }) => {
|
|
318
315
|
const randomName = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
319
316
|
const processName = 'Zeebe_User_Task_Process_With_Priority' + randomName;
|
|
320
317
|
const taskName = 'priorityTest' + randomName;
|
|
@@ -37,10 +37,7 @@ _8_8_1.test.describe('Smoke Tests', () => {
|
|
|
37
37
|
await (0, _setup_1.captureScreenshot)(page, testInfo);
|
|
38
38
|
await (0, _setup_1.captureFailureVideo)(page, testInfo);
|
|
39
39
|
});
|
|
40
|
-
|
|
41
|
-
// https://github.com/camunda/c8-cross-component-e2e-tests/pull/3144
|
|
42
|
-
// Re-enable in the same change that lands #3144.
|
|
43
|
-
_8_8_1.test.skip('Most Common Flow User Flow With All Apps', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, }) => {
|
|
40
|
+
(0, _8_8_1.test)('Most Common Flow User Flow With All Apps', async ({ page, homePage, modelerHomePage, appsPage, modelerCreatePage, formJsPage, }) => {
|
|
44
41
|
_8_8_1.test.slow();
|
|
45
42
|
const randomString = useFixedNames
|
|
46
43
|
? 'UpgradeTest'
|
|
@@ -46,10 +46,7 @@ SM_8_10_1.test.describe('HTO User Flow Tests', () => {
|
|
|
46
46
|
await operateProcessInstancePage.completedIconAssertion();
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
-
|
|
50
|
-
// https://github.com/camunda/c8-cross-component-e2e-tests/pull/3144
|
|
51
|
-
// Re-enable in the same change that lands #3144.
|
|
52
|
-
SM_8_10_1.test.skip('Zeebe User Task With Priority', async ({ page, modelerHomePage, navigationPage, modelerCreatePage, operateHomePage, operateProcessesPage, operateProcessInstancePage, taskDetailsPage, taskPanelPage, }) => {
|
|
49
|
+
(0, SM_8_10_1.test)('Zeebe User Task With Priority', async ({ page, modelerHomePage, navigationPage, modelerCreatePage, operateHomePage, operateProcessesPage, operateProcessInstancePage, taskDetailsPage, taskPanelPage, }) => {
|
|
53
50
|
SM_8_10_1.test.slow();
|
|
54
51
|
const randomName = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
55
52
|
const processName = 'Zeebe_User_Task_Process_With_Priority' + randomName;
|
|
@@ -61,7 +61,10 @@ SM_8_10_1.test.describe('Identity User Flow Tests', () => {
|
|
|
61
61
|
await (0, sleep_1.sleep)(40000);
|
|
62
62
|
});
|
|
63
63
|
await SM_8_10_1.test.step('Ensure Modeler is not Accessible', async () => {
|
|
64
|
-
|
|
64
|
+
// goToModeler asserts the Modeler banner, which is exactly what a user
|
|
65
|
+
// without the Hub role never gets: it exhausts its 8 login attempts on
|
|
66
|
+
// the Keycloak authorize URL and throws before this assertion can run.
|
|
67
|
+
await navigationPage.goToModelerWithoutAccess(credentials);
|
|
65
68
|
await (0, test_1.expect)(modelerHomePage.modelerPageBanner).not.toBeVisible({
|
|
66
69
|
timeout: 60000,
|
|
67
70
|
});
|
|
@@ -115,8 +115,8 @@ if (process.env.IS_MIGRATION === 'true') {
|
|
|
115
115
|
'ManagementIdentity',
|
|
116
116
|
'Optimize',
|
|
117
117
|
'Orchestration',
|
|
118
|
-
'
|
|
119
|
-
'
|
|
118
|
+
'Hub',
|
|
119
|
+
'Hub Admin',
|
|
120
120
|
]);
|
|
121
121
|
await managementIdentityPage.clickUsersLink();
|
|
122
122
|
await identityUsersPage.assertUserIsAssignedCorrectRole('bart', [
|
|
@@ -124,8 +124,8 @@ if (process.env.IS_MIGRATION === 'true') {
|
|
|
124
124
|
'ManagementIdentity',
|
|
125
125
|
'Optimize',
|
|
126
126
|
'Orchestration',
|
|
127
|
-
'
|
|
128
|
-
'
|
|
127
|
+
'Hub',
|
|
128
|
+
'Hub Admin',
|
|
129
129
|
]);
|
|
130
130
|
await managementIdentityPage.clickUsersLink();
|
|
131
131
|
await identityUsersPage.assertUserIsAssignedCorrectRole('lisa', [
|
|
@@ -133,8 +133,8 @@ if (process.env.IS_MIGRATION === 'true') {
|
|
|
133
133
|
'ManagementIdentity',
|
|
134
134
|
'Optimize',
|
|
135
135
|
'Orchestration',
|
|
136
|
-
'
|
|
137
|
-
'
|
|
136
|
+
'Hub',
|
|
137
|
+
'Hub Admin',
|
|
138
138
|
]);
|
|
139
139
|
});
|
|
140
140
|
(0, SM_8_10_1.test)('Assert Demo User Can Deploy Processes', async ({ page, modelerHomePage, navigationPage, modelerCreatePage, operateHomePage, operateProcessesPage, operateProcessInstancePage, taskDetailsPage, taskPanelPage, }) => {
|
|
@@ -41,10 +41,7 @@ SM_8_10_1.test.describe('Deploy and run a process in Play', () => {
|
|
|
41
41
|
await playPage.waitForProcessToBeCompleted();
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
|
-
|
|
45
|
-
// https://github.com/camunda/c8-cross-component-e2e-tests/pull/3144
|
|
46
|
-
// Re-enable in the same change that lands #3144.
|
|
47
|
-
SM_8_10_1.test.skip('Create,update and delete test scenarios in play', async ({ modelerHomePage, modelerCreatePage, playPage, }) => {
|
|
44
|
+
(0, SM_8_10_1.test)('Create,update and delete test scenarios in play', async ({ modelerHomePage, modelerCreatePage, playPage, }) => {
|
|
48
45
|
SM_8_10_1.test.slow();
|
|
49
46
|
const randomString = await (0, _setup_1.generateRandomStringAsync)(3);
|
|
50
47
|
const processName = 'Play_Test_Process' + randomString;
|