@camunda/e2e-test-suite 0.0.683 → 0.0.684
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/ConnectorMarketplacePage.d.ts +0 -1
- package/dist/pages/8.8/ConnectorMarketplacePage.js +23 -40
- package/dist/pages/8.8/ModelerCreatePage.js +35 -70
- package/dist/pages/8.9/ConnectorMarketplacePage.d.ts +1 -0
- package/dist/pages/8.9/ConnectorMarketplacePage.js +22 -2
- package/dist/pages/8.9/ModelerCreatePage.js +10 -19
- package/package.json +1 -1
|
@@ -7,7 +7,6 @@ declare class ConnectorMarketplacePage {
|
|
|
7
7
|
readonly closeButton: Locator;
|
|
8
8
|
readonly replaceResourceButton: Locator;
|
|
9
9
|
readonly addToProjectButton: Locator;
|
|
10
|
-
readonly saveAsCopyButton: Locator;
|
|
11
10
|
readonly cancelButton: Locator;
|
|
12
11
|
constructor(page: Page);
|
|
13
12
|
clickSearchForConnectorTextbox(): Promise<void>;
|
|
@@ -9,7 +9,6 @@ class ConnectorMarketplacePage {
|
|
|
9
9
|
closeButton;
|
|
10
10
|
replaceResourceButton;
|
|
11
11
|
addToProjectButton;
|
|
12
|
-
saveAsCopyButton;
|
|
13
12
|
cancelButton;
|
|
14
13
|
constructor(page) {
|
|
15
14
|
this.page = page;
|
|
@@ -22,21 +21,9 @@ class ConnectorMarketplacePage {
|
|
|
22
21
|
this.replaceResourceButton = page.getByRole('button', {
|
|
23
22
|
name: 'Replace resource',
|
|
24
23
|
});
|
|
25
|
-
// Camunda Hub's ImportModal renders one of three primary buttons depending
|
|
26
|
-
// on state. Source: camunda-hub
|
|
27
|
-
// frontend/apps/hub/src/components/ImportModal/get-action-buttons-props.js
|
|
28
|
-
// - "Add to project" for a brand-new resource (showPublish)
|
|
29
|
-
// - "Replace resource" when a duplicate exists and replace is allowed
|
|
30
|
-
// - "Save as copy" when a duplicate exists but replace is NOT
|
|
31
|
-
// allowed (e.g. an existing project template
|
|
32
|
-
// conflict — user must save the import under a
|
|
33
|
-
// new ID to keep both)
|
|
34
24
|
this.addToProjectButton = page.getByRole('button', {
|
|
35
25
|
name: 'Add to project',
|
|
36
26
|
});
|
|
37
|
-
this.saveAsCopyButton = page.getByRole('button', {
|
|
38
|
-
name: 'Save as copy',
|
|
39
|
-
});
|
|
40
27
|
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
|
|
41
28
|
}
|
|
42
29
|
async clickSearchForConnectorTextbox() {
|
|
@@ -59,35 +46,31 @@ class ConnectorMarketplacePage {
|
|
|
59
46
|
}
|
|
60
47
|
async downloadConnectorToProject() {
|
|
61
48
|
await this.clickDownloadToProjectButton();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// Cancel the modal: Save as copy would create a duplicate under a
|
|
75
|
-
// different name (and the test then can't find "Worldwide Public
|
|
76
|
-
// Holiday"), and Replace risks other tests' state. The connector
|
|
77
|
-
// already exists — clickPublicHolidayConnectorOption just needs
|
|
78
|
-
// to find it in the change-element popup, which it does via a
|
|
79
|
-
// state reset.
|
|
80
|
-
if (await this.addToProjectButton
|
|
81
|
-
.isVisible({ timeout: 20000 })
|
|
82
|
-
.catch(() => false)) {
|
|
83
|
-
await this.addToProjectButton.click({ timeout: 30000 });
|
|
84
|
-
return;
|
|
49
|
+
let imported = false;
|
|
50
|
+
try {
|
|
51
|
+
await Promise.race([
|
|
52
|
+
this.addToProjectButton.click({ timeout: 20000 }),
|
|
53
|
+
this.replaceResourceButton.click({ timeout: 20000 }),
|
|
54
|
+
]);
|
|
55
|
+
imported = true;
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
if (await this.cancelButton.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
59
|
+
await this.cancelButton.click({ timeout: 10000 });
|
|
60
|
+
}
|
|
85
61
|
}
|
|
86
|
-
|
|
87
|
-
|
|
62
|
+
// After a successful import, wait for the snackbar (confirms the connector
|
|
63
|
+
// template was received by the modeler) then close the marketplace panel so
|
|
64
|
+
// the diagram canvas is unblocked before the caller tries to select the
|
|
65
|
+
// newly installed connector.
|
|
66
|
+
if (imported) {
|
|
67
|
+
await this.snackbar
|
|
68
|
+
.waitFor({ state: 'visible', timeout: 60000 })
|
|
69
|
+
.catch(() => { });
|
|
70
|
+
if (await this.closeButton.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
71
|
+
await this.closeButton.click({ timeout: 10000 });
|
|
72
|
+
}
|
|
88
73
|
}
|
|
89
|
-
// If neither button is visible the import dialog never opened; nothing
|
|
90
|
-
// to dismiss and downstream state-reset will recover.
|
|
91
74
|
}
|
|
92
75
|
}
|
|
93
76
|
exports.ConnectorMarketplacePage = ConnectorMarketplacePage;
|
|
@@ -4,6 +4,7 @@ exports.ModelerCreatePage = void 0;
|
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
5
|
const sleep_1 = require("../../utils/sleep");
|
|
6
6
|
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
|
|
7
|
+
const ConnectorMarketplacePage_1 = require("./ConnectorMarketplacePage");
|
|
7
8
|
class ModelerCreatePage {
|
|
8
9
|
page;
|
|
9
10
|
generalPanel;
|
|
@@ -186,17 +187,9 @@ class ModelerCreatePage {
|
|
|
186
187
|
this.secondPlacedElement = page.locator('g:nth-child(2) > .djs-element > .djs-hit');
|
|
187
188
|
this.payloadInput = page.locator('[class="fjs-input"]');
|
|
188
189
|
this.marketPlaceButton = page.getByTitle('Browse Marketplace for more Connectors');
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// the virtualized list — which never satisfies toBeVisible. Targeting
|
|
193
|
-
// the listitem by accessible name mirrors the SM-8.8 pattern
|
|
194
|
-
// (pages/SM-8.8/ModelerCreatePage.ts:165) and works whether the
|
|
195
|
-
// connector is at the top of the list or filtered via search.
|
|
196
|
-
this.publicHolidayConnectorOption = page.getByRole('listitem', {
|
|
197
|
-
name: 'Worldwide Public Holiday',
|
|
198
|
-
exact: false,
|
|
199
|
-
});
|
|
190
|
+
this.publicHolidayConnectorOption = page
|
|
191
|
+
.locator('[data-test="modeler"]')
|
|
192
|
+
.getByText('Worldwide Public Holiday');
|
|
200
193
|
this.publicHolidayYearOption = page.getByLabel('Year');
|
|
201
194
|
this.publicHolidayCountryCodeOption = page.getByLabel('Countrycode');
|
|
202
195
|
this.implementationSection = page.locator('[data-group-id="group-userTaskImplementation"]');
|
|
@@ -784,77 +777,49 @@ class ModelerCreatePage {
|
|
|
784
777
|
throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
|
|
785
778
|
}
|
|
786
779
|
async clickPublicHolidayConnectorOption() {
|
|
787
|
-
// Port of the 8.7 state-reset approach
|
|
788
|
-
// (pages/8.7/ModelerCreatePage.ts). After the test's marketplace flow
|
|
789
|
-
// completes, the connector is on the project (whether freshly added or
|
|
790
|
-
// already there from a prior run) but the modeler may be in any of
|
|
791
|
-
// several states: change-element popup closed, residual import modal
|
|
792
|
-
// up, virtualized list with the connector off-screen. Instead of
|
|
793
|
-
// trying to manage those states, dismiss any overlay, reload the page,
|
|
794
|
-
// then re-open the change-element popup from a clean state. The
|
|
795
|
-
// downloaded connector persists across reloads (server-side project
|
|
796
|
-
// state). Filter the popup so the listitem comes into view —
|
|
797
|
-
// `.djs-popup-search input` is the popup's own search, same selector
|
|
798
|
-
// the camunda-hub e2e tests use under
|
|
799
|
-
// e2e/cypress/e2e/bpmn/browse-market-place/.
|
|
800
780
|
const maxRetries = 4;
|
|
801
|
-
const setupModelerState = async () => {
|
|
802
|
-
const onModeler = await this.page
|
|
803
|
-
.locator('[data-test="modeler"]')
|
|
804
|
-
.waitFor({ state: 'visible', timeout: 5000 })
|
|
805
|
-
.then(() => true)
|
|
806
|
-
.catch(() => false);
|
|
807
|
-
if (!onModeler) {
|
|
808
|
-
await this.page.keyboard.press('Escape');
|
|
809
|
-
await this.page.waitForTimeout(2000);
|
|
810
|
-
const afterEscape = await this.page
|
|
811
|
-
.locator('[data-test="modeler"]')
|
|
812
|
-
.waitFor({ state: 'visible', timeout: 3000 })
|
|
813
|
-
.then(() => true)
|
|
814
|
-
.catch(() => false);
|
|
815
|
-
if (!afterEscape) {
|
|
816
|
-
await this.page.goBack();
|
|
817
|
-
await this.page.waitForTimeout(5000);
|
|
818
|
-
}
|
|
819
|
-
await this.page.reload();
|
|
820
|
-
await this.page.waitForTimeout(5000);
|
|
821
|
-
}
|
|
822
|
-
await this.clickCanvas();
|
|
823
|
-
await this.secondElement.click({ timeout: 60000 });
|
|
824
|
-
await this.clickChangeTypeButton();
|
|
825
|
-
// Wait for the change-element popup to be fully loaded.
|
|
826
|
-
await (0, test_1.expect)(this.marketPlaceButton).toBeVisible({ timeout: 60000 });
|
|
827
|
-
// Filter the change-element popup so the connector listitem comes
|
|
828
|
-
// into the rendered slice of the virtualized list.
|
|
829
|
-
const changeElementSearch = this.page.locator('.djs-popup-search input');
|
|
830
|
-
if (await changeElementSearch.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
831
|
-
await changeElementSearch.fill('Worldwide Public Holiday');
|
|
832
|
-
}
|
|
833
|
-
};
|
|
834
781
|
for (let retries = 0; retries < maxRetries; retries++) {
|
|
835
782
|
try {
|
|
836
|
-
|
|
837
|
-
|
|
783
|
+
if (retries === 2) {
|
|
784
|
+
// Re-download connector on second retry in case the first download failed
|
|
785
|
+
await this.clickMarketPlaceButton();
|
|
786
|
+
const connectorMarketplacePage = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
|
|
787
|
+
await connectorMarketplacePage.clickSearchForConnectorTextbox();
|
|
788
|
+
await connectorMarketplacePage.fillSearchForConnectorTextbox('Public Holiday Connector');
|
|
789
|
+
await (0, sleep_1.sleep)(10000);
|
|
790
|
+
await connectorMarketplacePage.downloadConnectorToProject();
|
|
791
|
+
await this.clickCanvas();
|
|
792
|
+
await this.secondElement.click({ timeout: 60000 });
|
|
793
|
+
await this.clickChangeTypeButton();
|
|
794
|
+
}
|
|
795
|
+
// Filter the virtualized change-element popup so the option scrolls into view
|
|
796
|
+
const changeElementSearch = this.page.locator('.djs-popup-search input');
|
|
797
|
+
if (await changeElementSearch
|
|
798
|
+
.isVisible({ timeout: 5000 })
|
|
799
|
+
.catch(() => false)) {
|
|
800
|
+
await changeElementSearch.pressSequentially('Worldwide Public Holiday', {
|
|
801
|
+
delay: 50,
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
await this.publicHolidayConnectorOption.waitFor({
|
|
805
|
+
state: 'visible',
|
|
806
|
+
timeout: 60000,
|
|
807
|
+
});
|
|
808
|
+
await this.publicHolidayConnectorOption.click({ timeout: 30000 });
|
|
838
809
|
return;
|
|
839
810
|
}
|
|
840
811
|
catch (error) {
|
|
841
812
|
console.error(`Click attempt ${retries + 1} failed: ${error}`);
|
|
842
813
|
if (retries >= maxRetries - 1)
|
|
843
814
|
break;
|
|
844
|
-
const onModeler = await this.page
|
|
845
|
-
.locator('[data-test="modeler"]')
|
|
846
|
-
.waitFor({ state: 'visible', timeout: 3000 })
|
|
847
|
-
.then(() => true)
|
|
848
|
-
.catch(() => false);
|
|
849
|
-
if (!onModeler) {
|
|
850
|
-
await this.page.goBack();
|
|
851
|
-
await this.page.waitForTimeout(3000);
|
|
852
|
-
}
|
|
853
815
|
await this.page.reload();
|
|
854
|
-
await
|
|
816
|
+
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
817
|
+
await this.clickCanvas();
|
|
818
|
+
await this.secondElement.click({ timeout: 60000 });
|
|
819
|
+
await this.clickChangeTypeButton();
|
|
855
820
|
}
|
|
856
821
|
}
|
|
857
|
-
throw new Error(`Failed to click the
|
|
822
|
+
throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
|
|
858
823
|
}
|
|
859
824
|
async clickPublicHolidayYearOption() {
|
|
860
825
|
await this.publicHolidayYearOption.click({ timeout: 60000 });
|
|
@@ -6,6 +6,7 @@ declare class ConnectorMarketplacePage {
|
|
|
6
6
|
readonly snackbar: Locator;
|
|
7
7
|
readonly closeButton: Locator;
|
|
8
8
|
readonly replaceResourceButton: Locator;
|
|
9
|
+
readonly addToProjectButton: Locator;
|
|
9
10
|
readonly cancelButton: Locator;
|
|
10
11
|
constructor(page: Page);
|
|
11
12
|
clickSearchForConnectorTextbox(): Promise<void>;
|
|
@@ -8,6 +8,7 @@ class ConnectorMarketplacePage {
|
|
|
8
8
|
snackbar;
|
|
9
9
|
closeButton;
|
|
10
10
|
replaceResourceButton;
|
|
11
|
+
addToProjectButton;
|
|
11
12
|
cancelButton;
|
|
12
13
|
constructor(page) {
|
|
13
14
|
this.page = page;
|
|
@@ -20,6 +21,9 @@ class ConnectorMarketplacePage {
|
|
|
20
21
|
this.replaceResourceButton = page.getByRole('button', {
|
|
21
22
|
name: 'Replace resource',
|
|
22
23
|
});
|
|
24
|
+
this.addToProjectButton = page.getByRole('button', {
|
|
25
|
+
name: 'Add to project',
|
|
26
|
+
});
|
|
23
27
|
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
|
|
24
28
|
}
|
|
25
29
|
async clickSearchForConnectorTextbox() {
|
|
@@ -42,14 +46,30 @@ class ConnectorMarketplacePage {
|
|
|
42
46
|
}
|
|
43
47
|
async downloadConnectorToProject() {
|
|
44
48
|
await this.clickDownloadToProjectButton();
|
|
49
|
+
let imported = false;
|
|
45
50
|
try {
|
|
46
51
|
await Promise.race([
|
|
52
|
+
this.addToProjectButton.click({ timeout: 20000 }),
|
|
47
53
|
this.replaceResourceButton.click({ timeout: 20000 }),
|
|
48
|
-
this.cancelButton.click({ timeout: 20000 }),
|
|
49
54
|
]);
|
|
55
|
+
imported = true;
|
|
50
56
|
}
|
|
51
57
|
catch (e) {
|
|
52
|
-
|
|
58
|
+
if (await this.cancelButton.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
59
|
+
await this.cancelButton.click({ timeout: 10000 });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// After a successful import, wait for the snackbar (confirms the connector
|
|
63
|
+
// template was received by the modeler) then close the marketplace panel so
|
|
64
|
+
// the diagram canvas is unblocked before the caller tries to select the
|
|
65
|
+
// newly installed connector.
|
|
66
|
+
if (imported) {
|
|
67
|
+
await this.snackbar
|
|
68
|
+
.waitFor({ state: 'visible', timeout: 60000 })
|
|
69
|
+
.catch(() => { });
|
|
70
|
+
if (await this.closeButton.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
71
|
+
await this.closeButton.click({ timeout: 10000 });
|
|
72
|
+
}
|
|
53
73
|
}
|
|
54
74
|
}
|
|
55
75
|
}
|
|
@@ -767,38 +767,29 @@ class ModelerCreatePage {
|
|
|
767
767
|
const maxRetries = 4;
|
|
768
768
|
for (let retries = 0; retries < maxRetries; retries++) {
|
|
769
769
|
try {
|
|
770
|
-
if (retries
|
|
771
|
-
//
|
|
772
|
-
// panel before clicking. Without this we burn an attempt every
|
|
773
|
-
// time the panel is still loading after download.
|
|
774
|
-
await this.publicHolidayConnectorOption.waitFor({
|
|
775
|
-
state: 'visible',
|
|
776
|
-
timeout: 60000,
|
|
777
|
-
});
|
|
778
|
-
await this.publicHolidayConnectorOption.click({ timeout: 30000 });
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
770
|
+
if (retries === 2) {
|
|
771
|
+
// Re-download connector on second retry in case the first download failed
|
|
781
772
|
await this.clickMarketPlaceButton();
|
|
782
773
|
const connectorMarketplacePage = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
|
|
783
774
|
await connectorMarketplacePage.clickSearchForConnectorTextbox();
|
|
784
775
|
await connectorMarketplacePage.fillSearchForConnectorTextbox('Public Holiday Connector');
|
|
785
776
|
await (0, sleep_1.sleep)(10000);
|
|
786
777
|
await connectorMarketplacePage.downloadConnectorToProject();
|
|
787
|
-
await this.publicHolidayConnectorOption.waitFor({
|
|
788
|
-
state: 'visible',
|
|
789
|
-
timeout: 120000,
|
|
790
|
-
});
|
|
791
|
-
await this.publicHolidayConnectorOption.click({ timeout: 30000 });
|
|
792
778
|
}
|
|
779
|
+
// Always open the change-type popup before trying to click the option
|
|
780
|
+
await this.clickCanvas();
|
|
781
|
+
await this.secondElement.click({ timeout: 60000 });
|
|
782
|
+
await this.clickChangeTypeButton();
|
|
783
|
+
await (0, test_1.expect)(this.marketPlaceButton).toBeVisible({ timeout: 60000 });
|
|
784
|
+
await this.publicHolidayConnectorOption.click({ timeout: 120000 });
|
|
793
785
|
return;
|
|
794
786
|
}
|
|
795
787
|
catch (error) {
|
|
796
788
|
console.error(`Click attempt ${retries + 1} failed: ${error}`);
|
|
789
|
+
if (retries >= maxRetries - 1)
|
|
790
|
+
break;
|
|
797
791
|
await this.page.reload();
|
|
798
792
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
799
|
-
await this.clickCanvas();
|
|
800
|
-
await this.secondElement.click({ timeout: 60000 });
|
|
801
|
-
await this.clickChangeTypeButton();
|
|
802
793
|
}
|
|
803
794
|
}
|
|
804
795
|
throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
|