test: Cypress | CI Stabilize (Skipped tests fixes) + Cypress upgrade to v13.0.0 (#26583)
## Description - The PR does below: - TogglePropertyState() revert - BinaryDT_Spec.ts - unskip - AssertExistingToggleState() improved to handle the UI field names - Unskip TableV1/TableFilter2_1_Spec.ts & TableV2Filter2_1_Spec - Fixed Apps/CommunityIssues_Spec.ts - Added ClientSide Search validation - /Binding/Button_Text_WithRecaptcha_spec.js - fix & unskip - GitSync/DeleteBranch_spec.js - fix & unskip - TableV2/TableV2_Widget_Add_button_spec.js - flaky fix - Cypress upgrade from v12.17.4 to v13.0.0 #### Type of change - Script fix (non-breaking change which fixes an issue) ## Testing #### How Has This Been Tested? - [X] Cypress CI runs ## Checklist: #### QA activity: - [X] Added `Test Plan Approved` label after Cypress tests were reviewed --------- Co-authored-by: Saroj <43822041+sarojsarab@users.noreply.github.com>
This commit is contained in:
parent
7dcff0d774
commit
45ca5c4890
|
|
@ -6,7 +6,6 @@ export default defineConfig({
|
|||
requestTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
videoUploadOnPasses: false,
|
||||
videoCompression: false,
|
||||
numTestsKeptInMemory: 5,
|
||||
experimentalMemoryManagement: true,
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
|
||||
//deploy the app and verify the table data
|
||||
|
|
@ -176,7 +176,7 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
|
||||
//deploy the app and verify the table data
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
entityExplorer,
|
||||
locators,
|
||||
assertHelper,
|
||||
draggableWidgets,
|
||||
} from "../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("AForce - Community Issues page validations", function () {
|
||||
|
|
@ -66,7 +67,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
|
||||
it("2. Validate table navigation with Server Side pagination enabled with Default selected row", () => {
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
agHelper.AssertExistingToggleState("serversidepagination", "true");
|
||||
agHelper.AssertExistingToggleState("Server side pagination", "true");
|
||||
|
||||
propPane
|
||||
.ValidatePropertyFieldValue("Default selected row", "0")
|
||||
|
|
@ -139,7 +140,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
//propPane.EnterJSContext("Default search text", "Bug", false);
|
||||
propPane.TypeTextIntoField("Default search text", "Bug");
|
||||
deployMode.DeployApp();
|
||||
table.AssertSearchText("Bug", 2);
|
||||
table.AssertSearchText("Bug");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.NavigateBacktoEditor();
|
||||
|
|
@ -149,7 +150,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
propPane.TypeTextIntoField("Default search text", "Quest", true, false);
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.AssertSearchText("Quest", 2);
|
||||
table.AssertSearchText("Quest");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
|
|
@ -168,42 +169,75 @@ describe("AForce - Community Issues page validations", function () {
|
|||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
|
||||
it.skip("6. Validate Search table with Client Side Search enabled & disabled", () => {
|
||||
it("6. Validate Search table with Client Side Search enabled & disabled & onSearchTextChanged is set", () => {
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
agHelper.AssertExistingToggleState("clientsidesearch", "true");
|
||||
agHelper.AssertExistingToggleState("Client side search", "true");
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Bug", 2);
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.SearchTable("Best");
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("Quest");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "Off");
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Bug", 2);
|
||||
table.WaitForTableEmpty("v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.SearchTable("Bug");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //Since onSearchTextChanged is set , Search is queried for Search text with Client side search On or Off
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("Quest");
|
||||
table.WaitForTableEmpty("v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
//Remove onSearchTextChanged & test
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "On");
|
||||
propPane.EnterJSContext("onSearchTextChanged", "");
|
||||
propPane.ToggleJSMode("onSearchTextChanged", false);
|
||||
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Xano");
|
||||
table.WaitForTableEmpty("v2"); //Since Xano is present in 2nd page & Client side search is On
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("SSL");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //as 1st page has SSL entries
|
||||
table.ResetSearch();
|
||||
|
||||
//if the client side search is off, and there is no text in onSearchTextChanged, we still go ahead with client side search. this is a known limitation deployMode.NavigateBacktoEditor();
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "Off");
|
||||
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Xano");
|
||||
table.WaitForTableEmpty("v2"); //Since Xano is present in 2nd page & Client side search is Off
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("SSL");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //as 1st page has SSL entries
|
||||
table.ResetSearch();
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
it("7. Validate Filter table", () => {
|
||||
|
|
@ -293,7 +327,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
agHelper.ClickButton("Confirm");
|
||||
agHelper.AssertElementAbsence(locators._toastMsg); //Making sure internal api doesnt throw error
|
||||
agHelper.Sleep(3000);
|
||||
table.SearchTable("Suggestion", 2);
|
||||
table.SearchTable("Suggestion");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
|
||||
table.ReadTableRowColumnData(0, 0, "v2", 4000).then((cellData) => {
|
||||
|
|
|
|||
|
|
@ -23,48 +23,6 @@ describe(
|
|||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v3");
|
||||
});
|
||||
|
||||
//This test to be enabled once the product bug is fixed
|
||||
it.skip("Validate the Button binding with Text Widget with Recaptcha Token with invalid key before using valid key", function () {
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.testCodeMirrorLast(testdata.invalidKey);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).to.be.empty;
|
||||
});
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
|
||||
cy.get(".t--property-control-googlerecaptchaversion .bp3-popover-target")
|
||||
.last()
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--dropdown-option:contains('reCAPTCHA v2')").click({
|
||||
force: true,
|
||||
});
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--toast-action span").should("have.text", testdata.errorMsg);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.wait(3000);
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).to.be.empty;
|
||||
});
|
||||
});
|
||||
|
||||
it("2. Validate the Button binding with Text Widget with Recaptcha Token with v2Key & upward compatibilty doesnt work", function () {
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.propPane.UpdatePropertyFieldValue(
|
||||
|
|
@ -117,48 +75,22 @@ describe(
|
|||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v2");
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.AssertContains("Google Re-Captcha token generation failed!"); //toast doesnt come when run in CI!
|
||||
_.agHelper.AssertContains("Google Re-Captcha token generation failed!");
|
||||
});
|
||||
|
||||
//This test to be enabled once the product bug is fixed
|
||||
it.skip("Validate the Button binding with Text Widget with Recaptcha Token with invalid key", function () {
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.testCodeMirrorLast(testdata.invalidKey);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).not.to.be.empty;
|
||||
});
|
||||
it("4. Validate the Button binding with Text Widget with Recaptcha Token with invalid key (after using valid key)", function () {
|
||||
_.propPane.DeleteWidgetFromPropertyPane("Text1");
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
|
||||
cy.get(".t--property-control-googlerecaptchaversion .bp3-popover-target")
|
||||
.last()
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--dropdown-option:contains('reCAPTCHA v2')").click({
|
||||
force: true,
|
||||
});
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.wait(3000);
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).not.to.be.empty;
|
||||
});
|
||||
_.propPane.UpdatePropertyFieldValue(
|
||||
"Google reCAPTCHA key",
|
||||
testdata.invalidKey,
|
||||
);
|
||||
_.agHelper.ClickButton("Submit"); //for version 3
|
||||
_.agHelper.WaitUntilToastDisappear(testdata.errorMsg);
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v2");
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.WaitUntilToastDisappear(testdata.errorMsg);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -43,34 +43,34 @@ describe("Validate basic binding of Input widget to Input widget", () => {
|
|||
});
|
||||
});
|
||||
|
||||
//Till bug fixed
|
||||
it.skip("2. Validation of default displayed in Select widget based on row selected + Bug 12531", function () {
|
||||
table.SelectTableRow(1);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#2");
|
||||
});
|
||||
// //Till bug fixed
|
||||
// it.skip("2. Validation of default displayed in Select widget based on row selected + Bug 12531", function () {
|
||||
// table.SelectTableRow(1);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#2");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(0);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#1");
|
||||
});
|
||||
// table.SelectTableRow(0);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#1");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(2);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("Select option");
|
||||
});
|
||||
// table.SelectTableRow(2);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("Select option");
|
||||
// });
|
||||
|
||||
//Change select value now - failing here!
|
||||
agHelper.SelectDropDown("#1");
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#1");
|
||||
});
|
||||
// //Change select value now - failing here!
|
||||
// agHelper.SelectDropDown("#1");
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#1");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(2, 0, false); //Deselecting here!
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("Select option");
|
||||
});
|
||||
});
|
||||
// table.SelectTableRow(2, 0, false); //Deselecting here!
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("Select option");
|
||||
// });
|
||||
// });
|
||||
|
||||
it("3. Verify Selecting the already selected row deselects it", () => {
|
||||
table.SelectTableRow(0); //select here
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ describe("Bug 9334: The Select widget value is sent as null when user switches b
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
table.WaitUntilTableLoad();
|
||||
|
||||
|
|
@ -52,10 +52,11 @@ describe("Bug 9334: The Select widget value is sent as null when user switches b
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
table.WaitUntilTableLoad();
|
||||
});
|
||||
|
||||
it("2. Navigate & Assert toast", () => {
|
||||
//Navigating between CRUD (Page3) & EmptyPage (Page2):
|
||||
entityExplorer.SelectEntityByName("Page1");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import adminsSettings from "../../../../locators/AdminsSettings";
|
||||
|
||||
describe("Email verification", () => {
|
||||
it("Shows the email verification pending page correctly", () => {
|
||||
it("1. Shows the email verification pending page correctly", () => {
|
||||
cy.LogOut();
|
||||
cy.visit("/user/verificationPending?email=test@appsmith.com");
|
||||
cy.wait(1000);
|
||||
|
|
@ -9,7 +9,8 @@ describe("Email verification", () => {
|
|||
"VerificationPendingScreen",
|
||||
);
|
||||
});
|
||||
it("Verification error pages", () => {
|
||||
|
||||
it("2. Verification error pages", () => {
|
||||
const errorCode = {
|
||||
ALREADY_VERIFIED: "AE-EMV-4095",
|
||||
EXPIRED: "AE-EMV-4096",
|
||||
|
|
@ -45,7 +46,9 @@ describe("Email verification", () => {
|
|||
"Unknown error",
|
||||
);
|
||||
});
|
||||
it.skip("Email verification settings test", () => {
|
||||
|
||||
//Skipping since Server restart taking a lot of time
|
||||
it.skip("3. Email verification settings test", () => {
|
||||
cy.LogOut();
|
||||
cy.LoginFromAPI(Cypress.env("USERNAME"), Cypress.env("PASSWORD"));
|
||||
cy.get(".admin-settings-menu-option").should("be.visible");
|
||||
|
|
@ -54,11 +57,11 @@ describe("Email verification", () => {
|
|||
cy.wait("@getEnvVariables");
|
||||
cy.get(adminsSettings.authenticationTab).click();
|
||||
cy.get(adminsSettings.formloginButton).click();
|
||||
cy.pause();
|
||||
//cy.pause();
|
||||
// Assert verification is disabled
|
||||
cy.get(adminsSettings.enableEmailVerificationInput).should("be.disabled");
|
||||
// Assert callout
|
||||
cy.get(adminsSettings.adminSettingsCallout).should("be.visible");
|
||||
//cy.get(adminsSettings.adminSettingsCallout).should("be.visible");
|
||||
// go to email settings
|
||||
cy.get(adminsSettings.emailTab).click();
|
||||
// add email settings
|
||||
|
|
@ -67,8 +70,11 @@ describe("Email verification", () => {
|
|||
});
|
||||
// save
|
||||
cy.get(adminsSettings.saveButton).click();
|
||||
|
||||
cy.waitForServerRestart();
|
||||
|
||||
cy.waitUntil(() =>
|
||||
cy.contains("General", { timeout: 180000 }).should("be.visible"),
|
||||
cy.contains("General", { timeout: 210000 }).should("be.visible"),
|
||||
).then(() => {
|
||||
cy.wait("@getEnvVariables");
|
||||
cy.get(adminsSettings.authenticationTab).click();
|
||||
|
|
@ -92,6 +98,8 @@ describe("Email verification", () => {
|
|||
cy.get(adminsSettings.emailTab).click();
|
||||
// remove email settings
|
||||
cy.get(adminsSettings.saveButton).click();
|
||||
cy.waitForServerRestart();
|
||||
|
||||
cy.waitUntil(() =>
|
||||
cy.contains("General", { timeout: 180000 }).should("be.visible"),
|
||||
).then(() => {
|
||||
|
|
|
|||
|
|
@ -1,52 +1,44 @@
|
|||
import homePage from "../../../../../locators/HomePage";
|
||||
import gitSyncLocators from "../../../../../locators/gitSyncLocators";
|
||||
import * as _ from "../../../../../support/Objects/ObjectsCore";
|
||||
|
||||
import {
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
homePage,
|
||||
gitSync,
|
||||
} from "../../../../../support/Objects/ObjectsCore";
|
||||
|
||||
let repoName, branchName;
|
||||
// skipping this test as it gets stuck in CI, need to triage
|
||||
describe.skip("Delete branch flow", () => {
|
||||
describe("Delete branch flow", () => {
|
||||
it("1. Connect app to git, create new branch and delete it", () => {
|
||||
// create git repo and connect app to git
|
||||
_.gitSync.CreateNConnectToGit();
|
||||
gitSync.CreateNConnectToGit();
|
||||
cy.get("@gitRepoName").then((repName) => {
|
||||
repoName = repName;
|
||||
});
|
||||
_.gitSync.CreateGitBranch();
|
||||
gitSync.CreateGitBranch();
|
||||
//cy.createGitBranch(branchName);
|
||||
cy.wait(1000);
|
||||
// verify can not delete the checked out branch
|
||||
cy.get(gitSyncLocators.branchButton).click();
|
||||
cy.get(gitSyncLocators.branchListItem)
|
||||
.eq(1)
|
||||
.trigger("mouseenter")
|
||||
.within(() => {
|
||||
cy.get(gitSyncLocators.gitBranchContextMenu).click();
|
||||
cy.get(gitSyncLocators.gitBranchDelete).click();
|
||||
});
|
||||
DeleteBranchFromUI(1);
|
||||
cy.get("@gitbranchName").then((branName) => {
|
||||
branchName = branName;
|
||||
cy.get(homePage.toastMessage).should(
|
||||
"contain",
|
||||
`Cannot delete checked out branch. Please check out other branch before deleting ${branchName}.`,
|
||||
);
|
||||
cy.get(gitSyncLocators.closeBranchList).click();
|
||||
cy.get(gitSyncLocators.closeBranchList).click({ force: true });
|
||||
// switch to master and delete new branch created
|
||||
cy.switchGitBranch("master");
|
||||
cy.wait(2000);
|
||||
cy.get(gitSyncLocators.branchButton).click();
|
||||
cy.get(gitSyncLocators.branchListItem)
|
||||
.eq(1)
|
||||
.trigger("mouseenter")
|
||||
.within(() => {
|
||||
cy.get(gitSyncLocators.gitBranchContextMenu).click();
|
||||
cy.get(gitSyncLocators.gitBranchDelete).click();
|
||||
});
|
||||
|
||||
DeleteBranchFromUI(1);
|
||||
cy.wait("@deleteBranch").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get(gitSyncLocators.closeBranchList).click();
|
||||
cy.get(gitSyncLocators.closeBranchList).click({ force: true });
|
||||
// verify remote branch is there for the deleted local branch
|
||||
cy.wait(2000);
|
||||
cy.switchGitBranch(`origin/${branchName}`);
|
||||
|
|
@ -56,38 +48,33 @@ describe.skip("Delete branch flow", () => {
|
|||
|
||||
it("2. Create child branch, merge data from child branch, delete child branch verify the data should reflect in master ", () => {
|
||||
cy.switchGitBranch("master");
|
||||
_.gitSync.CreateGitBranch("", true);
|
||||
gitSync.CreateGitBranch("", true);
|
||||
cy.wait(1000);
|
||||
_.entityExplorer.NavigateToSwitcher("Widgets");
|
||||
entityExplorer.NavigateToSwitcher("Widgets");
|
||||
cy.dragAndDropToCanvas("checkboxwidget", { x: 100, y: 200 });
|
||||
cy.get(".t--draggable-checkboxwidget").should("exist");
|
||||
cy.wait(2000);
|
||||
cy.commitAndPush();
|
||||
cy.merge("master");
|
||||
cy.get(".t--close-git-sync-modal").click();
|
||||
gitSync.CloseGitSyncModal();
|
||||
cy.switchGitBranch("master");
|
||||
cy.wait(2000);
|
||||
cy.get(gitSyncLocators.branchButton).click();
|
||||
cy.get(gitSyncLocators.branchListItem)
|
||||
.eq(1)
|
||||
.trigger("mouseenter")
|
||||
.within(() => {
|
||||
cy.get(gitSyncLocators.gitBranchContextMenu).click();
|
||||
cy.get(gitSyncLocators.gitBranchDelete).click();
|
||||
});
|
||||
|
||||
DeleteBranchFromUI(1);
|
||||
|
||||
cy.wait("@deleteBranch").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get(gitSyncLocators.closeBranchList).click();
|
||||
cy.get(gitSyncLocators.closeBranchList).click({ force: true });
|
||||
cy.get(".t--draggable-checkboxwidget").should("be.visible");
|
||||
});
|
||||
|
||||
it("3. Create new branch, commit data in that branch , delete the branch, verify data should not reflect in master ", () => {
|
||||
_.gitSync.CreateGitBranch("", true);
|
||||
gitSync.CreateGitBranch("", true);
|
||||
cy.wait(1000);
|
||||
_.entityExplorer.NavigateToSwitcher("Widgets");
|
||||
entityExplorer.NavigateToSwitcher("Widgets");
|
||||
cy.dragAndDropToCanvas("chartwidget", { x: 210, y: 300 });
|
||||
cy.get(".t--widget-chartwidget").should("exist");
|
||||
cy.wait(2000);
|
||||
|
|
@ -95,40 +82,39 @@ describe.skip("Delete branch flow", () => {
|
|||
cy.wait(1000);
|
||||
cy.switchGitBranch("master");
|
||||
cy.wait(3000);
|
||||
cy.get(gitSyncLocators.branchButton).click();
|
||||
cy.get(gitSyncLocators.branchListItem)
|
||||
.eq(1)
|
||||
.trigger("mouseenter")
|
||||
.within(() => {
|
||||
cy.wait(1000);
|
||||
cy.get(gitSyncLocators.gitBranchContextMenu).click();
|
||||
cy.wait(1000);
|
||||
cy.get(gitSyncLocators.gitBranchDelete).click();
|
||||
});
|
||||
|
||||
DeleteBranchFromUI(1);
|
||||
|
||||
cy.wait("@deleteBranch").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get(".--widget-chartwidget").should("not.exist");
|
||||
cy.get(gitSyncLocators.closeBranchList).click({ force: true });
|
||||
});
|
||||
/*it("4. Verify Default branch deletion not allowed ", () => {
|
||||
cy.get(".t--branch-item")
|
||||
.eq(0)
|
||||
.click()
|
||||
|
||||
it("4. Verify Default branch deletion not allowed ", () => {
|
||||
agHelper.WaitUntilAllToastsDisappear();
|
||||
DeleteBranchFromUI(0);
|
||||
cy.get(gitSyncLocators.closeBranchList).click({ force: true });
|
||||
agHelper.ValidateToastMessage("Cannot delete default branch: master");
|
||||
});
|
||||
|
||||
function DeleteBranchFromUI(index = 1) {
|
||||
cy.get(gitSyncLocators.branchButton).click();
|
||||
cy.get(gitSyncLocators.branchListItem)
|
||||
.eq(index)
|
||||
.trigger("mouseenter")
|
||||
.within(() => {
|
||||
cy.get(".git-branch-more-menu").click({ force: true });
|
||||
cy.get(".t--branch-more-menu-delete").click();
|
||||
});
|
||||
cy.get(homePage.toastMessage).should(
|
||||
"contain",
|
||||
"Cannot delete default branch: master",
|
||||
);
|
||||
}); */
|
||||
.wait(1000);
|
||||
cy.get(gitSyncLocators.gitBranchContextMenu).click({ force: true });
|
||||
cy.xpath("//div[@role='menu']//span[text()='Delete']")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
}
|
||||
|
||||
after(() => {
|
||||
//clean up
|
||||
_.gitSync.DeleteTestGithubRepo(repoName);
|
||||
gitSync.DeleteTestGithubRepo(repoName);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,17 +13,18 @@ const queryLocators = require("../../../../locators/QueryEditor.json");
|
|||
|
||||
describe("MaintainContext&Focus", function () {
|
||||
before("Import the test application", () => {
|
||||
homePage.NavigateToHome();
|
||||
homePage.CreateNewWorkspace("MaintainContext&Focus", true);
|
||||
homePage.ImportApp("ContextSwitching.json");
|
||||
cy.wait("@importNewApplication").then((interception) => {
|
||||
agHelper.Sleep();
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
cy.log("isPartialImport is", isPartialImport);
|
||||
if (isPartialImport) {
|
||||
// should reconnect modal
|
||||
cy.get("body").then(($ele) => {
|
||||
if ($ele.find(reconnectDatasourceModal.SkipToAppBtn))
|
||||
agHelper.GetNClick(reconnectDatasourceModal.SkipToAppBtn, 0, true);
|
||||
else agHelper.GetNClick(homePage._importSuccessModalGotit, 0, true);
|
||||
else agHelper.ClickButton("Got it");
|
||||
agHelper.Sleep(2000);
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ describe("Theme validation usecase for multi-select widget", function () {
|
|||
appSettings.ClosePane();
|
||||
});
|
||||
|
||||
//Skipping due to mentioned bug
|
||||
it.skip("2. Publish the App and validate Font across the app + Bug 15007", function () {
|
||||
//Skipping due to mentioned bug
|
||||
deployMode.DeployApp();
|
||||
cy.get(".rc-select-selection-item > .rc-select-selection-item-content")
|
||||
.first()
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ describe("Checkbox Tests", function () {
|
|||
agHelper.AssertElementVisibility(propPane._colorPickerV2Color);
|
||||
// Verify full color picker
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "text", 0);
|
||||
propPane.TogglePropertyState("fontcolor", "On", "updateLayout", false);
|
||||
propPane.TogglePropertyState("fontcolor", "On", "");
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "color", 0);
|
||||
// Font size
|
||||
propPane.SelectPropertiesDropDown("fontsize", "L");
|
||||
|
|
@ -280,7 +280,7 @@ describe("Checkbox Tests", function () {
|
|||
);
|
||||
// Verify full color picker for accent color
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "text", 1);
|
||||
propPane.TogglePropertyState("accentcolor", "On", "updateLayout", false);
|
||||
propPane.TogglePropertyState("accentcolor", "On", "");
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "color", 1);
|
||||
|
||||
// Verify border
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ describe("Code scanner widget tests", () => {
|
|||
propPane.TogglePropertyState("Disabled", "Off");
|
||||
|
||||
//Animate loading property - JS convertible
|
||||
agHelper.AssertExistingToggleState("animateloading", "true");
|
||||
agHelper.AssertExistingToggleState("Animate loading", "true");
|
||||
propPane.EnterJSContext(
|
||||
"Animate loading",
|
||||
"{{(45>55)?false:true}}",
|
||||
|
|
@ -63,8 +63,8 @@ describe("Code scanner widget tests", () => {
|
|||
"{{(45>55)?false:true}}",
|
||||
);
|
||||
propPane.EnterJSContext("Animate loading", "", false);
|
||||
propPane.ToggleJSMode("animateloading", false);
|
||||
propPane.TogglePropertyState("animateloading", "On");
|
||||
propPane.ToggleJSMode("Animate loading", false);
|
||||
propPane.TogglePropertyState("Animate loading", "On");
|
||||
});
|
||||
|
||||
it(
|
||||
|
|
@ -135,7 +135,7 @@ describe("Code scanner widget tests", () => {
|
|||
propPane.TogglePropertyState("Disabled", "Off");
|
||||
|
||||
//Animate loading property - JS convertible
|
||||
agHelper.AssertExistingToggleState("animateloading", "true");
|
||||
agHelper.AssertExistingToggleState("Animate loading", "true");
|
||||
propPane.EnterJSContext(
|
||||
"Animate loading",
|
||||
"{{(45>55)?false:true}}",
|
||||
|
|
@ -147,7 +147,7 @@ describe("Code scanner widget tests", () => {
|
|||
"{{(45>55)?false:true}}",
|
||||
);
|
||||
propPane.EnterJSContext("Animate loading", "", false, true);
|
||||
propPane.ToggleJSMode("animateloading", false);
|
||||
propPane.ToggleJSMode("Animate loading", false);
|
||||
|
||||
// Text & tooltip properties
|
||||
agHelper.AssertElementVisibility(widgetLocators.codeScannerScanButton);
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ describe("CUrrency Input widget Tests", function () {
|
|||
agHelper.AssertElementVisibility(propPane._colorPickerV2Color);
|
||||
// Verify full color picker
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "text", 0);
|
||||
propPane.TogglePropertyState("fontcolor", "On", "updateLayout", false);
|
||||
propPane.TogglePropertyState("fontcolor", "On", "");
|
||||
agHelper.AssertAttribute(propPane._colorPickerInput, "type", "color", 0);
|
||||
// Font size
|
||||
propPane.SelectPropertiesDropDown("fontsize", "L");
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ describe("List v2 - Data Identifier property", () => {
|
|||
});
|
||||
|
||||
it("7. Widgets get displayed when PrimaryKey doesn't exist - SSP", () => {
|
||||
agHelper.AddDsl("Listv2/ListV2WithNullPrimaryKey");
|
||||
agHelper.AddDsl("Listv2/ListV2WithNullPrimaryKey");
|
||||
apiPage.CreateAndFillApi(
|
||||
"https://api.punkapi.com/v2/beers?page={{List1.pageNo}}&per_page={{List1.pageSize}}",
|
||||
|
|
|
|||
|
|
@ -218,8 +218,7 @@ describe("Verify various Table_Filter combinations", function () {
|
|||
_.table.RemoveFilterNVerify("2381224", true, false);
|
||||
});
|
||||
|
||||
//Skipping until bug closed
|
||||
it.skip("8. Verify Table Filter for changing from AND -> OR [Remove a filter] -> AND + Bug 12642", function () {
|
||||
it("8. Verify Table Filter for changing from AND -> OR [Remove a filter] -> AND + Bug 12642", function () {
|
||||
_.table.OpenNFilterTable("id", "contains", "7");
|
||||
_.table.ReadTableRowColumnData(1, 4).then(($cellData) => {
|
||||
expect($cellData).to.eq("Beef steak");
|
||||
|
|
@ -241,11 +240,7 @@ describe("Verify various Table_Filter combinations", function () {
|
|||
expect($cellData).to.eq("Tuna Salad");
|
||||
});
|
||||
|
||||
_.table.RemoveFilterNVerify("2381224", false, true, 0); //Verifies bug 12642
|
||||
|
||||
_.agHelper.GetNClick(_.table._filterOperatorDropdown);
|
||||
cy.get(_.table._dropdownText).contains("AND").click();
|
||||
_.agHelper.ClickButton("APPLY");
|
||||
_.table.RemoveFilterNVerify("7434532", false, true, 0); //Since TableV1 - revertion of operator upon removal of filter is not supported
|
||||
|
||||
_.table.ReadTableRowColumnData(0, 4).then(($cellData) => {
|
||||
expect($cellData).to.eq("Avocado Panini");
|
||||
|
|
|
|||
|
|
@ -229,8 +229,7 @@ describe("Verify various Table_Filter combinations", function () {
|
|||
table.RemoveFilterNVerify("2381224", true, false, 0, "v2");
|
||||
});
|
||||
|
||||
//Skipping until bug closed
|
||||
it.skip("8. Verify Table Filter for changing from AND -> OR [Remove a filter] -> AND + Bug 12642", function () {
|
||||
it("8. Verify Table Filter for changing from AND -> OR [Remove a filter] -> AND + Bug 12642", function () {
|
||||
table.OpenNFilterTable("id", "contains", "7");
|
||||
table.ReadTableRowColumnData(1, 4, "v2").then(($cellData) => {
|
||||
expect($cellData).to.eq("Beef steak");
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.editColumn("id");
|
||||
const color1 = "rgb(255, 0, 0)";
|
||||
cy.moveToStyleTab();
|
||||
cy.get(widgetsPage.buttonColor).click({ force: true }).clear().type(color1);
|
||||
propPane.EnterJSContext("Button color", color1);
|
||||
cy.get(widgetsPage.tableV2Btn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
|
|
@ -64,31 +64,23 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
|
||||
// Changing the color again to reproduce issue #9526
|
||||
const color2 = "rgb(255, 255, 0)";
|
||||
cy.get(widgetsPage.buttonColor)
|
||||
.click({ force: true })
|
||||
.clear()
|
||||
// following wait is required to reproduce #9526
|
||||
.wait(600)
|
||||
.type(color2);
|
||||
propPane.EnterJSContext("Button color", color2);
|
||||
|
||||
cy.get(widgetsPage.tableV2Btn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
color2,
|
||||
);
|
||||
});
|
||||
|
||||
it("3. Table widget triggeredRow property should be accessible", function () {
|
||||
); //verifying Bug #9526 - color is not reverted back to default
|
||||
//Table widget triggeredRow property should be accessible", function () {
|
||||
cy.get(commonlocators.TextInside).should("have.text", "Tobias Funke");
|
||||
});
|
||||
|
||||
it("4. Table widget triggeredRow property should be same even after sorting the table", function () {
|
||||
// Table widget triggeredRow property should be same even after sorting the table", function () {
|
||||
//sort table date on second column
|
||||
cy.get(".draggable-header ").first().click({ force: true });
|
||||
cy.wait(1000);
|
||||
cy.get(commonlocators.TextInside).should("have.text", "Tobias Funke");
|
||||
});
|
||||
|
||||
it("5. Table widget add new icon button column", function () {
|
||||
it("3. Table widget add new icon button column", function () {
|
||||
cy.get("[data-testid='t--property-pane-back-btn']").click({ force: true });
|
||||
// hide id column
|
||||
cy.makeColumnVisible("id");
|
||||
|
|
@ -123,7 +115,7 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.deleteColumn("customColumn1");
|
||||
});
|
||||
|
||||
it("6. Table widget add new menu button column", function () {
|
||||
it("4. Table widget add new menu button column", function () {
|
||||
cy.openPropertyPane("tablewidgetv2");
|
||||
// click on Add new Column.
|
||||
cy.get(".t--add-column-btn").click();
|
||||
|
|
@ -279,7 +271,7 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("7. Table widget test on button icon click, row should not get deselected", () => {
|
||||
it("5. Table widget test on button icon click, row should not get deselected", () => {
|
||||
cy.get(widgetsPage.tableV2IconBtn).last().click({ force: true });
|
||||
cy.get(commonlocators.TextInside).should("have.text", "Tobias Funke");
|
||||
//click icon button again
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ function GenerateCRUDNValidateDeployPage(
|
|||
agHelper.AssertContains("Successfully generated a page"); // Commenting this since FindQuery failure appears sometimes
|
||||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
appSettings.OpenPaneAndChangeTheme("Pacific");
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ describe("Validate Mongo CRUD with JSON Form", () => {
|
|||
agHelper.AssertContains("Successfully generated a page"); // Commenting this since FindQuery failure appears sometimes
|
||||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
|
|||
assertHelper.AssertNetworkStatus("@replaceLayoutWithCRUDPage", 201);
|
||||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
|
||||
|
|
@ -218,42 +218,43 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
|
|||
dataSources.AssertJSONFormHeader(0, 0, "productLine");
|
||||
});
|
||||
|
||||
it.skip("6. Verify Update/Delete row/Delete field data from Deploy page - on Productlines - existing record + Bug 14063", () => {
|
||||
entityExplorer.SelectEntityByName("update_form", "Widgets");
|
||||
propPane.ChangeJsonFormFieldType(
|
||||
"Text Description",
|
||||
"Multiline Text Input",
|
||||
);
|
||||
propPane.NavigateBackToPropertyPane();
|
||||
propPane.ChangeJsonFormFieldType(
|
||||
"Html Description",
|
||||
"Multiline Text Input",
|
||||
);
|
||||
propPane.NavigateBackToPropertyPane();
|
||||
deployMode.DeployApp();
|
||||
table.SelectTableRow(0, 0, false); //to make JSON form hidden
|
||||
agHelper.AssertElementAbsence(locators._jsonFormWidget);
|
||||
table.SelectTableRow(3);
|
||||
agHelper.AssertElementVisibility(locators._jsonFormWidget);
|
||||
//Open Bug 14063 - hence skipping
|
||||
// it.skip("6. Verify Update/Delete row/Delete field data from Deploy page - on Productlines - existing record + Bug 14063", () => {
|
||||
// entityExplorer.SelectEntityByName("update_form", "Widgets");
|
||||
// propPane.ChangeJsonFormFieldType(
|
||||
// "Text Description",
|
||||
// "Multiline Text Input",
|
||||
// );
|
||||
// propPane.NavigateBackToPropertyPane();
|
||||
// propPane.ChangeJsonFormFieldType(
|
||||
// "Html Description",
|
||||
// "Multiline Text Input",
|
||||
// );
|
||||
// propPane.NavigateBackToPropertyPane();
|
||||
// deployMode.DeployApp();
|
||||
// table.SelectTableRow(0, 0, false); //to make JSON form hidden
|
||||
// agHelper.AssertElementAbsence(locators._jsonFormWidget);
|
||||
// table.SelectTableRow(3);
|
||||
// agHelper.AssertElementVisibility(locators._jsonFormWidget);
|
||||
|
||||
dataSources.AssertJSONFormHeader(3, 0, "productLine");
|
||||
// dataSources.AssertJSONFormHeader(3, 0, "productLine");
|
||||
|
||||
deployMode.EnterJSONTextAreaValue(
|
||||
"Html Description",
|
||||
"The largest cruise ship is twice the length of the Washington Monument. Some cruise ships have virtual balconies.",
|
||||
);
|
||||
agHelper.ClickButton("Update"); //Update does not work, Bug 14063
|
||||
agHelper.AssertElementAbsence(locators._toastMsg); //Validating fix for Bug 14063
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
table.AssertSelectedRow(3);
|
||||
// deployMode.EnterJSONTextAreaValue(
|
||||
// "Html Description",
|
||||
// "The largest cruise ship is twice the length of the Washington Monument. Some cruise ships have virtual balconies.",
|
||||
// );
|
||||
// agHelper.ClickButton("Update"); //Update does not work, Bug 14063
|
||||
// agHelper.AssertElementAbsence(locators._toastMsg); //Validating fix for Bug 14063
|
||||
// assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
// table.AssertSelectedRow(3);
|
||||
|
||||
//validating update happened fine!
|
||||
table.ReadTableRowColumnData(3, 2, "v1", 200).then(($cellData) => {
|
||||
expect($cellData).to.eq(
|
||||
"The largest cruise ship is twice the length of the Washington Monument. Some cruise ships have virtual balconies.",
|
||||
);
|
||||
});
|
||||
});
|
||||
// //validating update happened fine!
|
||||
// table.ReadTableRowColumnData(3, 2, "v1", 200).then(($cellData) => {
|
||||
// expect($cellData).to.eq(
|
||||
// "The largest cruise ship is twice the length of the Washington Monument. Some cruise ships have virtual balconies.",
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
|
||||
// it.skip("7. Verify Add/Update/Delete from Deploy page - on Productlines - new record + Bug 14063", () => {
|
||||
// //To script aft bug fix!
|
||||
|
|
@ -323,7 +324,7 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
table.WaitUntilTableLoad();
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
table.WaitUntilTableLoad();
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ describe("Postgres Generate CRUD with JSON Form", () => {
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ describe("Validate Postgres Generate CRUD with JSON Form", () => {
|
|||
assertHelper.AssertNetworkStatus("@replaceLayoutWithCRUDPage", 201);
|
||||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
deployMode.DeployApp(locators._widgetInDeployed("tablewidget"));
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ describe("Tests fetch calls", () => {
|
|||
agHelper.AssertContains("anonymousUser", "exist");
|
||||
});
|
||||
|
||||
it.skip("3. Tests if fetch works with store value", function () {
|
||||
it("3. Tests if fetch works with store value", function () {
|
||||
entityExplorer.NavigateToSwitcher("Widgets");
|
||||
entityExplorer.DragDropWidgetNVerify("buttonwidget", 500, 200);
|
||||
entityExplorer.SelectEntityByName("Button1");
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import {
|
|||
assertHelper,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe.skip("Binary Datatype tests", function () {
|
||||
describe("Binary Datatype tests", function () {
|
||||
let dsName: any, query: string, imageNameToUpload: string;
|
||||
|
||||
before("Create DS, Importing App & setting theme", () => {
|
||||
agHelper.AddDsl("Datatypes/BinaryDTdsl");
|
||||
appSettings.OpenPaneAndChangeThemeColors(24, -37);
|
||||
appSettings.OpenPaneAndChangeThemeColors(7, -9);
|
||||
dataSources.CreateDataSource("Postgres");
|
||||
cy.get("@dsName").then(($dsName) => {
|
||||
dsName = $dsName;
|
||||
|
|
@ -378,6 +378,7 @@ describe.skip("Binary Datatype tests", function () {
|
|||
entityExplorer.ExpandCollapseEntity("Queries/JS", false);
|
||||
});
|
||||
|
||||
//Since query delete & Postgress DS delete is covered in other specs, commenting below code
|
||||
// after(
|
||||
// "Validate Drop of the Newly Created - binarytype - Table & Verify Deletion of all created queries",
|
||||
// () => {
|
||||
|
|
|
|||
|
|
@ -4,14 +4,12 @@ import {
|
|||
locators,
|
||||
agHelper,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
const datasource = require("../../../../locators/DatasourcesEditor.json");
|
||||
import datasource from "../../../../locators/DatasourcesEditor.json";
|
||||
|
||||
describe(
|
||||
"excludeForAirgap",
|
||||
"Google Sheets datasource row objects placeholder",
|
||||
function () {
|
||||
let queryName;
|
||||
let datasourceName;
|
||||
let pluginName = "Google Sheets";
|
||||
let placeholderText =
|
||||
'{\n "name": {{nameInput.text}},\n "dob": {{dobPicker.formattedDate}},\n "gender": {{genderSelect.selectedOptionValue}} \n}';
|
||||
|
|
@ -54,6 +52,28 @@ describe(
|
|||
//});
|
||||
});
|
||||
|
||||
it("1. Verify GSheets dropdown options", function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreatePlugIn("Google Sheets");
|
||||
VerifyFunctionDropdown([
|
||||
"Read / Write / Delete | Selected google sheets",
|
||||
"Read / Write / Delete | All google sheets",
|
||||
"Read / Write | All google sheets",
|
||||
"Read | All google sheets",
|
||||
]);
|
||||
dataSources.SaveDSFromDialog(false);
|
||||
});
|
||||
|
||||
function VerifyFunctionDropdown(scopeOptions: string[]) {
|
||||
agHelper.GetNClick(dataSources._gsScopeDropdown);
|
||||
cy.get(dataSources._gsScopeOptions).then(function ($ele) {
|
||||
expect($ele.eq(0).text()).to.be.oneOf(scopeOptions);
|
||||
expect($ele.eq(1).text()).to.be.oneOf(scopeOptions);
|
||||
expect($ele.eq(2).text()).to.be.oneOf(scopeOptions);
|
||||
});
|
||||
agHelper.GetNClick(dataSources._gsScopeDropdown);
|
||||
}
|
||||
|
||||
it("2. Bug # 25004 - Verify Google Sheets documentation opens", function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreatePlugIn(pluginName);
|
||||
|
|
|
|||
|
|
@ -862,7 +862,7 @@ describe("Validate Mongo Query Pane Validations", () => {
|
|||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
deployMode.DeployApp();
|
||||
|
||||
//Validating loaded table
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
import { agHelper, dataSources } from "../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe(
|
||||
"excludeForAirgap",
|
||||
"Google Sheets datasource test cases",
|
||||
function () {
|
||||
it("1. Create Google Sheets datasource", function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreatePlugIn("Google Sheets");
|
||||
VerifyFunctionDropdown([
|
||||
"Read / Write / Delete | Selected google sheets",
|
||||
"Read / Write / Delete | All google sheets",
|
||||
"Read / Write | All google sheets",
|
||||
"Read | All google sheets",
|
||||
]);
|
||||
dataSources.SaveDSFromDialog(false);
|
||||
});
|
||||
|
||||
function VerifyFunctionDropdown(scopeOptions: string[]) {
|
||||
agHelper.GetNClick(dataSources._gsScopeDropdown);
|
||||
cy.get(dataSources._gsScopeOptions).then(function ($ele) {
|
||||
expect($ele.eq(0).text()).to.be.oneOf(scopeOptions);
|
||||
expect($ele.eq(1).text()).to.be.oneOf(scopeOptions);
|
||||
expect($ele.eq(2).text()).to.be.oneOf(scopeOptions);
|
||||
});
|
||||
agHelper.GetNClick(dataSources._gsScopeDropdown);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
# To run only limited tests - give the spec names in below format:
|
||||
cypress/e2e/Regression/ClientSide/Widgets/Checkbox/CheckBoxGroupTest.ts
|
||||
cypress/e2e/Regression/ClientSide/Templates/Fork_Template_spec.js
|
||||
|
||||
|
||||
# For running all specs - uncomment below:
|
||||
# cypress/e2e/**/**/*
|
||||
#cypress/e2e/**/**/*
|
||||
|
||||
#ci-test-limit uses this file to run minimum of specs. Do not run entire suite with this command.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
"@typescript-eslint/parser": "^5.25.0",
|
||||
"chalk": "^4.1.1",
|
||||
"cy-verify-downloads": "^0.0.5",
|
||||
"cypress": "^12.17.4",
|
||||
"cypress": "^13.0.0",
|
||||
"cypress-file-upload": "^4.1.1",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-log-to-output": "^1.1.2",
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ Cypress.Commands.add("waitForServerRestart", () => {
|
|||
// cy.waitUntil(() => !Cypress.$(adminSettings.restartNotice).length, {
|
||||
// timeout: 180000,
|
||||
// });
|
||||
cy.get(adminSettings.restartNotice, { timeout: 210000 }).should("not.exist");
|
||||
cy.get(adminSettings.restartNotice, { timeout: 240000 }).should("not.exist");
|
||||
cy.window().then((win) => {
|
||||
win.location.reload();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -890,19 +890,11 @@ export class AggregateHelper extends ReusableHelper {
|
|||
propertyName: string,
|
||||
toggle: "true" | "false",
|
||||
) {
|
||||
let locator;
|
||||
if (propertyName.startsWith("//")) {
|
||||
locator = cy.xpath(propertyName);
|
||||
locator.should("have.attr", toggle);
|
||||
} else if (propertyName.includes(" ")) {
|
||||
locator = cy.get(propertyName);
|
||||
locator.should("have.attr", toggle);
|
||||
} else {
|
||||
locator = cy.xpath(this.locator._propertyToggleValue(propertyName));
|
||||
locator.invoke("attr", "data-checked").then((classes) => {
|
||||
this.GetElement(this.locator._propertyToggleValue(propertyName))
|
||||
.invoke("attr", "data-checked")
|
||||
.then((classes) => {
|
||||
expect(classes).includes(toggle);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public AssertExistingCheckedState(selector: string, toggle = "true") {
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ export class DataSources {
|
|||
).click();
|
||||
this.agHelper.GetNClick(this._generatePageBtn);
|
||||
this.assertHelper.AssertNetworkStatus("@replaceLayoutWithCRUDPage", 201);
|
||||
this.agHelper.GetNClick(this.locator._visibleTextSpan("Got it"));
|
||||
this.agHelper.ClickButton("Got it");
|
||||
}
|
||||
|
||||
public GeneratePageWithMockDB() {
|
||||
|
|
@ -303,7 +303,7 @@ export class DataSources {
|
|||
this.agHelper.GetNClickByContains(this._dropdownOption, "public.users");
|
||||
this.agHelper.GetNClick(this._generatePageBtn);
|
||||
this.assertHelper.AssertNetworkStatus("@replaceLayoutWithCRUDPage", 201);
|
||||
this.agHelper.GetNClick(this.locator._visibleTextSpan("Got it"));
|
||||
this.agHelper.ClickButton("Got it");
|
||||
}
|
||||
|
||||
public StartDataSourceRoutes() {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ export class HomePage {
|
|||
private _uploadFile = "//div/form/input";
|
||||
private _importSuccessModal = ".t--import-app-success-modal";
|
||||
private _forkModal = ".fork-modal";
|
||||
private _importSuccessModalGotit = ".t--import-success-modal-got-it";
|
||||
private _appCard = (applicationName: string) =>
|
||||
"//span[text()='" +
|
||||
applicationName +
|
||||
|
|
@ -585,7 +584,7 @@ export class HomePage {
|
|||
this.agHelper.AssertElementVisibility(
|
||||
this.locator._visibleTextSpan("Your application is ready to use."),
|
||||
);
|
||||
this.agHelper.GetNClick(this._importSuccessModalGotit, 0, true);
|
||||
this.agHelper.ClickButton("Got it");
|
||||
}
|
||||
|
||||
public AssertImportToast(timeout = 5000) {
|
||||
|
|
|
|||
|
|
@ -248,7 +248,6 @@ export class PropertyPane {
|
|||
propertyName: string,
|
||||
toggle: "On" | "Off" = "On",
|
||||
networkCall = "updateLayout",
|
||||
toValidateNetworkCall = true,
|
||||
) {
|
||||
if (toggle == "On") {
|
||||
this.agHelper
|
||||
|
|
@ -262,9 +261,7 @@ export class PropertyPane {
|
|||
.should("not.be.checked");
|
||||
}
|
||||
this.agHelper.AssertAutoSave();
|
||||
if (toValidateNetworkCall) {
|
||||
networkCall && this.assertHelper.AssertNetworkStatus(networkCall);
|
||||
}
|
||||
networkCall && this.assertHelper.AssertNetworkStatus(networkCall);
|
||||
}
|
||||
|
||||
public MoveToTab(tab: "Content" | "Style") {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export class Table {
|
|||
_liCurrentSelectedPage =
|
||||
"//div[@type='LIST_WIDGET']//ul[contains(@class, 'rc-pagination')]/li[contains(@class, 'rc-pagination-item-active')]/a";
|
||||
private _tr = ".tbody .tr";
|
||||
private _searchText = "input[type='search']";
|
||||
private _searchTableInput = "input[type='search'][placeholder='Search...']";
|
||||
_searchBoxCross =
|
||||
"//div[contains(@class, 't--search-input')]/following-sibling::div";
|
||||
_addIcon = "button .bp3-icon-add";
|
||||
|
|
@ -248,15 +248,12 @@ export class Table {
|
|||
}
|
||||
|
||||
public WaitForTableEmpty(tableVersion: "v1" | "v2" = "v1") {
|
||||
cy.waitUntil(() => cy.get(this._tableEmptyColumnData(tableVersion)), {
|
||||
errorMsg: "Table is populated when not expected",
|
||||
timeout: 10000,
|
||||
interval: 2000,
|
||||
}).then(($children) => {
|
||||
cy.wrap($children).children().should("have.length", 0); //or below
|
||||
//expect($children).to.have.lengthOf(0)
|
||||
this.agHelper.Sleep(500);
|
||||
});
|
||||
this.agHelper
|
||||
.GetElement(this._tableEmptyColumnData(tableVersion))
|
||||
.children()
|
||||
.should("have.length", 0); //or below
|
||||
//expect($children).to.have.lengthOf(0)
|
||||
this.agHelper.Sleep(500);
|
||||
}
|
||||
|
||||
public AssertTableHeaderOrder(expectedOrder: string) {
|
||||
|
|
@ -446,11 +443,11 @@ export class Table {
|
|||
}
|
||||
|
||||
public AssertSearchText(searchTxt: string, index = 0) {
|
||||
cy.get(this._searchText).eq(index).should("have.value", searchTxt);
|
||||
cy.get(this._searchTableInput).eq(index).should("have.value", searchTxt);
|
||||
}
|
||||
|
||||
public SearchTable(searchTxt: string, index = 0) {
|
||||
cy.get(this._searchText).eq(index).type(searchTxt);
|
||||
this.agHelper.TypeText(this._searchTableInput, searchTxt, index);
|
||||
}
|
||||
|
||||
public ResetSearch() {
|
||||
|
|
|
|||
|
|
@ -1,23 +1,22 @@
|
|||
{
|
||||
"baseUrl": "http://localhost/",
|
||||
"defaultCommandTimeout": 20000,
|
||||
"requestTimeout": 21000,
|
||||
"baseUrl": "http://localhost/",
|
||||
"defaultCommandTimeout": 20000,
|
||||
"requestTimeout": 21000,
|
||||
"responseTimeout": 20000,
|
||||
"pageLoadTimeout": 30000,
|
||||
"videoUploadOnPasses": false,
|
||||
"pageLoadTimeout": 30000,
|
||||
"videoCompression": false,
|
||||
"numTestsKeptInMemory": 10,
|
||||
"reporterOptions": {
|
||||
"reportDir": "results",
|
||||
"overwrite": false,
|
||||
"html": true,
|
||||
"json": false
|
||||
},
|
||||
"chromeWebSecurity": false,
|
||||
"viewportHeight": 1100,
|
||||
"viewportWidth": 1400,
|
||||
"retries": {
|
||||
"runMode": 0,
|
||||
"openMode": 0
|
||||
}
|
||||
"reporterOptions": {
|
||||
"reportDir": "results",
|
||||
"overwrite": false,
|
||||
"html": true,
|
||||
"json": false
|
||||
},
|
||||
"chromeWebSecurity": false,
|
||||
"viewportHeight": 1100,
|
||||
"viewportWidth": 1400,
|
||||
"retries": {
|
||||
"runMode": 0,
|
||||
"openMode": 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ export default defineConfig({
|
|||
requestTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
videoUploadOnPasses: false,
|
||||
videoCompression: false,
|
||||
numTestsKeptInMemory: 5,
|
||||
experimentalMemoryManagement: true,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ export default defineConfig({
|
|||
requestTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
videoUploadOnPasses: false,
|
||||
numTestsKeptInMemory: 5,
|
||||
experimentalMemoryManagement: true,
|
||||
reporter: "cypress-mochawesome-reporter",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ export default defineConfig({
|
|||
requestTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
videoUploadOnPasses: false,
|
||||
videoCompression: false,
|
||||
numTestsKeptInMemory: 5,
|
||||
experimentalMemoryManagement: true,
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@
|
|||
"compression-webpack-plugin": "^10.0.0",
|
||||
"cra-bundle-analyzer": "^0.1.0",
|
||||
"cy-verify-downloads": "^0.0.5",
|
||||
"cypress": "^12.17.4",
|
||||
"cypress": "^13.0.0",
|
||||
"cypress-file-upload": "^4.1.1",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-mochawesome-reporter": "^3.5.1",
|
||||
|
|
|
|||
|
|
@ -2249,9 +2249,9 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cypress/request@npm:2.88.12":
|
||||
version: 2.88.12
|
||||
resolution: "@cypress/request@npm:2.88.12"
|
||||
"@cypress/request@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "@cypress/request@npm:3.0.0"
|
||||
dependencies:
|
||||
aws-sign2: ~0.7.0
|
||||
aws4: ^1.8.0
|
||||
|
|
@ -2271,7 +2271,7 @@ __metadata:
|
|||
tough-cookie: ^4.1.3
|
||||
tunnel-agent: ^0.6.0
|
||||
uuid: ^8.3.2
|
||||
checksum: 2c6fbf7f3127d41bffca8374beaa8cf95450495a8a077b00309ea9d94dd2a4da450a77fe038e8ad26c97cdd7c39b65c53c850f8338ce9bc2dbe23ce2e2b48329
|
||||
checksum: 8ec81075b800b84df8a616dce820a194d562a35df251da234f849344022979f3675baa0b82988843f979a488e39bc1eec6204cfe660c75ace9bf4d2951edec43
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -9962,7 +9962,7 @@ __metadata:
|
|||
craco-alias: ^2.1.1
|
||||
craco-babel-loader: ^1.0.4
|
||||
cy-verify-downloads: ^0.0.5
|
||||
cypress: ^12.17.4
|
||||
cypress: ^13.0.0
|
||||
cypress-file-upload: ^4.1.1
|
||||
cypress-image-snapshot: ^4.0.1
|
||||
cypress-log-to-output: ^1.1.2
|
||||
|
|
@ -13405,11 +13405,11 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cypress@npm:^12.17.4":
|
||||
version: 12.17.4
|
||||
resolution: "cypress@npm:12.17.4"
|
||||
"cypress@npm:^13.0.0":
|
||||
version: 13.0.0
|
||||
resolution: "cypress@npm:13.0.0"
|
||||
dependencies:
|
||||
"@cypress/request": 2.88.12
|
||||
"@cypress/request": ^3.0.0
|
||||
"@cypress/xvfb": ^1.2.4
|
||||
"@types/node": ^16.18.39
|
||||
"@types/sinonjs__fake-timers": 8.1.1
|
||||
|
|
@ -13454,7 +13454,7 @@ __metadata:
|
|||
yauzl: ^2.10.0
|
||||
bin:
|
||||
cypress: bin/cypress
|
||||
checksum: c9c79f5493b23e9c8cfb92d45d50ea9d0fae54210dde203bfa794a79436faf60108d826fe9007a7d67fddf7919802ad8f006b7ae56c5c198c75d5bc85bbc851b
|
||||
checksum: 223dddfd85dbde5e3a915e87b6cb176b99a9e5bcc24baa40cd5b9ca4a93315a95cf53c5c6ac3a6984f59be55ffc8b58b93a713c0ddcb63a5f4996229cce70329
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user