add e2e test cases for account/identity and profile edit pages

This commit is contained in:
Nuwan 2024-02-23 16:22:55 +05:30
parent 8cf7048b7f
commit 1a11cc331c
8 changed files with 310 additions and 12 deletions

View File

@ -0,0 +1,166 @@
/// <reference types="cypress" />
import makeFakeUser from '../../factories/user';
describe('Change Current Email/Password Feature', () => {
beforeEach(() => {
// Log in to the application or navigate to the account page
// where the change email feature is available
const currentUser = makeFakeUser({
email: 'sam@example.com'
});
cy.stubAuthenticate({ ...currentUser });
cy.visit('/account/identity');
});
describe('Email update', () => {
it('should display the current email address', () => {
// Assert that the current email address is displayed
cy.get('[data-testid=edit_email_form]').within($form => {
cy.get('input#new_email[placeholder="sam@example.com"]');
});
});
it('shows validation error if no data is entered', () => {
// Assert that an error message is displayed
cy.get('[data-testid=edit_email_form]').within($form => {
cy.get('[data-testid=email_submit]').click();
cy.contains('Current password is required');
cy.contains('New Email is required');
});
});
it('shows validation error if new email is invalid', () => {
cy.get('[data-testid=edit_email_form]').within($form => {
// Enter the current password
cy.get('input#current_password').type('password');
// Enter an invalid email address in the input field
cy.get('input#new_email').type('invalidemail');
cy.get('[data-testid=email_submit]').click();
// Assert that an error message is displayed
cy.contains('Email is invalid');
});
});
it('reveal password', () => {
cy.get('[data-testid=edit_email_form]').within($form => {
// Click on the reveal password button
cy.get('.input-group-append').click();
// Assert that the password is revealed
cy.get('input#current_password').should('have.attr', 'type', 'text');
});
});
describe('when the user submits the form', () => {
beforeEach(() => {
cy.intercept('POST', /\S+\/users\S+/, {
statusCode: 200
}).as('updateEmail');
});
it('should update the email address', () => {
cy.get('[data-testid=edit_email_form]').within($form => {
// Enter the current password
cy.get('input#current_password').type('password');
// Enter the new email address
cy.get('input#new_email').type('samsam@example.com');
// Submit the form
cy.get('[data-testid=email_submit]').click();
});
// Assert that the email address is updated
cy.contains('A confirmation email has been sent to your email address');
});
});
});
describe('Password update', () => {
it('shows validation error if no data is entered', () => {
// Assert that an error message is displayed
cy.get('[data-testid=edit_password_form]').within($form => {
cy.get('[data-testid=password_submit]').click();
cy.contains('Current password is required');
cy.contains('New password is required');
});
});
it('reveal password', () => {
cy.get('[data-testid=edit_password_form]').within($form => {
// Click on the reveal password button
cy.get('.current-password-reveal').click();
// Assert that the password is revealed
cy.get('input#current_password').should('have.attr', 'type', 'text');
// Click on the reveal password button
cy.get('.new-password-reveal').click();
// Assert that the password is revealed
cy.get('input#new_password').should('have.attr', 'type', 'text');
});
});
describe('Submit form with errors', () => {
beforeEach(() => {
cy.intercept('POST', /\S+\/users\S+\/set_password/, {
statusCode: 422,
body: {
errors: {
password: ['is too short']
}
}
}).as('updatePassword');
});
it('shows validation error if new password is invalid', () => {
cy.get('[data-testid=edit_password_form]').within($form => {
// Enter the current password
cy.get('input#current_password').type('password');
// Enter an invalid new password
cy.get('input#new_password').type('short');
cy.get('[data-testid=password_submit]').click();
// Assert that an error message is displayed
cy.contains('New Password is too short');
});
});
});
describe('Submit with valid data', () => {
beforeEach(() => {
cy.intercept('POST', /\S+\/users\S+\/set_password/, {
statusCode: 200
}).as('updatePassword');
});
it('should update the password', () => {
cy.get('[data-testid=edit_password_form]').within($form => {
// Enter the current password
cy.get('input#current_password').type('password');
// Enter the new password
cy.get('input#new_password').type('newpassword');
// Submit the form
cy.get('[data-testid=password_submit]').click();
});
// Assert that the password is updated
cy.contains('password has been successfully updated');
});
})
describe('Forgot password', () => {
beforeEach(() => {
cy.intercept('POST', /\S+\/users\S+\/request_reset_password/, {
statusCode: 200
}).as('forgotPassword');
});
it('sends forgot password email', () => {
cy.get('[data-testid=forgot_password]').click();
cy.contains('A password reset email has been sent to your email');
});
})
});
});

View File

@ -0,0 +1,121 @@
/// <reference types="cypress" />
import makeFakeUser from '../../factories/user';
describe('Profile update', () => {
beforeEach(() => {
// Log in to the application or navigate to the account page
// where the change email feature is available
const currentUser = makeFakeUser();
cy.stubAuthenticate({ ...currentUser });
cy.intercept('GET', /\S+\/users\/\S+\/profile/, {
statusCode: 200,
body: {
first_name: 'David',
last_name: 'Wilson',
name: 'David Wilson',
city: 'Barstow',
state: 'CA',
country: 'US',
location: 'Barstow, CA',
photo_url: null,
biography:
'This is the musician biography. It is a long form text.',
virtual_band: true,
virtual_band_commitment: 2,
traditional_band: false,
traditional_band_commitment: null,
traditional_band_touring: false,
paid_sessions: true,
paid_sessions_hourly_rate: 19900,
paid_sessions_daily_rate: 200000,
free_sessions: true,
cowriting: true,
cowriting_purpose: 2,
subscribe_email: true,
genres: [
{
genre_id: 'asian',
player_type: 'JamRuby::User',
genre_type: 'profile'
},
{
genre_id: 'blues',
player_type: 'JamRuby::User',
genre_type: 'profile'
},
{
genre_id: 'dance',
player_type: 'JamRuby::User',
genre_type: 'profile'
}
],
instruments: [
{
description: 'Acoustic Guitar',
proficiency_level: 3,
priority: 0,
instrument_id: 'acoustic guitar'
},
{
description: 'Bass Guitar',
proficiency_level: 3,
priority: 2,
instrument_id: 'bass guitar'
},
{
description: 'Violin',
proficiency_level: 1,
priority: 0,
instrument_id: 'violin'
},
{
description: 'Banjo',
proficiency_level: 1,
priority: 1,
instrument_id: 'banjo'
}
],
}
}).as('getProfile');
cy.visit('/profile');
});
it('should render the profile form with persisted data', () => {
// Assert that the profile form is rendered
cy.get('[data-testid=edit_profile_form]').within($form => {
cy.get('[data-testid=firstName]').should('have.value', 'David');
cy.get('[data-testid=lastName]').should('have.value', 'Wilson');
cy.get("[data-testid=biography]").should('contain', 'This is the musician biography. It is a long form text');
cy.get('[data-testid=subscribeEmail]').should('be.checked');
cy.get('[data-testid=virtualBand]').should('be.checked');
cy.get('[data-testid=traditionalBand]').should('not.be.checked');
cy.get('[data-testid=cowriting]').should('be.checked');
cy.get('[data-testid=instruments] input:checked').should('have.length', 4);
cy.get('[data-testid=genres] input:checked').should('have.length', 3);
} );
});
it('should update the profile', () => {
// Update the profile form
cy.get('[data-testid=edit_profile_form]').within($form => {
// Update the first name
cy.get('[data-testid=firstName]').clear().type('Seth');
// Update the last name
cy.get('[data-testid=lastName]').clear().type('Call');
cy.wait(2000);
});
cy.reload();
cy.get('[data-testid=firstName]').should('have.value', 'Seth');
});
});

View File

@ -31,6 +31,7 @@ Cypress.Commands.add('stubAuthenticate', (attrs = {}) => {
first_name: 'Peter',
last_name: 'Pan',
name: 'Peter Pan',
email: 'peter@example.com',
photo_url: ''
}
const currentUserAtrs = {...defaultAttrs, ...attrs}

View File

@ -381,7 +381,7 @@ function JKEditProfile() {
<Card>
<FalconCardHeader title={t('page_title', { ns: 'profile' })} titleClass="font-weight-bold" />
<CardBody className="pt-3" style={{ backgroundColor: '#edf2f9' }}>
<Form>
<Form data-testid="edit_profile_form">
<Row>
<Col>
<Card>
@ -398,6 +398,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="firstName"
value={value}
onChange={e => {
onChange(e);
@ -416,6 +417,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="lastName"
value={value}
onChange={e => {
onChange(e);
@ -457,6 +459,7 @@ function JKEditProfile() {
const country = countries.find(country => country.countrycode === value);
return (
<Select
data-testid="countrySelect"
value={{ value: country.countrycode, label: country.countryname }}
onChange={handleCountryChange}
options={countries.map(country => {
@ -520,6 +523,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="biography"
style={{ height: 200 }}
type="textarea"
value={value}
@ -537,6 +541,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="subscribeEmail"
checked={value}
type="checkbox"
onChange={e => {
@ -564,6 +569,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="virtualBand"
checked={value}
onChange={e => {
onChange(e);
@ -583,6 +589,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="traditionalBand"
checked={value}
onChange={e => {
onChange(e);
@ -602,6 +609,7 @@ function JKEditProfile() {
control={control}
render={({ field: { onChange, value } }) => (
<Input
data-testid="cowriting"
checked={value}
onChange={e => {
onChange(e);
@ -623,7 +631,7 @@ function JKEditProfile() {
<CardHeader>
<h5>{t('instruments')}</h5>
</CardHeader>
<CardBody className="bg-light" style={{ overflowY: 'scroll', height: 300 }}>
<CardBody data-testid="instruments" className="bg-light" style={{ overflowY: 'scroll', height: 300 }}>
<FormGroup check>
{instrumentsInitialLoadingDone &&
musicInstruments.map((musicInstrument, index) => {
@ -666,7 +674,7 @@ function JKEditProfile() {
<CardHeader>
<h5>{t('genres')}</h5>
</CardHeader>
<CardBody className="bg-light" style={{ overflowY: 'scroll', height: 300 }}>
<CardBody data-testid="genres" className="bg-light" style={{ overflowY: 'scroll', height: 300 }}>
<FormGroup check>
{genreInitialLoadingDone &&
genres.map((genre, index) => {

View File

@ -93,7 +93,7 @@ const JKEditEmail = ({setAlert, toggleAlert}) => {
{t('identity.email_form.help_text')}
</small>
<Form className="mt-2" onSubmit={handleSubmit(onSubmitEmail)}>
<Form novalidate="novalidate" className="mt-2" onSubmit={handleSubmit(onSubmitEmail)} data-testid="edit_email_form">
<FormGroup>
<Label for="current_password">{t('identity.email_form.current_password')}</Label>
<Controller
@ -149,7 +149,7 @@ const JKEditEmail = ({setAlert, toggleAlert}) => {
{errors.new_email && <div className="text-danger"><small>{errors.new_email.message}</small></div>}
</FormGroup>
<div className='d-flex align-content-center justify-content-start'>
<input type="submit" className="btn btn-primary" value={t('identity.email_form.submit')} disabled={submitting} />
<input type="submit" formnovalidate className="btn btn-primary" value={t('identity.email_form.submit')} disabled={submitting} data-testid="email_submit" />
<span className='ml-2'>
{ submitting && <FontAwesomeIcon icon="spinner" />}
</span>

View File

@ -98,7 +98,7 @@ const JKEditPassword = ({ setAlert, toggleAlert }) => {
{t('identity.password_form.help_text')}
</small>
<Form className="mt-2" onSubmit={handleSubmit(onSubmitPassword)}>
<Form className="mt-2" onSubmit={handleSubmit(onSubmitPassword)} data-testid="edit_password_form">
<FormGroup>
<Label for="current_password"> {t('identity.password_form.current_password')}</Label>
<Controller
@ -116,6 +116,7 @@ const JKEditPassword = ({ setAlert, toggleAlert }) => {
/>
<InputGroupAddon
addonType="append"
className="current-password-reveal"
onClick={() => {
setShowPassword(!showPassword);
}}
@ -151,6 +152,7 @@ const JKEditPassword = ({ setAlert, toggleAlert }) => {
/>
<InputGroupAddon
addonType="append"
className='new-password-reveal'
onClick={() => {
setShowNewPassword(!showNewPassword);
}}
@ -169,13 +171,13 @@ const JKEditPassword = ({ setAlert, toggleAlert }) => {
)}
</FormGroup>
<div className="d-flex align-content-center justify-content-start">
<input type="submit" className="btn btn-primary" value={t('identity.password_form.submit')} disabled={submitting} />
<input type="submit" className="btn btn-primary" value={t('identity.password_form.submit')} disabled={submitting} data-testid="password_submit" />
<span className="ml-2">{submitting && <FontAwesomeIcon icon="spinner" />}</span>
</div>
</Form>
<div className="mt-2">
<small>
{t('identity.password_form.forgot_password.help_text_p1')} <a href="#" onClick={requestResetPassword}>{t('identity.password_form.forgot_password.click_here')}</a> {t('identity.password_form.forgot_password.help_text_p2')}
{t('identity.password_form.forgot_password.help_text_p1')} <a href="#" data-testid="forgot_password" onClick={requestResetPassword}>{t('identity.password_form.forgot_password.click_here')}</a> {t('identity.password_form.forgot_password.help_text_p2')}
</small>
</div>
</CardBody>

View File

@ -14,9 +14,9 @@ const JKProfileAvatarUpload = ({show, toggle}) => {
useEffect(() => {
if(currentUser) {
console.log(currentUser.photo_url);
getUserDetails(currentUser.id).then(response => {
console.log('_userDetails', response);
});
// getUserDetails(currentUser.id).then(response => {
// console.log('_userDetails', response);
// });
}
}, [currentUser]);

View File

@ -35,7 +35,7 @@
"submit": "Save Password",
"validations": {
"new_password": {
"required": "New Password is required",
"required": "New password is required",
"pattern": "Password must be at least 8 characters long"
},
"current_password": {