-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: Add cypress tests for Hubspot Datasource functionalities #39419
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,173 @@ | ||||||
import { | ||||||
agHelper, | ||||||
appSettings, | ||||||
dataSources, | ||||||
deployMode, | ||||||
draggableWidgets, | ||||||
entityExplorer, | ||||||
entityItems, | ||||||
locators, | ||||||
propPane, | ||||||
assertHelper, | ||||||
} from "../../../../support/Objects/ObjectsCore"; | ||||||
import EditorNavigation, { | ||||||
EntityType, | ||||||
PageLeftPane, | ||||||
PagePaneSegment, | ||||||
} from "../../../../support/Pages/EditorNavigation"; | ||||||
const myDsName = "HubspotDS"; | ||||||
|
||||||
describe( | ||||||
"Hubspot Basic Tests", | ||||||
{ | ||||||
tags: ["@tag.Datasource", "@tag.Git", "@tag.AccessControl", "@tag.Hubspot"], | ||||||
}, | ||||||
() => { | ||||||
it("1. Validate the configuration of Hubspot datasource", () => { | ||||||
dataSources.NavigateToDSCreateNew(); | ||||||
dataSources.CreatePlugIn("HubSpot"); | ||||||
agHelper.AssertElementVisibility(dataSources._imgHubspotLogo, true, 0); // Ensure the Hubspot logo is visible | ||||||
agHelper.GetNAssertContains(locators._dsName, "Untitled datasource 1"); | ||||||
|
||||||
// Attempt to rename the datasource with invalid and valid names | ||||||
agHelper.GetNClick(locators._dsName); | ||||||
agHelper.ClearTextField(locators._dsNameTxt, true); | ||||||
agHelper.AssertTooltip("Please enter a valid name"); | ||||||
agHelper.PressEnter(); | ||||||
agHelper.ValidateToastMessage("Invalid name"); | ||||||
agHelper.GetNClick(locators._dsName); | ||||||
agHelper.TypeText(locators._dsNameTxt, myDsName); | ||||||
agHelper.PressEnter(); | ||||||
agHelper.AssertElementVisibility(dataSources._datasourceCard, true); | ||||||
// Fill out the Hubspot configuration form and save the datasource | ||||||
dataSources.FillHubspotDSForm(); | ||||||
dataSources.SaveDatasource(); | ||||||
}); | ||||||
|
||||||
it("2. Validate creating & running queries for the datasource", () => { | ||||||
// Create and run a SELECT query, validating the response views | ||||||
dataSources.CreateQueryForDS("HubspotDS"); | ||||||
dataSources.ValidateNSelectDropdown( | ||||||
"Commands", | ||||||
"Please select an option", | ||||||
"HubDB - get details of a published table", | ||||||
); | ||||||
agHelper.EnterValue("appsmith1", { | ||||||
propFieldName: "", | ||||||
directInput: false, | ||||||
inputFieldName: "Table ID or name", | ||||||
}); | ||||||
|
||||||
const fireApi = (retries = 5, responseTimeout = 100000) => { | ||||||
if (retries === 0) { | ||||||
throw new Error("Max retries reached, API did not return success."); | ||||||
} | ||||||
|
||||||
dataSources.RunQuery({ | ||||||
toValidateResponse: false, | ||||||
}); | ||||||
cy.wait(assertHelper.GetAliasName("@postExecute"), { | ||||||
timeout: responseTimeout, | ||||||
}) | ||||||
Comment on lines
+69
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove cy.wait and agHelper.Sleep calls. According to the coding guidelines:
Replace the wait and sleep calls with proper Cypress commands that wait for specific conditions: -cy.wait(assertHelper.GetAliasName("@postExecute"), {
- timeout: responseTimeout,
-});
+cy.intercept('POST', '**/postExecute').as('postExecute');
+cy.get(assertHelper.GetAliasName("@postExecute")).should('exist');
-assertHelper.Sleep();
+cy.get(assertHelper.GetAliasName("@postExecute")).should('not.exist'); Also applies to: 84-84 |
||||||
.then((interceptions) => { | ||||||
return cy | ||||||
.get(assertHelper.GetAliasName("@postExecute"), { | ||||||
timeout: responseTimeout, | ||||||
}) | ||||||
.its("response"); | ||||||
}) | ||||||
.then((response) => { | ||||||
const { isExecutionSuccess } = response.body.data; | ||||||
|
||||||
if (!isExecutionSuccess) { | ||||||
cy.log(`Retrying... Attempts left: ${retries - 1}`); | ||||||
assertHelper.Sleep(); | ||||||
fireApi(retries - 1); | ||||||
} else { | ||||||
expect(isExecutionSuccess).to.eq(true); | ||||||
} | ||||||
}); | ||||||
}; | ||||||
|
||||||
fireApi(5); | ||||||
Comment on lines
+61
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor retry mechanism to use Cypress built-in retries. The custom retry mechanism can be replaced with Cypress's built-in retry-ability and assertions. -const fireApi = (retries = 5, responseTimeout = 100000) => {
- if (retries === 0) {
- throw new Error("Max retries reached, API did not return success.");
- }
-
- dataSources.RunQuery({
- toValidateResponse: false,
- });
- cy.wait(assertHelper.GetAliasName("@postExecute"))
- .then((interceptions) => {
- return cy.get(assertHelper.GetAliasName("@postExecute"))
- .its("response");
- })
- .then((response) => {
- const { isExecutionSuccess } = response.body.data;
-
- if (!isExecutionSuccess) {
- cy.log(`Retrying... Attempts left: ${retries - 1}`);
- assertHelper.Sleep();
- fireApi(retries - 1);
- } else {
- expect(isExecutionSuccess).to.eq(true);
- }
- });
-};
-
-fireApi(5);
+dataSources.RunQuery({
+ toValidateResponse: false,
+});
+
+cy.intercept('POST', '**/postExecute').as('postExecute');
+cy.get('@postExecute').should('exist').then((interception) => {
+ expect(interception.response.body.data.isExecutionSuccess).to.eq(true);
+});
|
||||||
// PageLeftPane.switchSegment(PagePaneSegment.UI); // Switching the tab to ensure connection reset from Hubspot platform gets refreshed | ||||||
// PageLeftPane.switchSegment(PagePaneSegment.Queries); | ||||||
cy.get("@postExecute").then((resObj: any) => { | ||||||
const json = resObj.response.body.data.body; | ||||||
const name = json.name; | ||||||
cy.log("Name is :" + name); | ||||||
expect(name).to.equal("appsmith1"); //Verify if record contains the table | ||||||
}); | ||||||
}); | ||||||
|
||||||
it("3. Validate widget binding with queries & deploying the app", () => { | ||||||
PageLeftPane.switchSegment(PagePaneSegment.UI); | ||||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT); | ||||||
propPane.EnterJSContext("Text", "{{Api1.data}}"); | ||||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TEXT)); | ||||||
agHelper.AssertElementVisibility(appSettings.locators._header); | ||||||
//agHelper.RefreshPage(); // Refreshing the page due to frequent connection reset from Hubspot | ||||||
// Assert that the text widget contains the expected data | ||||||
cy.get(locators._widgetInDeployed(draggableWidgets.TEXT)).should( | ||||||
"contain.text", | ||||||
"appsmith1", | ||||||
); | ||||||
// agHelper | ||||||
// .GetElement(locators._widgetInDeployed(draggableWidgets.TEXT)) | ||||||
// .then(($elements) => { | ||||||
// const values = $elements | ||||||
// .map((_, el) => Cypress.$(el).text().trim()) | ||||||
// .get(); | ||||||
// expect(values).to.include("appsmith1"); | ||||||
// }); | ||||||
deployMode.NavigateBacktoEditor(); | ||||||
EditorNavigation.SelectEntityByName("Api1", EntityType.Query); | ||||||
}); | ||||||
|
||||||
it("4. Validate deleting the datasource", () => { | ||||||
// Delete all queries associated with the datasource | ||||||
PageLeftPane.selectItem("Api1", { ctrlKey: true, force: true }); | ||||||
agHelper.ActionContextMenuWithInPane({ | ||||||
action: "Delete", | ||||||
entityType: entityItems.Query, | ||||||
}); | ||||||
|
||||||
// Delete the datasource and verify its removal | ||||||
dataSources.DeleteDatasourceFromWithinDS(myDsName, 409); | ||||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TEXT)); | ||||||
cy.get(locators._widgetInDeployed(draggableWidgets.TEXT)).should( | ||||||
"have.text", | ||||||
"", | ||||||
); | ||||||
deployMode.NavigateBacktoEditor(); | ||||||
dataSources.DeleteDatasourceFromWithinDS(myDsName, 200); | ||||||
agHelper.ValidateToastMessage( | ||||||
"HubspotDS datasource deleted successfully", | ||||||
); | ||||||
}); | ||||||
it("5. Validate connection error when misconfiguring datasource", () => { | ||||||
dataSources.NavigateToDSCreateNew(); | ||||||
dataSources.CreatePlugIn("HubSpot"); | ||||||
agHelper.GetNAssertContains(locators._dsName, "Untitled datasource 1"); | ||||||
agHelper.AssertElementVisibility(dataSources._datasourceCard, true); | ||||||
dataSources.FillHubspotDSForm(undefined, "wrongpassword"); | ||||||
dataSources.SaveDatasource(false); | ||||||
dataSources.CreateQueryForDS("Untitled datasource 1"); | ||||||
agHelper.RefreshPage(); // Refreshing the page due to frequent connection reset from Hubspot | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove page refresh call. The code uses agHelper.RefreshPage() which should be avoided. Instead, handle the connection reset gracefully using proper test setup and teardown. -agHelper.RefreshPage(); // Refreshing the page due to frequent connection reset from Hubspot
+// Handle connection reset by implementing proper retry mechanism or connection handling 📝 Committable suggestion
Suggested change
|
||||||
dataSources.ValidateNSelectDropdown( | ||||||
"Commands", | ||||||
"Please select an option", | ||||||
"HubDB - get details of a published table", | ||||||
); | ||||||
agHelper.EnterValue("appsmith1", { | ||||||
propFieldName: "", | ||||||
directInput: false, | ||||||
inputFieldName: "Table ID or name", | ||||||
}); | ||||||
dataSources.RunQuery({ | ||||||
expectedStatus: false, | ||||||
toValidateResponse: true, | ||||||
}); | ||||||
}); | ||||||
}, | ||||||
); |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -317,6 +317,7 @@ export class DataSources { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private _entityTriggerElement = ".t--template-menu-trigger"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_dsSchemaTableResponse = ".t--table-response"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_imgSnowflakeLogo = "//img[contains(@src, 'snowflake.svg')]"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_imgHubspotLogo = "//img[contains(@src, 'hubspot.png')]"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Replace XPath with data- attribute selector.* Using XPath selectors is against the coding guidelines. Use data-* attributes for more reliable and maintainable selectors. - _imgHubspotLogo = "//img[contains(@src, 'hubspot.png')]";
+ _imgHubspotLogo = "[data-testid='hubspot-logo-img']"; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_dsConfigProperties = (index: number) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"input[name*='datasourceConfiguration.properties[" + index + "]']"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_dsConfigAuthType = `[data-testid*='datasourceConfiguration.authentication.authenticationType']`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -608,7 +609,25 @@ export class DataSources { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
: password, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public FillHubspotDSForm( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
environment = this.dataManager.defaultEnviorment, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password = "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.ValidateNSelectDropdown( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Authentication type", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Please select an option", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Bearer token", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.agHelper.TypeText( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.locator._inputFieldByName("Bearer token") + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"//" + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.locator._inputField, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
? this.dataManager.dsValues[environment].hubspotBearerToken | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
: password, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.agHelper.Sleep(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+612
to
+630
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove agHelper.Sleep() and use proper wait conditions. Using Sleep() is against the coding guidelines. Use proper wait conditions or assertions instead. public FillHubspotDSForm(
environment = this.dataManager.defaultEnviorment,
password = "",
) {
this.ValidateNSelectDropdown(
"Authentication type",
"Please select an option",
"Bearer token",
);
this.agHelper.TypeText(
this.locator._inputFieldByName("Bearer token") +
"//" +
this.locator._inputField,
!password
? this.dataManager.dsValues[environment].hubspotBearerToken
: password,
);
- this.agHelper.Sleep();
+ this.agHelper.WaitUntilAllToastsDisappear();
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public FillMongoDSForm( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
environment = this.dataManager.defaultEnviorment, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shouldAddTrailingSpaces = false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use data- attributes for selectors.*
According to the guidelines, we should:
Replace the current selectors with data-* attributes:
Also applies to: 111-114, 138-141