test: Add tests for git sync app and git bugs (#13394)

* Add tests for gitSync

* add test for git import bug#12749

* modified importAppfromGit method

* add test for bug #13385

* updated tests

* fixed test

Co-authored-by: Parthvi Goswami <parthvigoswami@Parthvis-MacBook-Pro.local>
This commit is contained in:
Parthvi12 2022-05-02 09:59:03 +05:30 committed by GitHub
parent 4596a12bfd
commit 2f4ca6aa98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 613 additions and 6 deletions

View File

@ -0,0 +1,29 @@
import homePage from "../../../../locators/HomePage";
import gitSyncLocators from "../../../../locators/gitSyncLocators";
describe("Git import empty repository", function() {
let repoName;
const assertConnectFailure = true;
const failureMessage =
"git import failed. \nDetails: Cannot import app from an empty repo";
it("Bug #12749 Git Import - Empty Repo NullPointerException", () => {
cy.get(homePage.homeIcon).click();
cy.get(homePage.optionsIcon)
.first()
.click();
cy.get(homePage.orgImportAppOption).click({ force: true });
cy.get(".t--import-json-card")
.next()
.click();
cy.generateUUID().then((uid) => {
repoName = uid;
cy.createTestGithubRepo(repoName);
cy.importAppFromGit(repoName, true, failureMessage);
});
cy.get(gitSyncLocators.closeGitSyncModal).click();
});
after(() => {
cy.deleteTestGithubRepo(repoName);
});
});

View File

@ -242,3 +242,46 @@ describe("Git synced app with JSObject", function() {
cy.deleteTestGithubRepo(repoName);
});
});
describe("Git sync Bug #13385", function() {
it("Bug:13385 : Unable to see application in home page after the git connect flow is aborted in middle", () => {
cy.NavigateToHome();
cy.createOrg();
cy.wait("@createOrg").then((interception) => {
const newOrganizationName = interception.response.body.data.name;
cy.CreateAppForOrg(newOrganizationName, `${newOrganizationName}app`);
cy.generateUUID().then((uid) => {
const owner = Cypress.env("TEST_GITHUB_USER_NAME");
repoName = uid;
cy.createTestGithubRepo(repoName);
// open gitSync modal
cy.get(homePage.deployPopupOptionTrigger).click();
cy.get(homePage.connectToGitBtn).click({ force: true });
cy.intercept(
{
url: "api/v1/git/connect/*",
hostname: window.location.host,
},
(req) => {
req.headers["origin"] = "Cypress";
},
);
cy.intercept("POST", "/api/v1/applications/ssh-keypair/*").as(
`generateKey-${repoName}`,
);
cy.get(gitSyncLocators.gitRepoInput).type(
`git@github.com:${owner}/${repoName}.git`,
);
// abort git flow after generating key
cy.get(gitSyncLocators.closeGitSyncModal).click();
});
// verify app is visible and open
cy.NavigateToHome();
cy.reload();
cy.wait(3000);
cy.SearchApp(`${newOrganizationName}app`);
});
});
});

View File

@ -0,0 +1,528 @@
const pages = require("../../../../locators/Pages.json");
const generatePage = require("../../../../locators/GeneratePage.json");
const explorer = require("../../../../locators/explorerlocators.json");
const apiwidget = require("../../../../locators/apiWidgetslocator.json");
const dynamicInputLocators = require("../../../../locators/DynamicInput.json");
const queryLocators = require("../../../../locators/QueryEditor.json");
const commonlocators = require("../../../../locators/commonlocators.json");
import jsActions from "../../../../locators/jsActionLocators";
import gitSyncLocators from "../../../../locators/gitSyncLocators";
import ApiEditor from "../../../../locators/ApiEditor";
import homePage from "../../../../locators/HomePage";
import datasource from "../../../../locators/DatasourcesEditor.json";
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const ee = ObjectsRegistry.EntityExplorer;
const newPage = "ApiCalls_1";
const pageName = "crudpage_1";
const tempBranch = "feat/tempBranch";
const tempBranch1 = "feat/testing";
const tempBranch0 = "test/tempBranch0";
const mainBranch = "master";
let datasourceName;
let repoName;
describe("Git sync apps", function() {
before(() => {
// cy.NavigateToHome();
// cy.createOrg();
// cy.wait("@createOrg").then((interception) => {
// const newOrganizationName = interception.response.body.data.name;
// cy.CreateAppForOrg(newOrganizationName, "gitSyncApp");
});
it("Generate postgreSQL crud page , connect to git, clone the page, rename page with special character in it", () => {
cy.NavigateToHome();
cy.get(homePage.createNew)
.first()
.click({ force: true });
cy.wait("@createNewApplication").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
// create New App and generate Postgres CRUD page
cy.get(generatePage.generateCRUDPageActionCard).click();
cy.get(generatePage.selectDatasourceDropdown).click();
cy.contains("Connect New Datasource").click();
cy.get(datasource.PostgreSQL).click();
cy.fillPostgresDatasourceForm();
cy.generateUUID().then((UUID) => {
datasourceName = `${UUID}`;
cy.renameDatasource(datasourceName);
});
cy.get(".t--save-datasource").click();
cy.wait("@saveDatasource").should(
"have.nested.property",
"response.body.responseMeta.status",
200,
);
cy.wait("@getDatasourceStructure").should(
"have.nested.property",
"response.body.responseMeta.status",
200,
);
cy.get(generatePage.selectTableDropdown).click();
cy.get(generatePage.dropdownOption)
.first()
.click();
// skip optional search column selection.
cy.get(generatePage.generatePageFormSubmitBtn).click();
cy.wait("@replaceLayoutWithCRUDPage").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
cy.wait("@getActions");
cy.wait("@postExecute").should(
"have.nested.property",
"response.body.responseMeta.status",
200,
);
cy.get("span:contains('GOT IT')").click();
// connect app to git
cy.generateUUID().then((uid) => {
repoName = uid;
cy.createTestGithubRepo(repoName);
cy.connectToGitRepo(repoName);
});
// rename page to crud_page
cy.renameEntity("Page1", pageName);
cy.get(`.t--entity-name:contains(${pageName})`)
.trigger("mouseover")
.click({ force: true });
// create a clone of page
cy.get(`.t--entity-item:contains(${pageName})`).within(() => {
cy.get(".t--context-menu").click({ force: true });
});
cy.selectAction("Clone");
cy.wait("@clonePage").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
});
it("Create api queries from api pane and cURL import , bind it to widget and clone page from page settings", () => {
cy.Createpage(newPage);
cy.get(`.t--entity-item:contains(${newPage})`).click();
cy.wait(1000);
// create a get api call
cy.NavigateToAPI_Panel();
cy.CreateAPI("get_data");
// creating get request using echo
cy.enterDatasourceAndPath("https://mock-api.appsmith.com/echo", "/get");
cy.get(apiwidget.headerKey).type("info");
cy.xpath("//span[text()='Key']").click();
// entering the data in header
cy.get(apiwidget.headerValue).type("This is a test", {
parseSpecialCharSequences: false,
});
cy.SaveAndRunAPI();
cy.ResponseStatusCheck("200");
cy.get(".bp3-icon-chevron-left").click();
// curl import
cy.get(pages.integrationCreateNew)
.should("be.visible")
.click({ force: true });
cy.get(ApiEditor.curlImage).click({ force: true });
cy.get("textarea").type(
'curl -d \'{"name":"morpheus","job":"leader"}\' -H Content-Type:application/json -X POST https://mock-api.appsmith.com/echo/post',
{
force: true,
parseSpecialCharSequences: false,
},
);
cy.importCurl();
cy.RunAPI();
cy.ResponseStatusCheck("201 CREATED");
cy.get("@curlImport").then((response) => {
cy.expect(response.response.body.responseMeta.success).to.eq(true);
cy.get(apiwidget.ApiName)
.invoke("text")
.then((text) => {
const someText = text;
expect(someText).to.equal(response.response.body.data.name);
});
});
cy.get(explorer.addWidget).click();
// bind input widgets to the api calls responses
cy.dragAndDropToCanvas("inputwidgetv2", { x: 300, y: 300 });
cy.get(".t--widget-inputwidgetv2").should("exist");
cy.get(dynamicInputLocators.input)
.eq(1)
.click({ force: true })
.type("{{Api1.data.body.name}}", { parseSpecialCharSequences: false });
cy.dragAndDropToCanvas("inputwidgetv2", { x: 300, y: 500 });
cy.get(".t--widget-inputwidgetv2").should("exist");
cy.get(dynamicInputLocators.input)
.eq(1)
.click({ force: true })
.type("{{get_data.data.headers.info}}", {
parseSpecialCharSequences: false,
});
cy.wait(2000);
// clone the page from page settings
cy.xpath("//span[contains(@class,'entity-right-icon')]").click({
force: true,
});
cy.xpath("(//button[@type='button'])")
.eq(9)
.click();
cy.wait("@clonePage").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
cy.get(`.t--entity-item:contains(${newPage} Copy)`).click();
cy.wait("@getPage");
});
it("Commit and push changes, validate data binding on all pages in edit and deploy mode on master", () => {
// verfiy data binding on all pages in edit mode
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(`.t--entity-item:contains(${newPage})`)
.first()
.click();
cy.wait("@getPage");
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(`.t--entity-item:contains(${pageName} Copy)`).click();
cy.wait("@getPage");
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(`.t--entity-item:contains(${pageName})`)
.first()
.click();
cy.wait("@getPage");
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
// commit and push the changes
cy.commitAndPush();
cy.wait(2000);
// verify data binding on all pages in deploy mode
cy.latestDeployPreview();
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(".t--page-switch-tab")
.contains(`${pageName} Copy`)
.click({ force: true });
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(".t--page-switch-tab")
.contains(`${newPage}`)
.click({ force: true });
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(".t--page-switch-tab")
.contains(`${newPage} Copy`)
.click({ force: true });
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(commonlocators.backToEditor).click();
cy.wait(2000);
});
it("Create a new branch tempBranch, add jsObject and datasource query, move them to new page i.e. Child_Page and bind to widgets", () => {
cy.createGitBranch(tempBranch);
cy.wait(1000);
// create jsObject and rename it
cy.createJSObject('return "Success";');
cy.wait(2000);
// create postgres select query
//cy.CheckAndUnfoldEntityItem("DATASOURCES");
cy.NavigateToQueryEditor();
cy.NavigateToActiveTab();
cy.get(datasource.datasourceCard)
.contains(datasourceName)
.scrollIntoView()
.should("be.visible")
.closest(datasource.datasourceCard)
.within(() => {
cy.get(datasource.createQuerty).click();
});
cy.get(queryLocators.queryNameField).type("get_users");
cy.get(queryLocators.switch)
.last()
.click({ force: true });
cy.get(queryLocators.templateMenu).click();
cy.get(queryLocators.query).click({ force: true });
// writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users ORDER BY id LIMIT 10;", {
force: true,
parseSpecialCharSequences: false,
});
cy.WaitAutoSave();
cy.runQuery();
// create a new page
cy.CheckAndUnfoldEntityItem("PAGES");
cy.Createpage("Child_Page");
cy.wait(1000);
cy.get(`.t--entity-name:contains(${newPage} Copy)`)
.trigger("mouseover")
.click({ force: true });
// move jsObject and postgres query to new page
cy.CheckAndUnfoldEntityItem("QUERIES/JS");
ee.ActionContextMenuByEntityName("get_users", "Move to page", "Child_Page");
cy.wait(2000);
cy.get(`.t--entity-name:contains(${newPage} Copy)`)
.trigger("mouseover")
.click({ force: true });
ee.ActionContextMenuByEntityName("JSObject1", "Move to page", "Child_Page");
cy.wait(2000);
cy.get(explorer.addWidget).click();
// bind input widgets to the jsObject and query response
cy.dragAndDropToCanvas("inputwidgetv2", { x: 300, y: 300 });
cy.get(".t--widget-inputwidgetv2").should("exist");
cy.get(dynamicInputLocators.input)
.eq(1)
.click({ force: true })
.type("{{JSObject1.myFun1()}}", { parseSpecialCharSequences: false });
cy.dragAndDropToCanvas("inputwidgetv2", { x: 300, y: 500 });
cy.get(".t--widget-inputwidgetv2").should("exist");
cy.get(dynamicInputLocators.input)
.eq(1)
.click({ force: true })
.type("{{get_users.data[0].name}}", {
parseSpecialCharSequences: false,
});
cy.wait(2000);
});
it("Commit and push changes, validate data binding on all pages in edit and deploy mode on tempBranch", () => {
// commit and push changes
cy.get(homePage.publishButton).click();
cy.get(gitSyncLocators.commitCommentInput).type("Initial Commit");
cy.get(gitSyncLocators.commitButton).click();
cy.wait(8000);
cy.get(gitSyncLocators.closeGitSyncModal).click();
// verfiy data binding on all pages in deploy mode
cy.latestDeployPreview();
cy.get(".bp3-input")
.first()
.should("have.value", "Success");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "Test user 7");
cy.get(".t--page-switch-tab")
.contains(`${pageName}`)
.click({ force: true });
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(".t--page-switch-tab")
.contains(`${pageName} Copy`)
.click({ force: true });
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(".t--page-switch-tab")
.contains(`${newPage}`)
.click({ force: true });
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(".t--page-switch-tab")
.contains(`${newPage} Copy`)
.click({ force: true });
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(commonlocators.backToEditor).click();
cy.wait(2000);
// verfiy data binding on all pages in edit mode
/* cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(`.t--entity-item:contains(Child_Page)`)
.first()
.click();
cy.wait("@getPage");
cy.reload();
cy.wait(3000);
cy.get(".bp3-input")
.first()
.should("have.value", "Success");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "Test user 7");
cy.get(`.t--entity-item:contains(${newPage})`)
.first()
.click();
cy.wait("@getPage");
cy.get(".bp3-input")
.first()
.should("have.value", "morpheus");
cy.get(".bp3-input")
.eq(1)
.should("have.value", "This is a test");
cy.get(`.t--entity-item:contains(${pageName} Copy)`).click();
cy.wait("@getPage");
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
});
cy.get(`.t--entity-item:contains(${pageName})`)
.first()
.click();
cy.wait("@getPage");
cy.readTabledataPublish("0", "1").then((cellData) => {
expect(cellData).to.be.equal("New Config");
}); */
});
it("Switch to master and verify no uncommitted changes should be shown on master", () => {
cy.switchGitBranch("master");
cy.wait(2000);
// verify commit input box is disabled
cy.get(homePage.publishButton).click();
cy.get(".t--commit-comment-input")
.should("be.disabled")
.and("have.text", "No changes to commit");
cy.get(gitSyncLocators.closeGitSyncModal).click();
});
it("Switch to tempBranch , Clone the Child_Page, change it's visiblity to hidden and deploy, merge to master", () => {
cy.switchGitBranch(tempBranch);
cy.wait(2000);
// clone the Child_Page
cy.CheckAndUnfoldEntityItem("PAGES");
cy.get(`.t--entity-item:contains(Child_Page)`).within(() => {
cy.get(".t--context-menu").click({ force: true });
});
cy.selectAction("Clone");
cy.wait("@clonePage").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
// change cloned page visiblity to hidden
cy.CheckAndUnfoldEntityItem("PAGES");
cy.get(`.t--entity-item:contains(Child_Page Copy)`).within(() => {
cy.get(".t--context-menu").click({ force: true });
});
cy.selectAction("Hide");
cy.get(`.t--entity-item:contains(Child_Page)`)
.first()
.click();
cy.wait("@getPage");
cy.get(homePage.publishButton).click();
cy.get(gitSyncLocators.commitCommentInput).type("Initial Commit");
cy.get(gitSyncLocators.commitButton).click();
cy.wait(8000);
cy.get(gitSyncLocators.closeGitSyncModal).click();
cy.wait(2000);
cy.merge(mainBranch);
cy.get(gitSyncLocators.closeGitSyncModal).click();
cy.wait(2000);
cy.latestDeployPreview();
// verify page is hidden on deploy mode
cy.get(".t--page-switch-tab").should("not.contain", "Child_Page Copy");
cy.get(commonlocators.backToEditor).click();
cy.wait(2000);
});
it("Verify Page visiblity on master in edit and deploy mode", () => {
cy.switchGitBranch(mainBranch);
cy.wait(2000);
cy.latestDeployPreview();
cy.get(".t--page-switch-tab").should("not.contain", "Child_Page Copy");
cy.get(commonlocators.backToEditor).click();
cy.wait(2000);
});
it("Create new branch, delete a page and merge back to master, verify page is deleted on master", () => {
cy.createGitBranch(tempBranch1);
// delete page from page settings
cy.Deletepage("Child_Page Copy");
cy.get(homePage.publishButton).click();
cy.get(gitSyncLocators.commitCommentInput).type("Initial Commit");
cy.get(gitSyncLocators.commitButton).click();
cy.wait(8000);
cy.get(gitSyncLocators.closeGitSyncModal).click();
cy.wait(2000);
cy.merge(mainBranch);
cy.get(gitSyncLocators.closeGitSyncModal).click();
// verify Child_Page is not on master
cy.switchGitBranch(mainBranch);
cy.CheckAndUnfoldEntityItem("PAGES");
cy.get(`.t--entity-name:contains("Child_Page Copy")`).should("not.exist");
// create another branch and verify deleted page doesn't exist on it
cy.createGitBranch(tempBranch0);
cy.CheckAndUnfoldEntityItem("PAGES");
cy.get(`.t--entity-name:contains("Child_Page Copy")`).should("not.exist");
});
it("Import app from git and verify page order should not change", () => {
cy.get(homePage.homeIcon).click();
cy.get(homePage.optionsIcon)
.first()
.click();
cy.get(homePage.orgImportAppOption).click({ force: true });
cy.get(".t--import-json-card")
.next()
.click();
// import application from git
cy.importAppFromGit(repoName);
cy.wait(2000);
// verify page order remains same as in orignal app
cy.CheckAndUnfoldEntityItem("PAGES");
cy.get(".t--entity-item")
.eq(1)
.contains("crudpage_1");
cy.get(".t--entity-item")
.eq(2)
.contains("crudpage_1 Copy");
cy.get(".t--entity-item")
.eq(3)
.contains("ApiCalls_1");
cy.get(".t--entity-item")
.eq(4)
.contains("ApiCalls_1 Copy");
cy.get(".t--entity-item")
.eq(5)
.contains("Child_Page");
});
});

View File

@ -4,13 +4,9 @@
require("cy-verify-downloads").addCustomCommand();
require("cypress-file-upload");
const {
addMatchImageSnapshotCommand,
} = require("cypress-image-snapshot/command");
import homePage from "../locators/HomePage";
const generatePage = require("../locators/GeneratePage.json");
import explorer from "../locators/explorerlocators";
export const initLocalstorage = () => {
cy.window().then((window) => {
window.localStorage.setItem("ShowCommentsButtonToolTip", "");
@ -302,3 +298,12 @@ Cypress.Commands.add("CreateAppInFirstListedOrg", (appname) => {
*/
cy.wait("@updateLayout");
});
Cypress.Commands.add("renameEntity", (entityName, renamedEntity) => {
cy.get(`.t--entity-item:contains(${entityName})`).within(() => {
cy.get(".t--context-menu").click({ force: true });
});
cy.selectAction("Edit Name");
cy.get(explorer.editEntity)
.last()
.type(`${renamedEntity}`, { force: true });
});

View File

@ -294,7 +294,7 @@ Cypress.Commands.add("merge", (destinationBranch) => {
Cypress.Commands.add(
"importAppFromGit",
(repo, shouldCommit = true, assertConnectFailure) => {
(repo, assertConnectFailure, failureMessage) => {
const testEmail = "test@test.com";
const testUsername = "testusername";
const owner = Cypress.env("TEST_GITHUB_USER_NAME");
@ -353,7 +353,9 @@ Cypress.Commands.add(
} else {
cy.wait("@importFromGit").then((interception) => {
const status = interception.response.body.responseMeta.status;
const message = interception.response.body.responseMeta.error.message;
expect(status).to.be.gte(400);
expect(message).to.contain(failureMessage);
});
}
});