diff --git a/.version b/.version index 5506598e0f..f82db28d03 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.32.3 +2.32.5 diff --git a/cypress-tests/cypress-app-builder.config.js b/cypress-tests/cypress-app-builder.config.js index 756ef58abe..5d291f59c1 100644 --- a/cypress-tests/cypress-app-builder.config.js +++ b/cypress-tests/cypress-app-builder.config.js @@ -76,8 +76,8 @@ module.exports = defineConfig({ experimentalRunAllSpecs: true, baseUrl: "http://localhost:8082", specPattern: [ - "cypress/e2e/happypath/appbuilder/commonTestcases/**/*.cy.js", - "cypress/e2e/happypath/appbuilder/ceTestcases/**/*.cy.js" + "cypress/e2e/happyPath/appbuilder/commonTestcases/**/*.cy.js", + "cypress/e2e/happyPath/appbuilder/ceTestcases/**/*.cy.js" ], numTestsKeptInMemory: 1, redirectionLimit: 7, diff --git a/cypress-tests/cypress-marketplace.config.js b/cypress-tests/cypress-marketplace.config.js index f5e8661b1d..967e938248 100644 --- a/cypress-tests/cypress-marketplace.config.js +++ b/cypress-tests/cypress-marketplace.config.js @@ -76,8 +76,8 @@ module.exports = defineConfig({ experimentalRunAllSpecs: true, baseUrl: "http://localhost:8082", specPattern: [ - "cypress/e2e/happypath/marketplace/commonTestcases/**/*.cy.js", - "cypress/e2e/happypath/marketplace/ceTestcases/**/*.cy.js" + "cypress/e2e/happyPath/marketplace/commonTestcases/**/*.cy.js", + "cypress/e2e/happyPath/marketplace/ceTestcases/**/*.cy.js" ], numTestsKeptInMemory: 1, redirectionLimit: 7, diff --git a/cypress-tests/cypress-workspace.config.js b/cypress-tests/cypress-workspace.config.js index 0508e9910f..e22e022a9a 100644 --- a/cypress-tests/cypress-workspace.config.js +++ b/cypress-tests/cypress-workspace.config.js @@ -76,8 +76,8 @@ module.exports = defineConfig({ experimentalRunAllSpecs: true, baseUrl: "http://localhost:8082", specPattern: [ - "cypress/e2e/happypath/platform/commonTestcases/**/*.cy.js", - "cypress/e2e/happypath/platform/ceTestcases/**/*.cy.js" + "cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js", + "cypress/e2e/happyPath/platform/ceTestcases/**/*.cy.js" ], numTestsKeptInMemory: 1, redirectionLimit: 15, diff --git a/cypress-tests/cypress/constants/selectors/common.js b/cypress-tests/cypress/constants/selectors/common.js index 6aab19607c..7243adb353 100644 --- a/cypress-tests/cypress/constants/selectors/common.js +++ b/cypress-tests/cypress/constants/selectors/common.js @@ -83,7 +83,7 @@ export const commonSelectors = { workspaceSettings: '[data-cy="workspace-settings"]', manageUsersOption: '[data-cy="users-list-item"]', manageGroupsOption: '[data-cy="groups-list-item"]', - manageSSOOption: '[data-cy="sso-list-item"]', + manageSSOOption: '[data-cy="workspace-login-list-item"]', workspaceVariableOption: '[data-cy="workspace-variables-list-item"]', clearFilterButton: '[data-cy="clear-filter-button"]', userStatusSelect: '[data-cy="user-status-select-continer"]', @@ -257,6 +257,7 @@ export const commonSelectors = { }, defaultModalTitle: '[data-cy="modal-title"]', workspaceConstantsIcon: '[data-cy="icon-workspace-constants"]', + confirmationButton: '[data-cy="confirmation-button"]', }; export const commonWidgetSelector = { diff --git a/cypress-tests/cypress/constants/selectors/manageSSO.js b/cypress-tests/cypress/constants/selectors/manageSSO.js index 2c0b0e5d0e..6ec26231b1 100644 --- a/cypress-tests/cypress/constants/selectors/manageSSO.js +++ b/cypress-tests/cypress/constants/selectors/manageSSO.js @@ -1,7 +1,6 @@ export const ssoSelector = { pagetitle: "[data-cy=manage-sso-page-title]", - generalSettingsElements: { - generalSettings: '[data-cy="general-settings-list-item"]', + workspaceLoginPage: { enableSignupLabel: '[data-cy="enable-sign-up-label"]', helperText: "[data-cy=enable-sign-up-helper-text]", allowDefaultSSOLabel: '[data-cy="allow-default-sso-label"]', @@ -10,16 +9,22 @@ export const ssoSelector = { allowedDomainHelperText: '[data-cy="allowed-domain-helper-text"]', workspaceLoginUrl: '[data-cy="workspace-login-url-label"]', workspaceLoginHelpText: '[data-cy="workspace-login-help-text"]', + ssoHeader: '[data-cy="sso-header"]', + instanceSSOHelperText: '[data-cy="instance-sso-helper-text"]', + googleLabel: '[data-cy="google-label"]', + githubLabel: '[data-cy="github-label"]', + defaultSSO: '[data-cy="instance-sso-card"]', }, cardTitle: "[data-cy=card-title]", enableSignUpToggle: '[data-cy="enable-sign-up-toggle"]', - allowDefaultSSOToggle: '[data-cy="allow-default-sso-toggle"]', + allowDefaultSSOToggle: + '[style="padding-left: 0px; margin-bottom: 1px;"] > .switch > .slider', defaultSSOImage: '[data-cy="default-sso-status-image"]', - allowedDomainInput: "[data-cy=allowed-domain-input]", + allowedDomainInput: '[data-cy="allowed-domains"]', workspaceLoginUrl: '[data-cy="workspace-login-url"]', cancelButton: "[data-cy=cancel-button]", saveButton: "[data-cy=save-button]", - google: '[data-cy="google-list-item"]', + google: '[data-cy="google-sso-card"]', googleEnableToggle: '[data-cy="google-enable-toggle"]', statusLabel: "[data-cy=status-label]", clientIdLabel: "[data-cy=client-id-label]", @@ -29,9 +34,9 @@ export const ssoSelector = { googleTile: '[data-cy="google-sign-in-text"]', googleIcon: "[data-cy=google-sso-icon]", googleSSOText: "[data-cy=google-sso-text]", - git: '[data-cy="github-list-item"]', + git: '[data-cy="github-sso-card"]', gitEnableToggle: '[data-cy="github-toggle-input"]', - githubLabel: '[data-cy="github-toggle-label"]', + githubLabel: '[data-cy="github-label"]', clientSecretLabel: "[data-cy=client-secret-label]", encriptedLabel: "[data-cy=encripted-label]", clientSecretInput: "[data-cy=client-secret-input]", @@ -52,4 +57,6 @@ export const ssoSelector = { passwordLoginToggleLbale: '[data-cy="label-password-login"]', alertText: '[data-cy="alert-text"]', disablePasswordHelperText: '[data-cy="disable-password-helper-text"]', + defaultGoogle: '[data-cy="dropdown-options-google"]', + defaultGithub: '[data-cy="dropdown-options-git"]', }; diff --git a/cypress-tests/cypress/constants/texts/manageSSO.js b/cypress-tests/cypress/constants/texts/manageSSO.js index 7736de3728..c1a95e7179 100644 --- a/cypress-tests/cypress/constants/texts/manageSSO.js +++ b/cypress-tests/cypress/constants/texts/manageSSO.js @@ -1,7 +1,6 @@ export const ssoText = { - pagetitle: " SSO", - generalSettingsElements: { - generalSettings: "General Settings", + pagetitle: " Workspace login", + workspaceLoginPage: { enableSignupLabel: "Enable Signup", helperText: "New account will be created for user's first time SSO sign in", allowDefaultSSOLabel: "Allow default SSO", @@ -12,34 +11,39 @@ export const ssoText = { "Support multiple domains. Enter domain names separated by comma. example: tooljet.com,tooljet.io,yourorganization.com", workspaceLoginUrl: "Login URL", workspaceLoginHelpText: "Use this URL to login directly to this workspace", + ssoHeader: "SSO", + instanceSSOHelperText: "Display default SSO for workspace URL login", + googleLabel: "Google", + githubLabel: "GitHub", + defaultSSO: "Default SSO", }, cancelButton: "Cancel", saveButton: "Save changes", allowedDomain: "tooljet.io,gmail.com", - ssoToast: "updated sso configurations", + ssoToast: "Organization settings have been updated", ssoToast2: "updated SSO configurations", googleTitle: "Google", enabledLabel: "Enabled", - googleEnabledToast: "Enabled Google SSO", + googleSSOToast: "Saved Google SSO configurations", disabledLabel: "Disabled", googleDisableToast: "Disabled Google SSO", googleSSOText: "Sign in with Google", - clientIdLabel: "Client Id", + clientIdLabel: "Client ID", redirectUrlLabel: "Redirect URL", clientId: "24567098-mklj8t20za1smb2if.apps.googleusercontent.com", testClientId: "12345-client-id-.apps.googleusercontent.com", gitTitle: "GitHub", - clientSecretLabel: "Client Secret", + clientSecretLabel: "Client secret", encriptedLabel: "Encrypted", gitEnabledToast: "Enabled GitHub SSO", - gitDisabledToast: "Disabled GitHub SSO", + gitSSOToast: "Saved Git SSO configurations", gitSignInText: "Sign in with GitHub", passwordTitle: "Password Login", passwordEnabledToast: "Enabled Password login", - passwordDisabledToast: "Disabled Password login", + passwordDisabledToast: "Password login disabled successfully!", passwordDisableWarning: - "Users won’t be able to login via username and password if password login is disabled. Please make sure that you have setup other authentication methods before disabling password login, do you want to continue?", - hostNameLabel: "Host Name", + "Disable password login only if you have configured SSO or else you will get locked out.", + hostNameLabel: "Host name", hostNameHelpText: "Required if GitHub is self hosted", hostName: "Tooljet", signInHeader: "Sign in", @@ -51,8 +55,8 @@ export const ssoText = { gitSignUpText: "Sign up with GitHub", gitUserStatusToast: "GitHub login failed - User does not exist in the workspace", - passwordLoginToggleLbale: "Password login ", + passwordLoginToggleLbale: "Password login", alertText: "Danger zone", disablePasswordHelperText: - "Disable password login only if your SSO is configured otherwise you will get logged out.", + "Disable password login only if your SSO is configured otherwise you will get locked out", }; diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js index d6e6a7e8f2..dda3cd887c 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/authentication/forgotPassword.cy.js @@ -1,5 +1,5 @@ -import { commonSelectors } from "../../constants/selectors/common"; -import { commonText } from "../../constants/texts/common"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; import { fake } from "Fixtures/fake"; import { addNewUser } from "Support/utils/onboarding"; import { logout } from "Support/utils/common"; diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js index 48c40fde84..d91a207630 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageSSO.cy.js @@ -11,10 +11,11 @@ describe("Manage SSO for multi workspace", () => { const envVar = Cypress.env("environment"); beforeEach(() => { cy.defaultWorkspaceLogin(); + SSO.setSSOStatus("My workspace", "google", false); + SSO.setSSOStatus("My workspace", "git", false); }); it("Should verify General settings page elements", () => { common.navigateToManageSSO(); - cy.get(commonSelectors.breadcrumbTitle).should(($el) => { expect($el.contents().first().text().trim()).to.eq( commonText.breadcrumbworkspaceSettingTitle @@ -27,14 +28,12 @@ describe("Manage SSO for multi workspace", () => { cy.get(ssoSelector.cardTitle).verifyVisibleElement( "have.text", - ssoText.generalSettingsElements.generalSettings + "Workspace login" ); for (const elements in ssoSelector.generalSettingsElements) { - cy.get( - ssoSelector.generalSettingsElements[elements] - ).verifyVisibleElement( + cy.get(ssoSelector.workspaceLoginPage[elements]).verifyVisibleElement( "have.text", - ssoText.generalSettingsElements[elements] + ssoText.workspaceLoginPage[elements] ); } cy.get(ssoSelector.enableSignUpToggle).should("be.visible"); @@ -51,12 +50,6 @@ describe("Manage SSO for multi workspace", () => { ssoText.saveButton ); - SSO.generalSettings(); - - cy.get(ssoSelector.alertText).verifyVisibleElement( - "have.text", - ssoText.alertText - ); cy.get(ssoSelector.passwordEnableToggle).should("be.visible"); cy.get(ssoSelector.passwordLoginToggleLbale).verifyVisibleElement( "have.text", @@ -67,35 +60,32 @@ describe("Manage SSO for multi workspace", () => { ssoText.disablePasswordHelperText ); - SSO.passwordPageElements(); + SSO.generalSettings(); }); it("Should verify Google SSO page elements", () => { common.navigateToManageSSO(); cy.get(ssoSelector.google).should("be.visible").click(); - cy.get(ssoSelector.cardTitle).verifyVisibleElement( - "have.text", - ssoText.googleTitle - ); + cy.get(ssoSelector.cardTitle) + .eq(1) + .verifyVisibleElement("have.text", ssoText.googleTitle); cy.get(ssoSelector.googleEnableToggle).should("be.visible"); cy.get(ssoSelector.clientIdLabel).verifyVisibleElement( "have.text", ssoText.clientIdLabel ); cy.get(ssoSelector.clientIdInput).should("be.visible"); - cy.get(ssoSelector.cancelButton).verifyVisibleElement( - "have.text", - ssoText.cancelButton - ); - cy.get(ssoSelector.saveButton).verifyVisibleElement( - "have.text", - ssoText.saveButton - ); + cy.get(ssoSelector.cancelButton) + .eq(1) + .verifyVisibleElement("have.text", ssoText.cancelButton); + cy.get(ssoSelector.saveButton) + .eq(1) + .verifyVisibleElement("have.text", ssoText.saveButton); SSO.googleSSOPageElements(); - SSO.disableDefaultSSO(); - SSO.visitWorkspaceLoginPage(); - + SSO.defaultSSO("My workspace", false); + cy.logoutApi(); + cy.visit("/login/my-workspace"); cy.get(ssoSelector.googleIcon).should("be.visible"); cy.get(ssoSelector.googleSSOText).verifyVisibleElement( "have.text", @@ -104,6 +94,8 @@ describe("Manage SSO for multi workspace", () => { }); it("Should verify Git SSO page elements", () => { + SSO.defaultSSO("My workspace", true); + common.navigateToManageSSO(); cy.get(ssoSelector.git).should("be.visible").click(); @@ -139,27 +131,27 @@ describe("Manage SSO for multi workspace", () => { ssoText.encriptedLabel ); cy.get(ssoSelector.clientSecretInput).should("be.visible"); - cy.get(ssoSelector.cancelButton).verifyVisibleElement( - "have.text", - ssoText.cancelButton - ); - cy.get(ssoSelector.saveButton).verifyVisibleElement( - "have.text", - ssoText.saveButton - ); + cy.get(ssoSelector.cancelButton) + .eq(1) + .verifyVisibleElement("have.text", ssoText.cancelButton); + cy.get(ssoSelector.saveButton) + .eq(1) + .verifyVisibleElement("have.text", ssoText.saveButton); SSO.gitSSOPageElements(); - SSO.visitWorkspaceLoginPage(); + SSO.defaultSSO("My workspace", false); + cy.logoutApi(); + cy.visit("/login/my-workspace"); - cy.get(ssoSelector.googleIcon).should("be.visible"); - cy.get(ssoSelector.googleSSOText).verifyVisibleElement( + cy.get(ssoSelector.gitIcon).should("be.visible"); + cy.get(ssoSelector.gitSignInText).verifyVisibleElement( "have.text", - ssoText.googleSSOText + ssoText.gitSignInText ); }); if (envVar === "Community") { - it("Should verify the workspace login page", () => { + it.skip("Should verify the workspace login page", () => { data.workspaceName = fake.companyName.toLowerCase(); cy.apiLogin(); cy.apiCreateWorkspace(data.workspaceName, data.workspaceName); diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js index 899fbb4bb2..e41aeee42b 100644 --- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/manageUsers.cy.js @@ -9,7 +9,7 @@ import { dashboardSelector } from "Selectors/dashboard"; import { updateWorkspaceName } from "Support/utils/userPermissions"; import { groupsSelector } from "Selectors/manageGroups"; import { groupsText } from "Texts/manageGroups"; -import { addNewUser } from "../../support/utils/onboarding"; +import { addNewUser } from "Support/utils/onboarding"; const data = {}; data.groupName = fake.firstName.replaceAll("[^A-Za-z]", ""); diff --git a/cypress-tests/cypress/support/utils/common.js b/cypress-tests/cypress/support/utils/common.js index 3dc04c68ec..c4c1b602bd 100644 --- a/cypress-tests/cypress/support/utils/common.js +++ b/cypress-tests/cypress/support/utils/common.js @@ -275,3 +275,11 @@ export const releaseApp = () => { cy.verifyToastMessage(commonSelectors.toastMessage, "Version v1 released"); cy.wait(1000); }; + +export const verifyTooltipDisabled = (selector, message) => { + cy.get(selector) + .trigger("mouseover", { force: true }) + .then(() => { + cy.get(".tooltip-inner").last().should("have.text", message); + }); +}; \ No newline at end of file diff --git a/cypress-tests/cypress/support/utils/manageSSO.js b/cypress-tests/cypress/support/utils/manageSSO.js index 7c9a724888..119bd15d6a 100644 --- a/cypress-tests/cypress/support/utils/manageSSO.js +++ b/cypress-tests/cypress/support/utils/manageSSO.js @@ -6,207 +6,190 @@ import { commonText } from "Texts/common"; import { dashboardSelector } from "Selectors/dashboard"; export const generalSettings = () => { - cy.get(ssoSelector.enableSignUpToggle).then(($el) => { - if ($el.is(":checked")) { - cy.get(ssoSelector.enableSignUpToggle).uncheck(); - cy.get(ssoSelector.cancelButton).click(); - cy.get(ssoSelector.enableSignUpToggle).should("be.checked"); - } else { - cy.get(ssoSelector.enableSignUpToggle).check(); - cy.get(ssoSelector.cancelButton).click(); - cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked"); - cy.get(ssoSelector.enableSignUpToggle).check(); - } - cy.get(ssoSelector.allowDefaultSSOToggle).then(($el) => { - if ($el.is(":checked")) { - cy.get(ssoSelector.allowDefaultSSOToggle).uncheck(); - cy.get(ssoSelector.cancelButton).click(); - cy.get(ssoSelector.allowDefaultSSOToggle).should("not.be.checked"); - } else { - cy.get(ssoSelector.allowDefaultSSOToggle).check(); - cy.get(ssoSelector.cancelButton).click(); - cy.get(ssoSelector.allowDefaultSSOToggle).should("be.checked"); - cy.get(ssoSelector.allowDefaultSSOToggle).check(); - } - }); - cy.clearAndType(ssoSelector.allowedDomainInput, ssoText.allowedDomain); - cy.get(ssoSelector.saveButton).click(); - cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast); - }); + cy.get(ssoSelector.enableSignUpToggle).check(); + cy.get(ssoSelector.cancelButton).click(); + cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked"); + cy.get(ssoSelector.enableSignUpToggle).check(); + cy.get(ssoSelector.saveButton).click(); + cy.get(ssoSelector.enableSignUpToggle).should("be.checked"); + + cy.get(ssoSelector.enableSignUpToggle).uncheck(); + cy.get(ssoSelector.saveButton).click(); + cy.get(ssoSelector.enableSignUpToggle).should("not.be.checked"); + + cy.get(ssoSelector.workspaceLoginPage.defaultSSO).click(); + cy.get(ssoSelector.defaultGoogle).verifyVisibleElement("have.text", "Google"); + cy.get(ssoSelector.defaultGithub).verifyVisibleElement("have.text", "Github"); + + cy.clearAndType(ssoSelector.allowedDomainInput, ssoText.allowedDomain); + cy.get(ssoSelector.saveButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast); + + cy.get(ssoSelector.passwordEnableToggle).uncheck(); + cy.get(commonSelectors.modalComponent).should("be.visible"); + cy.get(commonSelectors.modalMessage).verifyVisibleElement( + "have.text", + ssoText.passwordDisableWarning + ); + cy.get(commonSelectors.cancelButton).eq(1).click(); + cy.get(ssoSelector.passwordEnableToggle).uncheck(); + cy.get(commonSelectors.confirmationButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + ssoText.passwordDisabledToast + ); + + cy.get(ssoSelector.passwordEnableToggle).check(); + cy.get(commonSelectors.saveButton).click(); + + cy.get(ssoSelector.allowDefaultSSOToggle).click(); + + cy.get(ssoSelector.passwordEnableToggle).should("be.disabled"); + + common.verifyTooltipDisabled( + ssoSelector.passwordEnableToggle, + "Password login cannot be disabled unless SSO is configured" + ); + + cy.get(ssoSelector.allowDefaultSSOToggle).click(); }; export const googleSSOPageElements = () => { - cy.get(ssoSelector.googleEnableToggle).then(($el) => { - if ($el.is(":checked")) { - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - cy.get(ssoSelector.googleEnableToggle).uncheck(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.googleDisableToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.disabledLabel - ); - cy.get(ssoSelector.googleEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.googleEnabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - } else { - cy.get(ssoSelector.googleEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.googleEnabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); + cy.get(ssoSelector.googleEnableToggle).click(); + cy.get(ssoSelector.saveButton).eq(1).click(); - cy.get(ssoSelector.googleEnableToggle).uncheck(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.googleDisableToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.disabledLabel - ); - cy.get(ssoSelector.googleEnableToggle).check(); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - } - cy.clearAndType(ssoSelector.clientIdInput, ssoText.testClientId); - cy.get(ssoSelector.cancelButton).click(); - cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId); - cy.get(ssoSelector.saveButton).click(); - cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast2); - cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId); - }); + cy.get('[data-cy="modal-title"]').verifyVisibleElement( + "have.text", + "Enable Google" + ); + cy.get('[data-cy="modal-close-button"]').should("be.visible"); + cy.get('[data-cy="modal-message"]').verifyVisibleElement( + "have.text", + "Enabling Google at the workspace level will override any Google configurations set at the instance level." + ); + cy.get('[data-cy="confirmation-text"]').verifyVisibleElement( + "have.text", + "Are you sure you want to continue?" + ); + cy.get('[data-cy="cancel-button"]') + .eq(2) + .verifyVisibleElement("have.text", "Cancel"); + cy.get('[data-cy="enable-button"]').verifyVisibleElement( + "have.text", + "Enable" + ); + + cy.get('[data-cy="cancel-button"]').eq(2).click(); + cy.get(ssoSelector.googleEnableToggle).click(); + cy.get(ssoSelector.saveButton).eq(1).click(); + cy.get('[data-cy="enable-button"]').click(); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast); + + cy.get(ssoSelector.statusLabel).verifyVisibleElement( + "have.text", + ssoText.enabledLabel + ); + cy.get('[data-cy="redirect-url-label"]').verifyVisibleElement( + "have.text", + ssoText.redirectUrlLabel + ); + cy.get('[data-cy="redirect-url"]').should("be.visible"); + cy.get('[data-cy="copy-icon"]').should("be.visible"); + + cy.get(ssoSelector.googleEnableToggle).click(); + cy.get(ssoSelector.saveButton).eq(1).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast); + cy.get(ssoSelector.statusLabel).verifyVisibleElement( + "have.text", + ssoText.disabledLabel + ); + + cy.clearAndType(ssoSelector.clientIdInput, ssoText.testClientId); + cy.get(ssoSelector.cancelButton).eq(1).click(); + cy.get(ssoSelector.google).click(); + cy.get(ssoSelector.clientIdInput).should("have.value", ""); + cy.get(ssoSelector.googleEnableToggle).click(); + cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId); + cy.get(ssoSelector.saveButton).eq(1).click(); + cy.get('[data-cy="enable-button"]').click(); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.googleSSOToast); + cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId); }; export const gitSSOPageElements = () => { - cy.get(ssoSelector.gitEnableToggle).then(($el) => { - if ($el.is(":checked")) { - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - cy.get(ssoSelector.gitEnableToggle).uncheck(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.gitDisabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.disabledLabel - ); - cy.get(ssoSelector.gitEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.gitEnabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - } else { - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.disabledLabel - ); - cy.get(ssoSelector.gitEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.gitEnabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - cy.get(ssoSelector.gitEnableToggle).uncheck(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.gitDisabledToast - ); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.disabledLabel - ); - cy.get(ssoSelector.gitEnableToggle).check(); - cy.get(ssoSelector.statusLabel).verifyVisibleElement( - "have.text", - ssoText.enabledLabel - ); - } - cy.clearAndType(ssoSelector.hostNameInput, ssoText.hostName); - cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId); - cy.clearAndType(ssoSelector.clientSecretInput, ssoText.testClientId); - cy.get(ssoSelector.saveButton).click(); - cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.ssoToast2); - cy.get(ssoSelector.hostNameInput).should("have.value", ssoText.hostName); - cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId); - cy.get(ssoSelector.clientSecretInput).should( - "have.value", - ssoText.testClientId - ); - }); -}; + cy.get(ssoSelector.gitEnableToggle).click(); -export const passwordPageElements = () => { - cy.get(ssoSelector.passwordEnableToggle).then(($el) => { - if ($el.is(":checked")) { - cy.get(ssoSelector.passwordEnableToggle).uncheck(); - cy.get(commonSelectors.modalComponent).should("be.visible"); - cy.get(commonSelectors.modalMessage).verifyVisibleElement( - "have.text", - ssoText.passwordDisableWarning - ); - cy.get(commonSelectors.buttonSelector("Yes")).click(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.passwordDisabledToast - ); + cy.get(ssoSelector.saveButton).eq(1).click(); - cy.get(ssoSelector.passwordEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.passwordEnabledToast - ); - } else { - cy.get(ssoSelector.passwordEnableToggle).check(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.passwordEnabledToast - ); + cy.get('[data-cy="modal-title"]').verifyVisibleElement( + "have.text", + "Enable Git" + ); + cy.get('[data-cy="modal-close-button"]').should("be.visible"); + cy.get('[data-cy="modal-message"]').verifyVisibleElement( + "have.text", + "Enabling Git at the workspace level will override any Git configurations set at the instance level." + ); + cy.get('[data-cy="confirmation-text"]').verifyVisibleElement( + "have.text", + "Are you sure you want to continue?" + ); + cy.get('[data-cy="cancel-button"]') + .eq(2) + .verifyVisibleElement("have.text", "Cancel"); + cy.get('[data-cy="enable-button"]').verifyVisibleElement( + "have.text", + "Enable" + ); - cy.get(ssoSelector.passwordEnableToggle).uncheck(); - cy.verifyToastMessage( - commonSelectors.toastMessage, - ssoText.passwordDisabledToast - ); + cy.get('[data-cy="cancel-button"]').eq(2).click(); + cy.get(ssoSelector.gitEnableToggle).click(); + cy.get(ssoSelector.saveButton).eq(1).click(); + cy.get('[data-cy="enable-button"]').click(); - cy.get(ssoSelector.passwordEnableToggle).check(); - } - }); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast); + + cy.get(ssoSelector.statusLabel).verifyVisibleElement( + "have.text", + ssoText.enabledLabel + ); + + cy.get('[data-cy="redirect-url-label"]').verifyVisibleElement( + "have.text", + ssoText.redirectUrlLabel + ); + cy.get('[data-cy="redirect-url"]').should("be.visible"); + cy.get('[data-cy="copy-icon"]').should("be.visible"); + + cy.get(ssoSelector.gitEnableToggle).click(); + cy.get(ssoSelector.saveButton).eq(1).click(); + + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast); + cy.get(ssoSelector.statusLabel).verifyVisibleElement( + "have.text", + ssoText.disabledLabel + ); + + cy.get(ssoSelector.gitEnableToggle).click(); + cy.clearAndType(ssoSelector.hostNameInput, ssoText.hostName); + cy.clearAndType(ssoSelector.clientIdInput, ssoText.clientId); + cy.clearAndType(ssoSelector.clientSecretInput, ssoText.testClientId); + cy.get(ssoSelector.saveButton).eq(1).click(); + cy.get('[data-cy="enable-button"]').click(); + cy.verifyToastMessage(commonSelectors.toastMessage, ssoText.gitSSOToast); + cy.get(ssoSelector.hostNameInput).should("have.value", ssoText.hostName); + cy.get(ssoSelector.clientIdInput).should("have.value", ssoText.clientId); + cy.get(ssoSelector.clientSecretInput).should( + "have.value", + ssoText.testClientId + ); }; export const visitWorkspaceLoginPage = () => { - cy.get(ssoSelector.generalSettingsElements.generalSettings).click(); cy.get(ssoSelector.workspaceLoginUrl).then(($temp) => { const url = $temp.text(); common.logout(); - cy.wait(1000) + cy.wait(1000); cy.visit(url); }); }; @@ -264,7 +247,7 @@ export const workspaceLogin = (workspaceName) => { cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io"); cy.clearAndType(commonSelectors.passwordInputField, "password"); cy.get(commonSelectors.loginButton).click(); - cy.wait(2000) + cy.wait(2000); cy.get(commonSelectors.homePageLogo).should("be.visible"); cy.get(commonSelectors.workspaceName).verifyVisibleElement( "have.text", @@ -576,3 +559,35 @@ export const updateId = () => { sql: "update sso_configs set id='9628dee2-6fa9-4aca-9c98-ef950601c83e' where sso='git';", }); }; + +export const setSSOStatus = (workspaceName, ssoType, enabled) => { + let workspaceId; + + cy.task("updateId", { + dbconfig: Cypress.env("app_db"), + sql: `SELECT id FROM organizations WHERE name = '${workspaceName}'`, + }).then((resp) => { + workspaceId = resp.rows[0].id; + + cy.task("updateId", { + dbconfig: Cypress.env("app_db"), + sql: `SELECT * FROM sso_configs WHERE organization_id = '${workspaceId}' AND sso = '${ssoType}'`, + }).then((ssoConfigResp) => { + if (ssoConfigResp.rows.length > 0) { + cy.task("updateId", { + dbconfig: Cypress.env("app_db"), + sql: `UPDATE sso_configs SET enabled = ${enabled ? "true" : "false" + } WHERE organization_id = '${workspaceId}' AND sso = '${ssoType}'`, + }); + } + }); + }); +}; + +export const defaultSSO = (workspaceName, enabled) => { + cy.task("updateId", { + dbconfig: Cypress.env("app_db"), + sql: `UPDATE organizations SET inherit_sso = ${enabled ? "true" : "false" + } WHERE name = '${workspaceName}'`, + }); +}; diff --git a/frontend/.version b/frontend/.version index 5506598e0f..f82db28d03 100644 --- a/frontend/.version +++ b/frontend/.version @@ -1 +1 @@ -2.32.3 +2.32.5 diff --git a/frontend/src/Editor/Box.jsx b/frontend/src/Editor/Box.jsx index 21a45089c3..bb11eb38d6 100644 --- a/frontend/src/Editor/Box.jsx +++ b/frontend/src/Editor/Box.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useMemo, useContext, useRef, memo, useCallback } from 'react'; +import React, { useEffect, useState, useMemo, useContext, memo } from 'react'; import { Button } from './Components/Button'; import { Image } from './Components/Image'; import { Text } from './Components/Text'; @@ -42,7 +42,6 @@ import { Html } from './Components/Html'; import { ButtonGroup } from './Components/ButtonGroup'; import { CustomComponent } from './Components/CustomComponent/CustomComponent'; import { VerticalDivider } from './Components/verticalDivider'; -import { PDF } from './Components/PDF'; import { ColorPicker } from './Components/ColorPicker'; import { KanbanBoard } from './Components/KanbanBoard/KanbanBoard'; import { Kanban } from './Components/Kanban/Kanban'; @@ -68,6 +67,7 @@ import { EditorContext } from '@/Editor/Context/EditorContextWrapper'; import { useTranslation } from 'react-i18next'; import { useCurrentState } from '@/_stores/currentStateStore'; import { useAppInfo } from '@/_stores/appDataStore'; +import { isPDFSupported } from '@/_stores/utils'; export const AllComponents = { Button, @@ -112,7 +112,6 @@ export const AllComponents = { ButtonGroup, CustomComponent, VerticalDivider, - PDF, ColorPicker, KanbanBoard, Kanban, @@ -124,6 +123,14 @@ export const AllComponents = { BoundedBox, }; +/** + * Conditionally importing PDF component since importing it breaks app in older versions of browsers. + * refer: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#compatibility + **/ +if (isPDFSupported()) { + AllComponents.PDF = await import('./Components/PDF').then((module) => module.PDF); +} + export const Box = memo( ({ id, @@ -281,6 +288,9 @@ export const Box = memo( ...{ validationObject: component.definition.validation, currentState }, customResolveObjects: customResolvables, }); + + const shouldHideWidget = component.component === 'PDF' && !isPDFSupported(); + return ( - {!resetComponent ? ( + {!resetComponent && !shouldHideWidget ? ( { - return tableData.map((row) => ({ - ...row, - ...Object.fromEntries( - transformations.map((t) => [ - t.key, - resolveReferences(t.transformation, currentState, row[t.key], { cellValue: row[t.key], rowData: row }), - ]) - ), - })); + return tableData.map((row) => { + return { + ...row, + ...Object.fromEntries( + transformations.map(({ key, transformation }) => { + const nestedKeys = key.includes('.') && key.split('.'); + if (nestedKeys) { + // Single-level nested property + const [nestedKey, subKey] = nestedKeys; + const nestedObject = row[nestedKey]; + return [ + nestedKey, + { + ...nestedObject, + [subKey]: resolveReferences(transformation, currentState, row[key], { + cellValue: row?.[nestedKey]?.[subKey], + rowData: row, + }), + }, + ]; + } else { + // Non-nested property + return [ + key, + resolveReferences(transformation, currentState, row[key], { cellValue: row[key], rowData: row }), + ]; + } + }) + ), + }; + }); }, [JSON.stringify([transformations, currentState, component.definition.properties.data.value])]); useEffect(() => { diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index 0d7ad0020a..4e5e339e06 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -22,6 +22,8 @@ import { shallow } from 'zustand/shallow'; import _ from 'lodash'; // eslint-disable-next-line import/no-unresolved import { diff } from 'deep-object-diff'; +import { isPDFSupported } from '@/_stores/utils'; +import toast from 'react-hot-toast'; const NO_OF_GRIDS = 43; @@ -256,6 +258,13 @@ export const Container = ({ return; } + if (item.component.component === 'PDF' && !isPDFSupported()) { + toast.error( + 'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.' + ); + return; + } + if (item.name === 'comment') { const canvasBoundingRect = document.getElementsByClassName('real-canvas')[0].getBoundingClientRect(); const offsetFromTopOfWindow = canvasBoundingRect.top; diff --git a/frontend/src/Editor/SubContainer.jsx b/frontend/src/Editor/SubContainer.jsx index 29371ed7ab..45ee2dc834 100644 --- a/frontend/src/Editor/SubContainer.jsx +++ b/frontend/src/Editor/SubContainer.jsx @@ -18,6 +18,7 @@ import { useMounted } from '@/_hooks/use-mount'; import { useEditorStore } from '@/_stores/editorStore'; // eslint-disable-next-line import/no-unresolved import { diff } from 'deep-object-diff'; +import { isPDFSupported } from '@/_stores/utils'; const NO_OF_GRIDS = 43; @@ -308,6 +309,13 @@ export const SubContainer = ({ () => ({ accept: ItemTypes.BOX, drop(item, monitor) { + if (item.component.component === 'PDF' && !isPDFSupported()) { + toast.error( + 'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.' + ); + return; + } + const componentMeta = _.cloneDeep( componentTypes.find((component) => component.component === item.component.component) ); diff --git a/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx b/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx index c6385ba9ec..a9f4e4c3e9 100644 --- a/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx +++ b/frontend/src/_components/OrganizationLogin/DisablePasswordLoginModal.jsx @@ -15,8 +15,10 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r const modalContent = (
-

Disable password login only if you have configured SSO or else you will get locked out.

-

Are you sure you want to continue?

+

+ Disable password login only if you have configured SSO or else you will get locked out. +

+

Are you sure you want to continue?

); @@ -25,7 +27,7 @@ function DisablePasswordLoginModal({ show, disablePasswordLogin, setShowModal, r Cancel - + Disable diff --git a/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx b/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx index a2ee10b9bd..425020f00a 100644 --- a/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx +++ b/frontend/src/_components/OrganizationLogin/GithubSsoModal.jsx @@ -134,8 +134,8 @@ export function GithubSSOModal({ settings, onClose, onUpdateSSOSettings, isInsta }} >
-