Update cypress specs with delete datasource (#12954)

* update filed validation and delete datasource

* fixed pgsql spec
This commit is contained in:
Mekhla Asopa 2025-05-29 14:29:05 +05:30 committed by GitHub
parent 2051ed3279
commit db4cce3b0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 355 additions and 112 deletions

View file

@ -226,9 +226,9 @@ Cypress.Commands.add(
.invoke("text")
.then((text) => {
cy.wrap(subject).realType(createBackspaceText(text)),
{
delay: 0,
};
{
delay: 0,
};
});
}
);
@ -429,7 +429,6 @@ Cypress.Commands.add("visitSlug", ({ actualUrl }) => {
});
});
Cypress.Commands.add("releaseApp", () => {
if (Cypress.env("environment") !== "Community") {
cy.get(commonEeSelectors.promoteButton).click();
@ -549,7 +548,7 @@ Cypress.Commands.add("installMarketplacePlugin", (pluginName) => {
}
});
function installPlugin (pluginName) {
function installPlugin(pluginName) {
cy.get('[data-cy="-list-item"]').eq(1).click();
cy.wait(1000);
@ -605,3 +604,20 @@ Cypress.Commands.add("uninstallMarketplacePlugin", (pluginName) => {
});
});
});
Cypress.Commands.add(
"verifyRequiredFieldValidation",
(fieldName, expectedColor) => {
cy.get(commonSelectors.textField(fieldName)).should(
"have.css",
"border-color",
expectedColor
);
cy.get(commonSelectors.labelFieldValidation(fieldName))
.should("be.visible")
.and("have.text", `${fieldName} is required`);
cy.get(commonSelectors.labelFieldAlert(fieldName))
.should("be.visible")
.and("have.text", `${fieldName} is required`);
}
);

View file

@ -1,5 +1,5 @@
export const cyParamName = (paramName = "") => {
return paramName.toLowerCase().replace(/\s+/g, "-");
return String(paramName).toLowerCase().replace(/\s+/g, "-");
};
export const commonSelectors = {
@ -278,6 +278,16 @@ export const commonSelectors = {
defaultModalTitle: '[data-cy="modal-title"]',
workspaceConstantsIcon: '[data-cy="icon-workspace-constants"]',
confirmationButton: '[data-cy="confirmation-button"]',
textField: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-text-field"]`;
},
labelFieldValidation: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-is-required-validation-label"]`;
},
labelFieldAlert: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-is-required-field-alert-text"]`;
},
};
export const commonWidgetSelector = {

View file

@ -101,6 +101,8 @@ export const dataSourceSelector = {
unSavedModalTitle: '[data-cy="unsaved-changes-title"]',
eventQuerySelectionField: '[data-cy="query-selection-field"]',
connectionAlertText: '[data-cy="connection-alert-text"]',
requiredIndicator: '[data-cy="required-indicator"]',
informationIcon: '[data-cy="information-icon"]',
deleteDSButton: (datasourceName) => {
return `[data-cy="${cyParamName(datasourceName)}-delete-button"]`;
},
@ -110,4 +112,37 @@ export const dataSourceSelector = {
dataSourceNameButton: (dataSourceName) => {
return `[data-cy="${cyParamName(dataSourceName)}-button"]`;
},
dropdownLabel: (label) => {
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
},
textField: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-text-field"]`;
},
subSection: (header) => {
return `[data-cy="${cyParamName(header)}-section"]`;
},
toggleInput: (toggleName) => {
return `[data-cy="${cyParamName(toggleName)}-toggle-input"]`;
},
button: (buttonName) => {
return `[data-cy="button-${cyParamName(buttonName)}"]`;
},
keyInputField: (header, index) => {
return `[data-cy="${cyParamName(header)}-key-input-field-${cyParamName(index)}"]`;
},
valueInputField: (header, index) => {
return `[data-cy="${cyParamName(header)}-value-input-field-${cyParamName(index)}"]`;
},
deleteButton: (header, index) => {
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
},
addMoreButton: (header) => {
return `[data-cy="${cyParamName(header)}-add-button"]`;
},
dropdownField: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-select-dropdown"]`;
},
labelFieldValidation: (fieldName) => {
return `[data-cy="${cyParamName(fieldName)}-is-required-validation-label"]`;
},
};

View file

@ -87,6 +87,8 @@ export const postgreSqlSelector = {
recordsInputField: '[data-cy="records-input-field"]',
eventQuerySelectionField: '[data-cy="query-selection-field"]',
sslToggleInput: '[data-cy="ssl-enabled-toggle-input"]',
labelEncryptedText: '[data-cy="encrypted-text"]',
};
export const airTableSelector = {

View file

@ -1,6 +1,7 @@
export const airtableText = {
airtable: "Airtable",
cypressairtable: "cypress-Airtable",
ApiKey: "Personal access token",
apikeyPlaceholder: "**************",
};
airtable: "Airtable",
cypressairtable: "cypress-Airtable",
ApiKey: "Personal access token",
apikeyPlaceholder: "**************",
invalidAccessToken: "Authentication failed: Invalid personal access token",
};

View file

@ -17,13 +17,17 @@ export const postgreSqlText = {
allCloudStorage: "Cloud Storages (4)",
postgreSQL: "PostgreSQL",
labelConnectionType: "Connection type",
manualConnectionOption: "Manual connection",
connectionStringOption: "Connection string",
labelHost: "Host",
labelPort: "Port",
labelSSL: "SSL",
labelDbName: "Database name",
labelUserName: "Username",
labelPassword: "Password",
label: "Encrypted",
labelEncrypted: "Encrypted",
labelConnectionOptions: "Connection options",
sslCertificate: "SSL certificate",
whiteListIpText:
"Please white-list our IP address if the data source is not publicly accessible",
@ -74,6 +78,8 @@ export const postgreSqlText = {
guiOptionBulkUpdate: "Bulk update using primary key",
buttonTextTestConnection: "Test connection",
editButtonText: "Edit",
unableAcquireConnectionAlertText: "Unable to acquire a connection",
tabAdvanced: "Advanced",
labelNoEventhandler: "No event handlers",

View file

@ -3,24 +3,15 @@ import { postgreSqlSelector, airTableSelector } from "Selectors/postgreSql";
import { postgreSqlText } from "Texts/postgreSql";
import { airtableText } from "Texts/airTable";
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import {
fillDataSourceTextField,
selectAndAddDataSource,
} from "Support/utils/postgreSql";
import {
deleteDatasource,
closeDSModal,
deleteAppandDatasourceAfterExecution,
} from "Support/utils/dataSource";
import { closeDSModal } from "Support/utils/dataSource";
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
const data = {};
data.queryName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
const airTable_apiKey = Cypress.env("airTable_apikey");
const airTable_baseId = Cypress.env("airtabelbaseId");
const airTable_tableName = Cypress.env("airtable_tableName");
const airTable_recordID = Cypress.env("airtable_recordId");
describe("Data source Airtable", () => {
beforeEach(() => {
@ -54,18 +45,71 @@ describe("Data source Airtable", () => {
postgreSqlText.allCloudStorage
);
selectAndAddDataSource("databases", airtableText.airtable, data.dsName);
cy.get(postgreSqlSelector.buttonSave).verifyVisibleElement(
cy.apiCreateGDS(
`${Cypress.env("server_host")}/api/data-sources`,
`cypress-${data.dsName}-airtable`,
"airtable",
[
{
key: "personal_access_token",
value: `${Cypress.env("airTable_apikey")}`,
encrypted: true,
},
]
);
cy.reload();
cy.get(
dataSourceSelector.dataSourceNameButton(`cypress-${data.dsName}-airtable`)
)
.should("be.visible")
.click();
cy.get(
dataSourceSelector.labelFieldName(airtableText.ApiKey)
).verifyVisibleElement("have.text", `${airtableText.ApiKey}*`);
cy.get(postgreSqlSelector.labelEncryptedText).verifyVisibleElement(
"have.text",
postgreSqlText.buttonTextSave
postgreSqlText.labelEncrypted
);
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).should(
"be.visible"
);
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).click();
cy.verifyRequiredFieldValidation(airtableText.ApiKey, "rgb(226, 99, 103)");
cy.get(dataSourceSelector.textField(airtableText.ApiKey)).should(
"be.visible"
);
cy.get(postgreSqlSelector.labelIpWhitelist).verifyVisibleElement(
"have.text",
postgreSqlText.whiteListIpText
);
cy.get(postgreSqlSelector.buttonCopyIp).verifyVisibleElement(
"have.text",
postgreSqlText.textCopy
);
cy.verifyToastMessage(
commonSelectors.toastMessage,
postgreSqlText.toastDSSaved
cy.get(postgreSqlSelector.linkReadDocumentation).verifyVisibleElement(
"have.text",
postgreSqlText.readDocumentation
);
deleteDatasource(`cypress-${data.dsName}-airtable`);
cy.get(postgreSqlSelector.buttonTestConnection)
.verifyVisibleElement(
"have.text",
postgreSqlText.buttonTextTestConnection
)
.click();
cy.get(postgreSqlSelector.connectionFailedText).verifyVisibleElement(
"have.text",
postgreSqlText.couldNotConnect
);
cy.get(postgreSqlSelector.buttonSave)
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
.and("be.disabled");
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
"have.text",
airtableText.invalidAccessToken
);
cy.apiDeleteGDS(`cypress-${data.dsName}-airtable`);
});
it("Should verify the functionality of AirTable connection form.", () => {
@ -95,7 +139,7 @@ describe("Data source Airtable", () => {
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
"have.text",
"Authentication failed: Invalid personal access token"
airtableText.invalidAccessToken
);
cy.reload();
cy.apiUpdateGDS({
@ -123,11 +167,6 @@ describe("Data source Airtable", () => {
});
it("Should able to run the query with valid conection", () => {
const airTable_apiKey = Cypress.env("airTable_apikey");
const airTable_baseId = Cypress.env("airtabelbaseId");
const airTable_tableName = Cypress.env("airtable_tableName");
const airTable_recordID = Cypress.env("airtable_recordId");
cy.apiCreateGDS(
`${Cypress.env("server_host")}/api/data-sources`,
`cypress-${data.dsName}-airtable`,

View file

@ -27,7 +27,7 @@ describe("Data sources", () => {
.replaceAll("[^A-Za-z]", "");
});
it.skip("Should verify elements on connection form", () => {
it("Should verify elements on connection form with validation", () => {
cy.log(process.env.NODE_ENV);
cy.log(postgreSqlText.allDatabase());
cy.get(commonSelectors.globalDataSourceIcon).click();
@ -81,30 +81,147 @@ describe("Data sources", () => {
`cypress-${data.dataSourceName}-postgresql`
);
cy.get(postgreSqlSelector.labelHost).verifyVisibleElement(
cy.get(
dataSourceSelector.dropdownLabel(postgreSqlText.labelConnectionType)
).verifyVisibleElement("have.text", postgreSqlText.labelConnectionType);
cy.get(dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType))
.should("be.visible")
.click();
cy.contains(
`[id*="react-select-"]`,
postgreSqlText.connectionStringOption
).click();
cy.get(
dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType)
).should("be.visible");
cy.get(
dataSourceSelector.labelFieldName(postgreSqlText.connectionStringOption)
).verifyVisibleElement(
"have.text",
postgreSqlText.labelHost
`${postgreSqlText.connectionStringOption}*`
);
cy.get(postgreSqlSelector.labelPort).verifyVisibleElement(
cy.get(postgreSqlSelector.labelEncryptedText).verifyVisibleElement(
"have.text",
postgreSqlText.labelPort
postgreSqlText.labelEncrypted
);
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).should(
"be.visible"
);
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).click();
cy.verifyRequiredFieldValidation(
postgreSqlText.connectionStringOption,
"rgb(226, 99, 103)"
);
cy.get(
dataSourceSelector.textField(postgreSqlText.connectionStringOption)
).should("be.visible");
cy.get(postgreSqlSelector.labelIpWhitelist).verifyVisibleElement(
"have.text",
postgreSqlText.whiteListIpText
);
cy.get(postgreSqlSelector.buttonCopyIp).verifyVisibleElement(
"have.text",
postgreSqlText.textCopy
);
cy.get(postgreSqlSelector.linkReadDocumentation).verifyVisibleElement(
"have.text",
postgreSqlText.readDocumentation
);
cy.get(postgreSqlSelector.buttonTestConnection)
.verifyVisibleElement(
"have.text",
postgreSqlText.buttonTextTestConnection
)
.click();
cy.get(postgreSqlSelector.connectionFailedText).verifyVisibleElement(
"have.text",
postgreSqlText.couldNotConnect
);
cy.get(postgreSqlSelector.buttonSave)
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
.and("be.disabled");
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
"have.text",
postgreSqlText.unableAcquireConnectionAlertText
);
cy.get(dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType))
.should("be.visible")
.click();
cy.contains(
`[id*="react-select-"]`,
postgreSqlText.manualConnectionOption
).click();
cy.get(
dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType)
).should("be.visible");
const requiredFields = [
postgreSqlText.labelHost,
postgreSqlText.labelPort,
postgreSqlText.labelUserName,
postgreSqlText.labelPassword,
];
const sections = [
postgreSqlText.labelHost,
postgreSqlText.labelPort,
postgreSqlText.labelDbName,
postgreSqlText.labelUserName,
postgreSqlText.labelPassword,
postgreSqlText.labelConnectionOptions,
];
sections.forEach((section) => {
if (section === postgreSqlText.labelConnectionOptions) {
cy.get(dataSourceSelector.keyInputField(section, 0)).should(
"be.visible"
);
cy.get(dataSourceSelector.valueInputField(section, 0)).should(
"be.visible"
);
cy.get(dataSourceSelector.deleteButton(section, 0)).should(
"be.visible"
);
cy.get(dataSourceSelector.addMoreButton(section)).should("be.visible");
} else if (requiredFields.includes(section)) {
cy.get(dataSourceSelector.labelFieldName(section)).verifyVisibleElement(
"have.text",
`${section}*`
);
cy.get(dataSourceSelector.textField(section)).should("be.visible");
if (section === postgreSqlText.labelPassword) {
cy.get(
dataSourceSelector.button(postgreSqlText.editButtonText)
).click();
cy.verifyRequiredFieldValidation(section, "rgb(215, 45, 57)");
} else {
cy.get(dataSourceSelector.textField(section)).click();
cy.get(commonSelectors.textField(section)).should(
"have.css",
"border-color",
"rgba(0, 0, 0, 0)"
);
cy.get(dataSourceSelector.textField(section))
.type("123")
.clear()
.blur();
cy.verifyRequiredFieldValidation(section, "rgb(215, 45, 57)");
}
} else {
cy.get(dataSourceSelector.labelFieldName(section)).verifyVisibleElement(
"have.text",
section
);
cy.get(dataSourceSelector.textField(section)).should("be.visible");
}
});
cy.get(postgreSqlSelector.labelSsl).verifyVisibleElement(
"have.text",
postgreSqlText.labelSSL
);
cy.get(postgreSqlSelector.labelDbName).verifyVisibleElement(
"have.text",
postgreSqlText.labelDbName
);
cy.get(postgreSqlSelector.labelUserName).verifyVisibleElement(
"have.text",
postgreSqlText.labelUserName
);
cy.get(postgreSqlSelector.labelPassword).verifyVisibleElement(
"have.text",
postgreSqlText.labelPassword
);
cy.get(postgreSqlSelector.sslToggleInput).should("be.visible");
cy.get(postgreSqlSelector.labelSSLCertificate).verifyVisibleElement(
"have.text",
postgreSqlText.sslCertificate
@ -132,72 +249,85 @@ describe("Data sources", () => {
"have.text",
postgreSqlText.couldNotConnect
);
cy.get(postgreSqlSelector.buttonSave).verifyVisibleElement(
cy.get(postgreSqlSelector.buttonSave)
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
.and("be.disabled");
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
"have.text",
postgreSqlText.buttonTextSave
"connect ECONNREFUSED 127.0.0.1:5432"
);
cy.get(dataSourceSelector.connectionAlertText).should("be.visible");
deleteDatasource(`cypress-${data.dataSourceName}-postgresql`);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-postgresql`);
});
it.skip("Should verify the functionality of PostgreSQL connection form.", () => {
selectAndAddDataSource(
"databases",
postgreSqlText.postgreSQL,
data.dataSourceName
it("Should verify the functionality of PostgreSQL connection form.", () => {
cy.get(commonSelectors.globalDataSourceIcon).click();
cy.apiCreateGDS(
`${Cypress.env("server_host")}/api/data-sources`,
`cypress-${data.dataSourceName}-manual-pgsql`,
"postgresql",
[
{ key: "connection_type", value: "manual", encrypted: false },
{ key: "host", value: `${Cypress.env("pg_host")}`, encrypted: false },
{ key: "port", value: 5432, encrypted: false },
{ key: "ssl_enabled", value: false, encrypted: false },
{ key: "database", value: "postgres", encrypted: false },
{ key: "ssl_certificate", value: "none", encrypted: false },
{
key: "username",
value: `${Cypress.env("pg_user")}`,
encrypted: false,
},
{
key: "password",
value: `${Cypress.env("pg_password")}`,
encrypted: true,
},
{ key: "ca_cert", value: null, encrypted: true },
{ key: "client_key", value: null, encrypted: true },
{ key: "client_cert", value: null, encrypted: true },
{ key: "root_cert", value: null, encrypted: true },
{ key: "connection_string", value: null, encrypted: true },
]
);
fillDataSourceTextField(
postgreSqlText.labelHost,
postgreSqlText.placeholderEnterHost,
Cypress.env("pg_host")
);
fillDataSourceTextField(
postgreSqlText.labelPort,
postgreSqlText.placeholderEnterPort,
"5432"
);
cy.get('[data-cy="-toggle-input"]').then(($el) => {
if ($el.is(":checked")) {
cy.get('[data-cy="-toggle-input"]').uncheck();
}
});
fillDataSourceTextField(
postgreSqlText.labelDbName,
postgreSqlText.placeholderNameOfDB,
"postgres"
);
fillDataSourceTextField(
postgreSqlText.labelUserName,
postgreSqlText.placeholderEnterUserName,
"postgres"
);
fillDataSourceTextField(
postgreSqlText.labelPassword,
"**************",
Cypress.env("pg_password")
);
cy.get(
dataSourceSelector.dataSourceNameButton(
`cypress-${data.dataSourceName}-manual-pgsql`
)
)
.should("be.visible")
.click();
cy.get(postgreSqlSelector.buttonTestConnection).click();
cy.get(postgreSqlSelector.textConnectionVerified, {
timeout: 10000,
}).should("have.text", postgreSqlText.labelConnectionVerified);
cy.get(postgreSqlSelector.buttonSave).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
postgreSqlText.toastDSSaved
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-manual-pgsql`);
cy.reload();
cy.apiCreateGDS(
`${Cypress.env("server_host")}/api/data-sources`,
`cypress-${data.dataSourceName}-string-pgsql`,
"postgresql",
[
{ key: "connection_type", value: "string", encrypted: false },
{
key: "connection_string",
value: `${Cypress.env("pg_string")}`,
encrypted: true,
},
]
);
cy.get(commonSelectors.globalDataSourceIcon).click();
cy.get(
`[data-cy="cypress-${data.dataSourceName}-postgresql-button"]`
).verifyVisibleElement(
"have.text",
`cypress-${data.dataSourceName}-postgresql`
);
deleteDatasource(`cypress-${data.dataSourceName}-postgresql`);
dataSourceSelector.dataSourceNameButton(
`cypress-${data.dataSourceName}-string-pgsql`
)
)
.should("be.visible")
.click();
cy.get(postgreSqlSelector.buttonTestConnection).click();
cy.get(postgreSqlSelector.textConnectionVerified, {
timeout: 10000,
}).should("have.text", postgreSqlText.labelConnectionVerified);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-string-pgsql`);
});
it.skip("Should verify elements of the Query section.", () => {

View file

@ -426,6 +426,7 @@ describe("Data source Rest API", () => {
});
}
);
cy.apiDeleteApp(`${fake.companyName}-restAPI-CURD-App`);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
});
it("Should verify response for basic authentication type connection", () => {
@ -488,6 +489,7 @@ describe("Data source Rest API", () => {
method: "GET",
urlSuffix: "/basic-auth/invaliduser/invalidpass",
});
cy.apiDeleteApp(`${fake.companyName}-restAPI-Basic-App`);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
});
it("Should verify response for bearer authentication type connection", () => {
@ -545,6 +547,7 @@ describe("Data source Rest API", () => {
urlSuffix: "/bearer",
expectedResponseShape: { authenticated: true, token: "my-token-123" },
});
cy.apiDeleteApp(`${fake.companyName}-restAPI-Bearer-App`);
cy.intercept("GET", "api/data_sources?**").as("datasource");
cy.apiCreateGDS(
`${Cypress.env("server_host")}/api/data-sources`,
@ -597,6 +600,7 @@ describe("Data source Rest API", () => {
method: "GET",
urlSuffix: "/bearer",
});
cy.apiDeleteApp(`${fake.companyName}-restAPI-Bearer-invalid`);
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
});
it.skip("Should verify response for authentication code grant type connection", () => {