test: Cypress - Gitea App Automation (#25144)

## Description

**Fixed below flaky tests**

- Gitea app automation , validations covered:
    - A successful api call
    - An unsuccessful api cal
    - CRUD pages for DS - Postgres, Mongo, Mysql
    - CRUD table validations in Deploy page
    - Widgets & their bindings validations
    - Update JSObjects, bind it to widget & Validate updated response

## Type of change

- New feature

## How Has This Been Tested?
- Cypress test runs

## Checklist:
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test

---------

Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
Vijetha-Kaja 2023-07-11 22:09:13 +05:30 committed by GitHub
parent eeb2d40a10
commit d7202abbc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 392 additions and 56 deletions

View File

@ -35,7 +35,7 @@ describe("AForce - Community Issues page validations", function () {
const { isPartialImport } = interception.response.body.data;
if (isPartialImport) {
// should reconnect modal
dataSources.ReconnectDataSource("AForceDB", "PostgreSQL");
dataSources.ReconnectSingleDSNAssert("AForceDB", "PostgreSQL");
homePage.AssertNCloseImport();
} else {
homePage.AssertImportToast();

View File

@ -29,7 +29,7 @@ describe("Import, Export and Fork application and validate data binding", functi
const { isPartialImport } = interception.response.body.data;
if (isPartialImport) {
// should reconnect button
dataSources.ReconnectDataSource("mockdata", "PostgreSQL");
dataSources.ReconnectSingleDSNAssert("mockdata", "PostgreSQL");
homePage.AssertNCloseImport();
cy.wait(2000);
} else {

View File

@ -81,11 +81,11 @@ describe("Git Bugs", function () {
_.agHelper.GetNClick(_.locators._appChangeThemeBtn, 0, true);
_.agHelper.GetNClick(_.locators._appThemeCard, 2);
_.agHelper.GetNClick(_.locators._publishButton);
_.agHelper.WaitUntilEleAppear(_.locators._gitStatusChanges);
_.agHelper.WaitUntilEleAppear(_.gitSync._gitStatusChanges);
_.agHelper.AssertContains(
Cypress.env("MESSAGES").CHANGES_THEME(),
"exist",
_.locators._gitStatusChanges,
_.gitSync._gitStatusChanges,
);
_.agHelper.GetNClick(_.locators._dialogCloseButton);
_.agHelper.GetNClick(_.locators._appEditMenuBtn);
@ -94,11 +94,11 @@ describe("Git Bugs", function () {
_.agHelper.GetNClick(_.locators._appNavigationSettings);
_.agHelper.GetNClick(_.locators._appNavigationSettingsShowTitle);
_.agHelper.GetNClick(_.locators._publishButton);
_.agHelper.WaitUntilEleAppear(_.locators._gitStatusChanges);
_.agHelper.WaitUntilEleAppear(_.gitSync._gitStatusChanges);
_.agHelper.AssertContains(
Cypress.env("MESSAGES").CHANGES_APP_SETTINGS(),
"exist",
_.locators._gitStatusChanges,
_.gitSync._gitStatusChanges,
);
_.agHelper.GetNClick(_.locators._dialogCloseButton);
});
@ -114,7 +114,7 @@ describe("Git Bugs", function () {
_.agHelper.GetNClick(_.locators._appNavigationSettings);
_.agHelper.GetNClick(_.locators._appNavigationSettingsShowTitle);
_.agHelper.GetNClick(_.locators._publishButton);
_.agHelper.WaitUntilEleAppear(_.locators._gitStatusChanges);
_.agHelper.WaitUntilEleAppear(_.gitSync._gitStatusChanges);
_.agHelper.GetNClick(_.gitSync._discardChanges);
_.agHelper.WaitUntilEleAppear(_.gitSync._discardCallout);
_.agHelper.AssertContains(

View File

@ -0,0 +1,272 @@
import {
agHelper,
assertHelper,
dataSources,
deployMode,
draggableWidgets,
entityExplorer,
gitSync,
homePage,
jsEditor,
locators,
propPane,
table,
} from "../../../../../../support/Objects/ObjectsCore";
describe("Import and validate older app (app created in older versions of Appsmith) from Gitea", function () {
let appRepoName = "TestMigration",
appName = "UpgradeAppToLatestVersion",
keyId: any,
workspaceName: any;
before(() => {
homePage.NavigateToHome();
agHelper.GenerateUUID();
cy.get("@guid").then((uid) => {
workspaceName = "GitImport_" + uid;
homePage.CreateNewWorkspace(workspaceName);
});
//Import App From Gitea
gitSync.ImportAppFromGit(workspaceName, appRepoName, true);
cy.get("@deployKeyId").then((id) => {
keyId = id;
});
//Reconnect datasources
dataSources.ReconnectDSbyType("MongoDB");
dataSources.ReconnectDSbyType("MySQL");
dataSources.ReconnectDSbyType("PostgreSQL");
homePage.AssertNCloseImport();
});
it("1. Validate merge status", () => {
entityExplorer.AssertEntityPresenceInExplorer("ListingAndReviews");
//Wait for the app to settle
agHelper.Sleep(1000);
homePage.RenameApplication(appName);
agHelper.AssertElementVisible(gitSync._bottomBarCommit);
agHelper.AssertText(gitSync._gitPullCount, "text", "4");
agHelper.GetNClick(gitSync._bottomBarCommit);
agHelper.AssertElementVisible(gitSync._gitSyncModal);
//This is expected due to Canvas Splitting PR changes in v1.9.24
agHelper.GetNAssertElementText(
gitSync._gitStatusChanges,
"4 pages modified",
"contain.text",
);
agHelper.GetNAssertElementText(
gitSync._gitStatusChanges,
"Some of the changes above are due to an improved file structure designed to reduce merge conflicts. You can safely commit them to your repository.",
"contain.text",
);
agHelper.GetNClick(gitSync._commitButton);
assertHelper.AssertNetworkStatus("@commit", 201);
gitSync.CloseGitSyncModal();
});
it("2. Deploy the app & Validate CRUD pages - Mongo , MySql, Postgres pages", () => {
//Mongo CRUD page validation
//Assert table data
cy.latestDeployPreview();
agHelper.AssertText(
locators._widgetInDeployed(draggableWidgets.TEXT),
"text",
"listingAndReviews Data",
);
agHelper.AssertElementVisible(locators._widgetByName("data_table"));
//Filter & validate table data
table.OpenNFilterTable("_id", "is exactly", "15665837");
table.ReadTableRowColumnData(0, 0).then(($cellData) => {
expect($cellData).to.eq(
'["TV","Internet","Wifi","Air conditioning","Wheelchair accessible","Pool","Kitchen","Free parking on premises","Smoking allowed","Pets allowed","Gym","Elevator","Hot tub","Heating","Family/kid friendly","Washer","Dryer","Smoke detector","Fire extinguisher","Essentials"]',
);
});
//MySql CRUD page validation
agHelper.GetNClickByContains(locators._deployedPage, "CountryFlags");
//Assert table data
agHelper.AssertText(
locators._widgetInDeployed(draggableWidgets.TEXT),
"text",
"countryFlags Data",
);
agHelper.AssertElementVisible(locators._widgetByName("data_table"));
//Filter & validate table data
table.OpenNFilterTable("Country", "starts with", "Ba");
table.ReadTableRowColumnData(2, 0).then(($cellData) => {
expect($cellData).to.eq("Bangladesh");
});
table.CloseFilter();
//Download table data
table.DownloadFromTable("Download as CSV");
table.ValidateDownloadNVerify("data_table.csv", "Bangladesh");
//Postgres CRUD page validation
agHelper.GetNClickByContains(locators._deployedPage, "Public.astronauts");
agHelper.AssertText(
locators._widgetInDeployed(draggableWidgets.TEXT),
"text",
"public_astronauts Data",
);
agHelper.AssertElementVisible(locators._widgetByName("data_table"));
//Filter & validate table data
table.OpenNFilterTable("id", "is exactly", "196");
table.ReadTableRowColumnData(0, 2).then(($cellData) => {
expect($cellData).to.eq("Ulf Merbold");
});
table.RemoveFilter();
//Update table data
deployMode.EnterJSONInputValue("Statusid", "5", 0, true);
deployMode.EnterJSONInputValue("Statusname", "Active", 0, true);
agHelper.Sleep(500);
agHelper.ClickButton("Update");
//Validate updated values in table
table.ReadTableRowColumnData(0, 3).then(($cellData) => {
expect($cellData).to.eq("5");
});
table.ReadTableRowColumnData(0, 4).then(($cellData) => {
expect($cellData).to.eq("Active");
});
agHelper.Sleep(500);
});
it("3. Validate widgets & bindings", () => {
agHelper.GetNClickByContains(locators._deployedPage, "Widgets");
agHelper.AssertElementVisible(
locators._widgetInDeployed(draggableWidgets.AUDIO),
);
agHelper.AssertElementVisible(
locators._widgetInDeployed(draggableWidgets.AUDIORECORDER),
);
agHelper.AssertElementVisible(
locators._widgetInDeployed(draggableWidgets.DOCUMENT_VIEWER),
);
agHelper.AssertElementVisible(
locators._widgetInDeployed(draggableWidgets.CHART),
);
//Button
agHelper.ClickButton("Alert button");
agHelper.Sleep(500);
agHelper.WaitUntilToastDisappear("404 hit : invalidApi failed to execute");
//Checkbox group
agHelper.AssertElementVisible(
locators._widgetInDeployed(draggableWidgets.CHECKBOXGROUP),
);
agHelper.GetNAssertElementText(
locators._widgetInDeployed(draggableWidgets.CHECKBOXGROUP),
"Select AstronautUlf MerboldAndreas MogensenWubbo OckelsThomas ReiterAnil Menon",
"have.text",
);
agHelper
.GetElement(locators._checkboxGroupOptions("Ulf Merbold"))
.should("be.checked");
agHelper.CheckUncheck(locators._checkboxGroupOptions("Anil Menon"));
//Slider
agHelper
.ScrollIntoView(locators._sliderThumb)
.focus()
.type("{rightArrow}")
.wait(500);
agHelper.Sleep(500);
agHelper.WaitUntilToastDisappear("Category Value Changed!");
//Currency input
agHelper.TypeText(
locators._widgetInDeployed(draggableWidgets.CURRENCY_INPUT) + " input",
"10",
);
agHelper.WaitUntilToastDisappear(
'{"countryCode":"IN","currencyCode":"INR","value":10}',
);
//Table
agHelper.TypeText(
locators._widgetInDeployed("inputwidgetv2") + " input",
"144",
);
table.ReadTableRowColumnData(0, 3, "v2").then(($cellData) => {
expect($cellData).to.eq("Christina ");
});
//Add customer details - Validate Modal & JSON Form
agHelper.ClickButton("Add customer Details");
agHelper.AssertElementVisible(locators._modal);
deployMode.EnterJSONInputValue("Customer Name", "TestUser", 0, true);
deployMode.EnterJSONInputValue("Customer Number", "1", 0, true);
deployMode.EnterJSONInputValue("Phone Number", "999999999", 0, true);
agHelper.ClickButton("Submit", 1);
agHelper.WaitUntilToastDisappear("Add Customer Successful!");
agHelper.ClickButton("Close");
//Delete customer details
agHelper.ClickButton("Delete customer details");
agHelper.AssertElementVisible(locators._modal);
agHelper.ClickButton("Confirm");
agHelper.WaitUntilToastDisappear("Delete customer successful!");
agHelper.ClickButton("Close");
});
it("4. Edit JSObject & Check Updated Data ", () => {
deployMode.NavigateBacktoEditor();
//Edit existing JS object
entityExplorer.SelectEntityByName("users", "Queries/JS");
jsEditor.EditJSObj(`export default {
fun: async () => {
return await invalidApi.run().catch((e) => showAlert("404 hit : " + e.message));
},
myFun1: async () => {
//write code here
const data = JSON.stringify(await usersApi.run())
return data
},
myFun2: async () => {
//use async-await or promises
await this.myFun1()
return showAlert("myFun2 Data")
}
}`);
//Update property field for button
entityExplorer.SelectEntityByName("Button1", "Widgets");
propPane.EnterJSContext("onClick", `{{users.myFun2()}}`, true, false);
//Drag n drop text widget & bind it to myFun1
entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT);
propPane.TypeTextIntoField("Text", `{{users.myFun1.data}}`);
agHelper.ValidateToastMessage(
"[users.myFun1] will be executed automatically on page load",
);
//Commit & push new changes
gitSync.CommitAndPush();
cy.latestDeployPreview();
//Validate new response for button & text widget
agHelper.GetNClickByContains(locators._deployedPage, "Widgets");
agHelper.ClickButton("Submit");
agHelper.ValidateToastMessage("myFun2 Data");
agHelper
.GetText(locators._widgetInDeployed(draggableWidgets.TEXT), "text")
.should("not.be.empty");
});
after(() => {
gitSync.DeleteDeployKey(appRepoName, keyId);
deployMode.NavigateToHomeDirectly();
agHelper.WaitUntilAllToastsDisappear();
homePage.DeleteApplication(appName);
homePage.DeleteWorkspace(workspaceName);
});
});

View File

@ -20,7 +20,7 @@ describe("JSObjects OnLoad Actions tests", function () {
homePage.ImportApp("ImportApps/JSOnLoadImport.json", "JSOnLoadTest");
cy.wait("@importNewApplication").then(() => {
agHelper.Sleep();
dataSources.ReconnectDataSource("MySQL-Ds", "MySQL");
dataSources.ReconnectSingleDSNAssert("MySQL-Ds", "MySQL");
});
AssertJSOnPageLoad("runSpaceCraftImages", true);
});

View File

@ -31,7 +31,7 @@ describe("Reconnect Datasource Modal validation while importing application", fu
// should check reconnect modal openning
const { isPartialImport } = interception.response.body.data;
if (isPartialImport) {
dataSources.ReconnectDataSource(
dataSources.ReconnectSingleDSNAssert(
"Untitled Datasource",
"PostgreSQL",
);

View File

@ -153,6 +153,8 @@ export class CommonLocators {
_evaluatedErrorMessage =
".t--CodeEditor-evaluatedValue .t--evaluatedPopup-error";
_evalPopup = ".evaluated-value-popup";
_checkboxGroupOptions = (option: string) =>
"//div[contains(text(),'" + option + "')]/parent::label/input";
_multiSelectOptions = (option: string) =>
"div[title='" + option + "'] input[type='checkbox']";
_divWithClass = (className: string) =>
@ -247,7 +249,6 @@ export class CommonLocators {
_appThemeSettings = "#t--theme-settings-header";
_appChangeThemeBtn = ".t--change-theme-btn";
_appThemeCard = ".t--theme-card";
_gitStatusChanges = "[data-testid='t--git-change-statuses']";
_appNavigationSettings = "#t--navigation-settings-header";
_appNavigationSettingsShowTitle = "#t--navigation-settings-application-title";
_switchGroupControl =

View File

@ -62,7 +62,9 @@ export class DataSources {
this._section(name) +
"/following-sibling::div/div[@class ='bp3-collapse-body']";
private _password =
"input[name$='.datasourceConfiguration.authentication.password']";
"input[name $= '.datasourceConfiguration.authentication.password']";
private defaultDatabaseName =
"input[name*='datasourceConfiguration.connection.defaultDatabaseName']";
private _testDs = ".t--test-datasource";
_saveAndAuthorizeDS = ".t--save-and-authorize-datasource";
_saveDs = ".t--save-datasource";
@ -865,19 +867,23 @@ export class DataSources {
}
}
public ReconnectDataSource(dbName: string, dsName: "PostgreSQL" | "MySQL") {
public ReconnectSingleDSNAssert(
dbName: string,
dsName: "PostgreSQL" | "MySQL" | "MongoDB",
) {
this.ReconnectModalValidation(dbName, dsName);
this.ValidateNSelectDropdown("Connection mode", "Read / Write");
if (dsName == "PostgreSQL") this.FillPostgresDSForm();
else if (dsName == "MySQL") this.FillMySqlDSForm();
this.agHelper.GetNClick(this._saveDs);
else if (dsName == "MongoDB") this.FillMongoDSForm();
this.SaveDatasource(true);
this.assertHelper.AssertNetworkStatus("@getPage", 200);
this.assertHelper.AssertNetworkStatus("getWorkspace");
}
public ReconnectModalValidation(
dbName: string,
dsName: "PostgreSQL" | "MySQL",
dsName: "PostgreSQL" | "MySQL" | "MongoDB",
) {
this.WaitForReconnectModalToAppear();
this.agHelper.AssertElementVisible(

View File

@ -144,7 +144,14 @@ export class DeployMode {
this.agHelper.AssertElementVisible(this._homeAppsmithImage);
}
public EnterJSONInputValue(fieldName: string, value: string, index = 0) {
public EnterJSONInputValue(
fieldName: string,
value: string,
index = 0,
clearField = false,
) {
if (clearField) this.ClearJSONFieldValue(fieldName, index);
cy.xpath(this._jsonFormFieldByName(fieldName))
.eq(index)
.click()

View File

@ -7,9 +7,10 @@ export class GitSync {
public locator = ObjectsRegistry.CommonLocators;
private tedTestConfig = ObjectsRegistry.TEDTestConfigs;
private assertHelper = ObjectsRegistry.AssertHelper;
private homePage = ObjectsRegistry.HomePage;
private _connectGitBottomBar = ".t--connect-git-bottom-bar";
private _gitSyncModal = "[data-testid=t--git-sync-modal]";
public _gitSyncModal = "[data-testid=t--git-sync-modal]";
private _closeGitSyncModal =
"//div[@data-testid='t--git-sync-modal']//button[@aria-label='Close']";
//private _closeGitSyncModal = ".ads-v2-modal__content-header-close-button";
@ -22,7 +23,8 @@ export class GitSync {
"//label[text()='Author email']/following-sibling::div//input";
_branchButton = ".t--branch-button";
private _branchSearchInput = ".t--branch-search-input input";
private _bottomBarCommit = ".t--bottom-bar-commit button";
public _bottomBarCommit = ".t--bottom-bar-commit button";
public _gitPullCount = ".t--bottom-bar-commit .count";
_bottomBarPull = ".t--bottom-bar-pull button";
private _branchName = (branch: string) =>
"//button[contains(@class, 't--branch-button')]//*[text()='" +
@ -35,11 +37,12 @@ export class GitSync {
".t--merge-branch-dropdown-destination";
private _dropdownmenu = ".rc-select-item-option-content";
private _openRepoButton = "[data-testid=t--git-repo-button]";
private _commitButton = ".t--commit-button";
public _commitButton = ".t--commit-button";
private _commitCommentInput = ".t--commit-comment-input textarea";
public _discardChanges = ".t--discard-button";
public _discardCallout = "[data-testid='t--discard-callout']";
public _gitStatusChanges = "[data-testid='t--git-change-statuses']";
OpenGitSyncModal() {
this.agHelper.GetNClick(this._connectGitBottomBar);
@ -83,13 +86,23 @@ export class GitSync {
});
}
public AuthorizeKeyToGitea(repo: string, assertConnect = true) {
let generatedKey;
this.OpenGitSyncModal();
cy.intercept("POST", "/api/v1/applications/ssh-keypair/*").as(
`generateKey-${repo}`,
);
public AuthorizeKeyToGitea(
repo: string,
assertConnect = true,
importFlow = false,
) {
let generatedKey,
submitBtnName = importFlow ? "Import" : "Connect";
if (!importFlow) {
this.OpenGitSyncModal();
cy.intercept("POST", "/api/v1/applications/ssh-keypair/*").as(
`generateKey-${repo}`,
);
} else {
cy.intercept("GET", "api/v1/git/import/keys?keyType=ECDSA").as(
`generateKey-${repo}`,
);
}
this.agHelper.AssertAttribute(
this._gitRepoInput,
"placeholder",
@ -102,38 +115,57 @@ export class GitSync {
);
this.agHelper.ClickButton("Generate key");
cy.wait(`@generateKey-${repo}`).then((result: any) => {
generatedKey = result.response.body.data.publicKey;
generatedKey = generatedKey.slice(0, generatedKey.length - 1);
// fetch the generated key and post to the github repo
cy.request({
method: "POST",
url: `${this.tedTestConfig.GITEA_API_BASE_TED}:${this.tedTestConfig.GITEA_API_PORT_TED}/api/v1/repos/Cypress/${repo}/keys`,
headers: {
Authorization: `token ${Cypress.env("GITEA_TOKEN")}`,
},
body: {
title: "key0",
key: generatedKey,
read_only: false,
},
this.agHelper.GenerateUUID();
cy.get("@guid").then((uid) => {
cy.wait(`@generateKey-${repo}`).then((result: any) => {
generatedKey = result.response.body.data.publicKey;
generatedKey = generatedKey.slice(0, generatedKey.length - 1);
// fetch the generated key and post to the github repo
cy.request({
method: "POST",
url: `${this.tedTestConfig.GITEA_API_BASE_TED}:${this.tedTestConfig.GITEA_API_PORT_TED}/api/v1/repos/Cypress/${repo}/keys`,
headers: {
Authorization: `token ${Cypress.env("GITEA_TOKEN")}`,
},
body: {
title: "key_" + uid,
key: generatedKey,
read_only: false,
},
}).then((resp: any) => {
cy.log("Deploy Key Id ", resp.body.key_id);
cy.wrap(resp.body.key_id).as("deployKeyId");
});
});
});
this.agHelper.GetNClick(this._useDefaultConfig); //Uncheck the Use default configuration
this.agHelper.TypeText(
this._gitConfigNameInput,
"testusername",
//`{selectall}${testUsername}`,
);
this.agHelper.TypeText(this._gitConfigEmailInput, "test@test.com");
this.agHelper.GetNClick(this._useDefaultConfig); //Uncheck the Use default configuration
this.agHelper.TypeText(
this._gitConfigNameInput,
"testusername",
//`{selectall}${testUsername}`,
);
this.agHelper.TypeText(this._gitConfigEmailInput, "test@test.com");
this.agHelper.ClickButton("Connect");
if (assertConnect) {
this.agHelper.ClickButton(submitBtnName);
if (assertConnect) {
if (!importFlow) {
this.assertHelper.AssertNetworkStatus("@connectGitLocalRepo");
this.agHelper.AssertElementExist(this._bottomBarCommit, 0, 30000);
this.CloseGitSyncModal();
} else {
this.assertHelper.AssertNetworkStatus("@importFromGit", 201);
}
});
}
}
public ImportAppFromGit(
workspaceName: string,
repo: string,
assertConnect = true,
) {
this.homePage.ImportGitApp(workspaceName);
this.AuthorizeKeyToGitea(repo, assertConnect, true);
}
DeleteTestGithubRepo(repo: any) {
@ -146,6 +178,16 @@ export class GitSync {
});
}
DeleteDeployKey(repo: any, id: number) {
cy.request({
method: "DELETE",
url: `${this.tedTestConfig.GITEA_API_BASE_TED}:${this.tedTestConfig.GITEA_API_PORT_TED}/api/v1/repos/Cypress/${repo}/keys/${id}`,
headers: {
Authorization: `token ${Cypress.env("GITEA_TOKEN")}`,
},
});
}
CreateGitBranch(branch = "br", toUseNewGuid = false) {
if (toUseNewGuid) this.agHelper.GenerateUUID();
this.agHelper.AssertElementExist(this._bottomBarCommit);
@ -212,11 +254,7 @@ export class GitSync {
if (!assertFailure) {
// check for commit success
//adding timeout since commit is taking longer sometimes
cy.wait("@commit", { timeout: 35000 }).should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
this.assertHelper.AssertNetworkStatus("@commit", 201);
cy.wait(3000);
} else {
cy.wait("@commit", { timeout: 35000 }).then((interception: any) => {

View File

@ -110,6 +110,7 @@ export class HomePage {
// _appRenameTooltip =
// '//span[text()="Rename application"]/ancestor::div[contains(@class,"rc-tooltip")]';
_appRenameTooltip = "span:contains('Rename application')";
_importFromGitBtn = "div.t--import-json-card + div";
public SwitchToAppsTab() {
this.agHelper.GetNClick(this._homeTab);
@ -439,6 +440,17 @@ export class HomePage {
this.agHelper.Sleep(3500);
}
public ImportGitApp(intoWorkspaceName = "") {
this.NavigateToHome();
if (intoWorkspaceName)
this.agHelper.GetNClick(this._optionsIconInWorkspace(intoWorkspaceName));
else this.agHelper.GetNClick(this._optionsIcon);
this.agHelper.GetNClick(this._workspaceImport, 0, true);
this.agHelper.AssertElementVisible(this._workspaceImportAppModal);
this.agHelper.GetNClick(this._importFromGitBtn);
this.agHelper.Sleep(1000);
}
// Do not use this directly, it will fail on EE. Use `InviteUserToApplication` instead
private InviteUserToWorkspaceFromApp(
email: string,