diff --git a/cypress/constants/selectors/common.js b/cypress/constants/selectors/common.js index a564ff490d..d878a51d9c 100644 --- a/cypress/constants/selectors/common.js +++ b/cypress/constants/selectors/common.js @@ -1,15 +1,18 @@ export const commonSelectors={ - toastMessage: ".go318386747", - appCard: "[data-cy=app-card]", - editButton: "[data-cy=edit-button]", - searchField:"[data-cy=widget-search-box]", - firstWidget:"[data-cy=widget-list]:eq(0)", - canvas:"[data-cy=real-canvas]", - appCardOptions: "[data-cy=app-card-menu-icon]", - deleteApp: "[data-cy=card-options] :nth-child(5)>span", - confirmButton: "[data-cy=confirm-yes-button]", - autoSave: "[data-cy=autosave-indicator]", - skipButton: ".driver-close-btn", - skipInstallationModal: "[data-cy=skip-button]", - homePageLogo: "[data-cy=home-page-logo]" + toastMessage: ".go318386747", + appCard: "[data-cy=app-card]", + editButton: "[data-cy=edit-button]", + searchField:"[data-cy=widget-search-box]", + firstWidget:"[data-cy=widget-list]:eq(0)", + canvas:"[data-cy=real-canvas]", + appCardOptions: "[data-cy=app-card-menu-icon]", + deleteApp: "[data-cy=card-options] :nth-child(5)>span", + confirmButton: "[data-cy=confirm-yes-button]", + autoSave: "[data-cy=autosave-indicator]", + skipButton: ".driver-close-btn", + skipInstallationModal: "[data-cy=skip-button]", + homePageLogo: "[data-cy=home-page-logo]", + emailField: "[data-cy=email-text-field]", + passwordField: "[data-cy=password-text-field]", + signInButton: "[data-cy=login-button]", } \ No newline at end of file diff --git a/cypress/constants/selectors/profile.js b/cypress/constants/selectors/profile.js new file mode 100644 index 0000000000..53090d05fc --- /dev/null +++ b/cypress/constants/selectors/profile.js @@ -0,0 +1,22 @@ +export const profileSelector={ + profileDropdown: "[data-cy=dropdown-menu]", + profileLink: "[data-cy=profile-link]", + logoutLink: "[data-cy=logout-link]", + profileElements:{ + pageTitle: "[data-cy=page-title]", + profileCard: "[data-cy=card-title-profile]", + firstNameLabel: "[data-cy=first-name-label]", + lastNameLabel: "[data-cy=last-name-label]", + emailLabel: "[data-cy=email-label]", + passwordCard: "[data-cy=card-title-change-password]", + currentPasswordLabel: "[data-cy=current-password-label]", + newPasswordLabel: "[data-cy=new-password-label]", + }, + firstNameInput: "[data-cy=first-name-input]", + lastNameInput: "[data-cy=last-name-input]", + emailInput: "[data-cy=email-input]", + updateButton: "[data-cy=update-button]", + changePasswordButton: "[data-cy=change-password-button]", + currentPasswordField: "[data-cy=current-password-input]", + newPasswordField: "[data-cy=new-password-input]", +} \ No newline at end of file diff --git a/cypress/constants/texts/common.js b/cypress/constants/texts/common.js index 808ba04d43..c6b713614e 100644 --- a/cypress/constants/texts/common.js +++ b/cypress/constants/texts/common.js @@ -1,9 +1,12 @@ export const path={ - loginPath:"/login", + loginPath: "/login", + profilePath: "/settings" } export const commonText={ - autoSave:"All changes are saved" + autoSave: "All changes are saved", + email: "dev@tooljet.io", + password: "password" } diff --git a/cypress/constants/texts/profile.js b/cypress/constants/texts/profile.js new file mode 100644 index 0000000000..507073f676 --- /dev/null +++ b/cypress/constants/texts/profile.js @@ -0,0 +1,23 @@ +export const profileText={ + profileElements:{ + pageTitle: "Profile Settings", + profileCard: "Profile", + firstNameLabel: "First name ", + lastNameLabel: "Last name", + emailLabel: "Email ", + passwordCard: "Change password", + currentPasswordLabel: "Current password", + newPasswordLabel: "New password", + }, + firstName: "The", + lastName: "Developer", + updateButton: "Update", + email: "dev@tooljet.io", + nameSuccessToast: "Details updated!", + nameErrorToast: "Name can't be empty!", + newPassword: "newpassword", + changePasswordButton: "Change password", + passwordErrorToast: "Please verify that you have entered the correct password", + passwordSuccessToast: "Password updated successfully", + loginErrorToast:"Invalid email or password", +} \ No newline at end of file diff --git a/cypress/fixtures/fake.js b/cypress/fixtures/fake.js index 1e21ea808f..c22943fd59 100644 --- a/cypress/fixtures/fake.js +++ b/cypress/fixtures/fake.js @@ -2,12 +2,18 @@ import faker from 'faker' export let fake ={}; function email(){ - return (`${faker.name.findName()}@example.com`) + return (`${faker.name.findName()}@example.com`); } - function password(){ - return(faker.internet.password()) + return(faker.internet.password()); +} +function firstName(){ + return (faker.name.firstName()); +} +function lastName(){ + return (faker.name.lastName()); } - Object.defineProperty(fake, "email", {get:email}); -Object.defineProperty(fake, "password", {get:password}); \ No newline at end of file +Object.defineProperty(fake, "password", {get:password}); +Object.defineProperty(fake, "firstName", {get:firstName}); +Object.defineProperty(fake, "lastName", {get:lastName}); \ No newline at end of file diff --git a/cypress/integration/dashboard/profile.spec.js b/cypress/integration/dashboard/profile.spec.js new file mode 100644 index 0000000000..2634463ad4 --- /dev/null +++ b/cypress/integration/dashboard/profile.spec.js @@ -0,0 +1,120 @@ +import { profileSelector } from "Selectors/profile"; +import * as profile from "Support/utils/profile" +import * as common from "Support/utils/common" +import { profileText } from "Texts/profile"; +import {commonSelectors} from "Selectors/common"; +import { fake } from "Fixtures/fake"; +import { commonText } from "Texts/common"; + +describe("Profile Settings",()=>{ + let user; + const randomFirstName = fake.firstName; + const randomLastName = fake.lastName; + beforeEach(()=>{ + cy.fixture("credentials/login.json").then(login=>{ + user = login; + }); + cy.appUILogin(); + common.navigateToProfile(); + }); + + it("Should verify the elements on profile settings page and name reset functionality",()=>{ + profile.profilePageElements(); + + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameSuccessToast); + + cy.get(profileSelector.firstNameInput).clear(); + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameErrorToast); + + cy.get(profileSelector.lastNameInput).clear(); + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameErrorToast); + + cy.clearAndType(profileSelector.firstNameInput , profileText.firstName); + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameErrorToast); + + cy.clearAndType(profileSelector.firstNameInput , randomFirstName); + cy.clearAndType(profileSelector.lastNameInput , randomLastName); + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameSuccessToast); + cy.get(profileSelector.firstNameInput).should("be.visible").and("have.value", randomFirstName); + cy.get(profileSelector.lastNameInput).should("be.visible").and("have.value", randomLastName); + + cy.clearAndType(profileSelector.firstNameInput , profileText.firstName); + cy.clearAndType(profileSelector.lastNameInput , profileText.lastName); + cy.get(profileSelector.updateButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.nameSuccessToast); + cy.get(profileSelector.firstNameInput).should("be.visible").and("have.value", profileText.firstName); + cy.get(profileSelector.lastNameInput).should("be.visible").and("have.value", profileText.lastName); + common.logout(); + }) + + it("Should verify the password reset functionality",()=>{ + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage, profileText.passwordErrorToast); + cy.get(profileSelector.currentPasswordField).should("have.value", ""); + cy.get(profileSelector.newPasswordField).should("have.value", ""); + + cy.clearAndType(profileSelector.currentPasswordField, user.password); + cy.get(profileSelector.currentPasswordField).should("have.value", user.password); + cy.get(profileSelector.newPasswordField).should("have.value", ""); + cy.wait(500); + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordSuccessToast); + + cy.clearAndType(profileSelector.currentPasswordField, profileText.newPassword); + cy.get(profileSelector.currentPasswordField).should("have.value", profileText.newPassword ) + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordErrorToast); + + cy.get(profileSelector.currentPasswordField).clear(); + cy.clearAndType(profileSelector.newPasswordField,profileText.newPassword); + cy.get(profileSelector.newPasswordField).should("have.value", profileText.newPassword ) + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordErrorToast); + + cy.clearAndType(profileSelector.currentPasswordField, profileText.newPassword); + cy.get(profileSelector.currentPasswordField).should("have.value", profileText.newPassword) + cy.clearAndType(profileSelector.newPasswordField, user.password); + cy.get(profileSelector.newPasswordField).should("have.value", user.password ) + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordErrorToast); + + cy.clearAndType(profileSelector.currentPasswordField, user.password); + cy.get(profileSelector.currentPasswordField).should("have.value", user.password) + cy.clearAndType(profileSelector.newPasswordField,profileText.newPassword); + cy.get(profileSelector.newPasswordField).should("have.value", profileText.newPassword ) + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordSuccessToast); + + cy.clearAndType(profileSelector.currentPasswordField, user.password); + cy.get(profileSelector.currentPasswordField).should("have.value", user.password) + cy.clearAndType(profileSelector.newPasswordField,profileText.newPassword); + cy.get(profileSelector.newPasswordField).should("have.value", profileText.newPassword ) + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordSuccessToast); + + common.logout(); + cy.wait(1000); + cy.clearAndType(commonSelectors.emailField, commonText.email); + cy.clearAndType(commonSelectors.passwordField, commonText.password); + cy.get(commonSelectors.signInButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.loginErrorToast); + + cy.clearAndType(commonSelectors.passwordField, profileText.newPassword); + cy.get(commonSelectors.signInButton).click(); + common.navigateToProfile(); + + cy.clearAndType(profileSelector.currentPasswordField,profileText.newPassword); + cy.clearAndType(profileSelector.newPasswordField, user.password); + cy.get(profileSelector.changePasswordButton).click(); + cy.verifyToastMessage(commonSelectors.toastMessage,profileText.passwordSuccessToast); + common.logout(); + + cy.login(user.email,user.password); + common.logout(); + }) +}); \ No newline at end of file diff --git a/cypress/support/utils/common.js b/cypress/support/utils/common.js new file mode 100644 index 0000000000..a4d0e4d71a --- /dev/null +++ b/cypress/support/utils/common.js @@ -0,0 +1,14 @@ +import { path } from "Texts/common"; +import { profileSelector } from "Selectors/profile"; + +export const navigateToProfile=()=>{ + cy.get(profileSelector.profileDropdown).invoke("show"); + cy.contains("Profile").click(); + cy.url().should("include", path.profilePath); +}; + +export const logout=()=>{ + cy.get(profileSelector.profileDropdown).invoke("show"); + cy.contains("Logout").click(); + cy.url().should("include",path.loginPath); +}; \ No newline at end of file diff --git a/cypress/support/utils/profile.js b/cypress/support/utils/profile.js new file mode 100644 index 0000000000..5e06b73c86 --- /dev/null +++ b/cypress/support/utils/profile.js @@ -0,0 +1,16 @@ +import { profileSelector } from "Selectors/profile"; +import { profileText } from "Texts/profile"; + +export const profilePageElements = () =>{ + for(const elements in profileSelector.profileElements ){ + cy.get(profileSelector.profileElements[elements]).should("be.visible").and("have.text",profileText.profileElements[elements]); + } + cy.get(profileSelector.updateButton).should("be.visible").and("have.text", profileText.updateButton); + cy.get(profileSelector.changePasswordButton).should("be.visible").and("have.text", profileText.changePasswordButton); + cy.get(profileSelector.firstNameInput).should("be.visible").and("have.value", profileText.firstName); + cy.get(profileSelector.lastNameInput).should("be.visible").and("have.value", profileText.lastName); + cy.get(profileSelector.emailInput).should("be.visible").and("have.value", profileText.email); + cy.get(profileSelector.currentPasswordField).should("be.visible").should("be.visible"); + cy.get(profileSelector.newPasswordField).should("be.visible").should("be.visible"); +}; + diff --git a/frontend/src/SettingsPage/SettingsPage.jsx b/frontend/src/SettingsPage/SettingsPage.jsx index 7d1426b913..1d94f83141 100644 --- a/frontend/src/SettingsPage/SettingsPage.jsx +++ b/frontend/src/SettingsPage/SettingsPage.jsx @@ -61,7 +61,9 @@ function SettingsPage(props) {
-

Profile Settings

+

+ Profile Settings +

@@ -71,13 +73,17 @@ function SettingsPage(props) {
-

Profile

+

+ Profile +

- + setFirstName(event.target.value)} + data-cy="first-name-input" />
- + setLastName(event.target.value)} + data-cy="last-name-input" />
- - + +
@@ -115,6 +135,7 @@ function SettingsPage(props) { href="#" className={'btn btn-primary' + (updateInProgress ? ' btn-loading' : '')} onClick={updateDetails} + data-cy="update-button" > Update @@ -126,13 +147,17 @@ function SettingsPage(props) {
-

Change password

+

+ Change password +

- + setCurrentPassword(event.target.value)} + data-cy="current-password-input" />
- + setNewPassword(event.target.value)} onKeyPress={newPasswordKeyPressHandler} + data-cy="new-password-input" />
@@ -162,6 +191,7 @@ function SettingsPage(props) { href="#" className={'btn btn-primary' + (passwordChangeInProgress ? ' btn-loading' : '')} onClick={changePassword} + data-cy="change-password-button" > Change password diff --git a/frontend/src/_components/Header.jsx b/frontend/src/_components/Header.jsx index 8d76aa58e0..e0ee8bf261 100644 --- a/frontend/src/_components/Header.jsx +++ b/frontend/src/_components/Header.jsx @@ -61,7 +61,7 @@ export const Header = function Header({ switchDarkMode, darkMode }) {
-
+