mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-05 22:38:48 +00:00
Cypress test for the profile settings page (#3083)
* Added cypress test for profile settings page * Updated common selectors * Updated common text * Added functions for random names * Added data-cy attributes for components * Added verification for the input value * Added password field validation * Added common utils file * Added wait * Updated login error toast
This commit is contained in:
parent
cacce68713
commit
cb678190d7
10 changed files with 267 additions and 30 deletions
|
|
@ -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]",
|
||||
}
|
||||
22
cypress/constants/selectors/profile.js
Normal file
22
cypress/constants/selectors/profile.js
Normal file
|
|
@ -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]",
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
23
cypress/constants/texts/profile.js
Normal file
23
cypress/constants/texts/profile.js
Normal file
|
|
@ -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",
|
||||
}
|
||||
|
|
@ -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});
|
||||
Object.defineProperty(fake, "password", {get:password});
|
||||
Object.defineProperty(fake, "firstName", {get:firstName});
|
||||
Object.defineProperty(fake, "lastName", {get:lastName});
|
||||
120
cypress/integration/dashboard/profile.spec.js
Normal file
120
cypress/integration/dashboard/profile.spec.js
Normal file
|
|
@ -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();
|
||||
})
|
||||
});
|
||||
14
cypress/support/utils/common.js
Normal file
14
cypress/support/utils/common.js
Normal file
|
|
@ -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);
|
||||
};
|
||||
16
cypress/support/utils/profile.js
Normal file
16
cypress/support/utils/profile.js
Normal file
|
|
@ -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");
|
||||
};
|
||||
|
||||
|
|
@ -61,7 +61,9 @@ function SettingsPage(props) {
|
|||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<div className="page-pretitle"></div>
|
||||
<h2 className="page-title">Profile Settings</h2>
|
||||
<h2 className="page-title" data-cy="page-title">
|
||||
Profile Settings
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -71,13 +73,17 @@ function SettingsPage(props) {
|
|||
<div className="container-xl">
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Profile</h3>
|
||||
<h3 className="card-title" data-cy="card-title-profile">
|
||||
Profile
|
||||
</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="mb-3">
|
||||
<label className="form-label">First name </label>
|
||||
<label className="form-label" data-cy="first-name-label">
|
||||
First name{' '}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
|
|
@ -85,12 +91,15 @@ function SettingsPage(props) {
|
|||
placeholder="Enter first name"
|
||||
value={firstName}
|
||||
onChange={(event) => setFirstName(event.target.value)}
|
||||
data-cy="first-name-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col">
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Last name</label>
|
||||
<label className="form-label" data-cy="last-name-label">
|
||||
Last name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
|
|
@ -98,14 +107,25 @@ function SettingsPage(props) {
|
|||
placeholder="Enter last name"
|
||||
value={lastName}
|
||||
onChange={(event) => setLastName(event.target.value)}
|
||||
data-cy="last-name-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-6">
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Email </label>
|
||||
<input type="text" className="form-control" name="email" value={email} readOnly disabled />
|
||||
<label className="form-label" data-cy="email-label">
|
||||
Email{' '}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
name="email"
|
||||
value={email}
|
||||
readOnly
|
||||
disabled
|
||||
data-cy="email-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -115,6 +135,7 @@ function SettingsPage(props) {
|
|||
href="#"
|
||||
className={'btn btn-primary' + (updateInProgress ? ' btn-loading' : '')}
|
||||
onClick={updateDetails}
|
||||
data-cy="update-button"
|
||||
>
|
||||
Update
|
||||
</a>
|
||||
|
|
@ -126,13 +147,17 @@ function SettingsPage(props) {
|
|||
<br />
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Change password</h3>
|
||||
<h3 className="card-title" data-cy="card-title-change-password">
|
||||
Change password
|
||||
</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Current password</label>
|
||||
<label className="form-label" data-cy="current-password-label">
|
||||
Current password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
className="form-control"
|
||||
|
|
@ -140,12 +165,15 @@ function SettingsPage(props) {
|
|||
placeholder="Enter current password"
|
||||
value={currentpassword}
|
||||
onChange={(event) => setCurrentPassword(event.target.value)}
|
||||
data-cy="current-password-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col">
|
||||
<div className="mb-3">
|
||||
<label className="form-label">New password</label>
|
||||
<label className="form-label" data-cy="new-password-label">
|
||||
New password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
className="form-control"
|
||||
|
|
@ -154,6 +182,7 @@ function SettingsPage(props) {
|
|||
value={newPassword}
|
||||
onChange={(event) => setNewPassword(event.target.value)}
|
||||
onKeyPress={newPasswordKeyPressHandler}
|
||||
data-cy="new-password-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -162,6 +191,7 @@ function SettingsPage(props) {
|
|||
href="#"
|
||||
className={'btn btn-primary' + (passwordChangeInProgress ? ' btn-loading' : '')}
|
||||
onClick={changePassword}
|
||||
data-cy="change-password-button"
|
||||
>
|
||||
Change password
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export const Header = function Header({ switchDarkMode, darkMode }) {
|
|||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<div className="dropdown-menu dropdown-menu-end dropdown-menu-arrow end-0">
|
||||
<div className="dropdown-menu dropdown-menu-end dropdown-menu-arrow end-0" data-cy="dropdown-menu">
|
||||
<Link
|
||||
data-testid="settingsBtn"
|
||||
to="#"
|
||||
|
|
|
|||
Loading…
Reference in a new issue