Skip to content

Commit

Permalink
src/components/register: add register method to FormRegister component (
Browse files Browse the repository at this point in the history
#608)

* change UI colors for registration form

* add infra for register api call

* RegistrationForm update

* refactor tests and EmailConfirmation placement

* add e2e tests

* udpate email confirmation graphics

* cleanup error messages and add logger

* fix register e2e tests

* fix FormRegister comp tests

* add tests for register link to FormLogin

* extend component tests for FormRegister

* cleanup

* remove env file

* update gitignore

* update EmailConfirmation docs

* cleanup

* add checkboxes to FormRegister component

* add checkboxes and update FormRegister tests to reflect this

* fix e2e tests

* add ConfirmEmailPage and routing rules

* remove confirmation check in FormRegister component

* update e2e regiseter test with enabled redirection rules

* add redirection tests to register e2e spec

* cleanup comments

* add api endpoint to config

* update inner state boolean value

* add checkEmailVerification method to register store

* update register e2e tests with registration email verification and login examples

* rename route to verify-email

* rename VerifyEmailPage and EmailVerification

* update EmailVerification tests for sending request

* cleanup router/index

* cleanup routes.ts

* refactor test variables timeUntilExpiration and systemTime

* refactor selectors in register e2e tests

* src/composables: fix user registration process

* src/utils: fix import global app config

To fix run e2e unit_tests_app_code.spec.cy.js test.

* fix FormRegister tests

* fix variable names

* update register tests based on new API responses

* fix EmailVerification test intercept

* refactor saving acess and refresh token

* fix race condition in EmailVerification test

* set token expiration time to UTC

* fix config import

* cleanup

* Revert "fix config import"

This reverts commit 2f86603.

* src/utils: fix get API version from global config

* src/stores: fix challenge store instance name

* src/components/register: log redirect URL if email address was verified successfully

* src/stores: fix log message level and fix message grammar

* fix import + TS issue in EmailVerification component

* add function docs to register store

---------

Co-authored-by: Šimon Macek <[email protected]>
Co-authored-by: Tomas Zigo <[email protected]>
  • Loading branch information
3 people authored Oct 14, 2024
1 parent a62e4f9 commit 83b1e19
Show file tree
Hide file tree
Showing 32 changed files with 1,621 additions and 205 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
.thumbs.db
.env
node_modules

# Quasar core related directories
Expand Down
5 changes: 5 additions & 0 deletions public/icons/email_confirmation/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions ride_to_work_by_bike_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,7 @@ apiBase = "https://test.dopracenakole.cz/rest/"
apiVersion = "1.0"
apiDefaultLang = "cs"

urlApiHasUserVerifiedEmail = "auth/registration/has-user-verified-email-address/"
urlApiLogin = "auth/login/"
urlApiRefresh = "auth/token/refresh/"
urlApiRegister = "auth/registration/"
207 changes: 207 additions & 0 deletions src/components/__tests__/EmailVerification.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import { colors } from 'quasar';
import { createPinia, setActivePinia } from 'pinia';
import EmailVerification from 'components/register/EmailVerification.vue';
import { i18n } from '../../boot/i18n';
import { useRegisterStore } from '../../stores/register';
import { routesConf } from '../../router/routes_conf';
import { rideToWorkByBikeConfig } from '../../boot/global_vars';
import { getApiBaseUrlWithLang } from '../../utils/get_api_base_url_with_lang';
import { httpSuccessfullStatus } from '../../../test/cypress/support/commonTests';

// colors
const { getPaletteColor, changeAlpha } = colors;
const white = getPaletteColor('white');
const whiteOpacity20 = changeAlpha(white, 0.2);

// selectors
const selectorEmailVerification = 'email-verification';
const selectorEmailVerificationTitle = 'email-verification-title';
const selectorEmailVerificationText = 'email-verification-text';
const selectorEmailVerificationWrongEmailHint =
'email-verification-wrong-email-hint';
const selectorEmailVerificationRegisterLink =
'email-verification-register-link';
const selectorEmailVerificationGraphics = 'email-verification-graphics';
const selectorEmailVerificationAvatar = 'email-verification-avatar';
const selectorEmailVerificationIcon = 'email-verification-icon';

// variables
const fontSizeTitle = 24;
const fontWeightTitle = 700;
const fontSizeText = 14;
const fontWeightText = 400;
const avatarSize = 64;
const iconSize = 40;
const testEmail = '[email protected]';

describe('<EmailVerification>', () => {
it('has translation for all strings', () => {
cy.testLanguageStringsInContext(
[
'linkRegister',
'hintWrongEmail',
'textEmailVerification',
'titleEmailVerification',
],
'register.form',
i18n,
);
});

context('desktop', () => {
beforeEach(() => {
setActivePinia(createPinia());
cy.viewport('macbook-16');
// variables
const { apiBase, apiDefaultLang, urlApiHasUserVerifiedEmail } =
rideToWorkByBikeConfig;
const apiBaseUrl = getApiBaseUrlWithLang(
null,
apiBase,
apiDefaultLang,
i18n,
);
const apiEmailVerificationUrl = `${apiBaseUrl}${urlApiHasUserVerifiedEmail}`;
// intercept email verification request
cy.intercept('GET', apiEmailVerificationUrl, {
statusCode: httpSuccessfullStatus,
body: { has_user_verified_email_address: true },
})
.as('emailVerificationRequest')
.then(() => {
// mount after intercept
cy.mount(EmailVerification, {
props: {},
});
});
});

coreTests();
});

context('mobile', () => {
beforeEach(() => {
setActivePinia(createPinia());
cy.viewport('iphone-6');
// variables
const { apiBase, apiDefaultLang, urlApiHasUserVerifiedEmail } =
rideToWorkByBikeConfig;
const apiBaseUrl = getApiBaseUrlWithLang(
null,
apiBase,
apiDefaultLang,
i18n,
);
const apiEmailVerificationUrl = `${apiBaseUrl}${urlApiHasUserVerifiedEmail}`;
// intercept email verification request
cy.intercept('GET', apiEmailVerificationUrl, {
statusCode: httpSuccessfullStatus,
body: { has_user_verified_email_address: true },
})
.as('emailVerificationRequest')
.then(() => {
// mount after intercept
cy.mount(EmailVerification, {
props: {},
});
});
});

coreTests();
});
});

function coreTests() {
it('renders component', () => {
cy.dataCy(selectorEmailVerification).should('be.visible');
// title
cy.dataCy(selectorEmailVerificationTitle)
.should('be.visible')
.and('have.css', 'font-size', `${fontSizeTitle}px`)
.and('have.css', 'font-weight', `${fontWeightTitle}`)
.and('have.color', white)
.and('contain', i18n.global.t('register.form.titleEmailVerification'));
// text
const store = useRegisterStore();
store.setEmail(testEmail);
cy.dataCy(selectorEmailVerificationText)
.should('be.visible')
.and('contain', testEmail);
// check inner html
cy.dataCy(selectorEmailVerificationText)
.should('be.visible')
.and('have.css', 'font-size', `${fontSizeText}px`)
.and('have.css', 'font-weight', `${fontWeightText}`)
.then(($el) => {
const content = $el.text();
cy.stripHtmlTags(
i18n.global.t('register.form.textEmailVerification', {
email: testEmail,
}),
).then((text) => {
expect(content).to.equal(text);
});
});
// wrong email hint
cy.dataCy(selectorEmailVerificationWrongEmailHint)
.should('be.visible')
.and('have.css', 'font-size', `${fontSizeText}px`)
.and('have.css', 'font-weight', `${fontWeightText}`)
.and('have.color', white)
.and('contain', i18n.global.t('register.form.hintWrongEmail'));
// register link
cy.dataCy(selectorEmailVerificationRegisterLink)
.should('be.visible')
.and('have.css', 'font-size', `${fontSizeText}px`)
.and('have.css', 'font-weight', `${fontWeightText}`)
.and('have.color', white)
.and('contain', i18n.global.t('register.form.linkRegister'))
.invoke('attr', 'href')
.should('contain', routesConf['register']['path']);
// graphics
cy.dataCy(selectorEmailVerificationGraphics).should('be.visible');
// avatar
cy.dataCy(selectorEmailVerificationAvatar)
.should('be.visible')
.and('have.backgroundColor', whiteOpacity20)
.invoke('height')
.should('eq', avatarSize);
cy.dataCy(selectorEmailVerificationAvatar)
.invoke('width')
.should('eq', avatarSize);
// icon
cy.dataCy(selectorEmailVerificationIcon)
.should('be.visible')
.and('have.color', white)
.invoke('height')
.should('eq', iconSize);
cy.dataCy(selectorEmailVerificationIcon)
.invoke('width')
.should('eq', iconSize);
});

it('makes an email verification request', () => {
// check that email verification request is made
cy.wait('@emailVerificationRequest')
.then((interception) => {
expect(interception.response.statusCode).to.equal(
httpSuccessfullStatus,
);
expect(
interception.response.body.has_user_verified_email_address,
).to.equal(true);
})
.then(() => {
// prevent race condition between modifying and accessing store
return new Cypress.Promise((resolve) => {
setTimeout(() => {
resolve();
}, 500);
});
})
.then(() => {
const store = useRegisterStore();
expect(store.getIsEmailVerified).to.equal(true);
});
});
}
32 changes: 32 additions & 0 deletions src/components/__tests__/FormLogin.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const contactEmail = rideToWorkByBikeConfig.contactEmail;

// selectors
const classSelectorQNotificationMessage = '.q-notification__message';
const selectorLoginPromptNoAccount = 'login-prompt-no-account';
const selectorLoginLinkRegister = 'login-link-register';

// variables
const { apiBase, apiDefaultLang, urlApiLogin, urlApiRefresh } =
Expand Down Expand Up @@ -158,6 +160,36 @@ describe('<FormLogin>', () => {
.and('have.text', i18n.global.t('login.form.submitLogin'));
});

it('renders a no account prompt and a link to register', () => {
cy.dataCy(selectorLoginPromptNoAccount)
.should('be.visible')
.and('have.css', 'font-size', '14px')
.and('have.css', 'font-weight', '400')
.and('have.color', white)
.then(($el) => {
const content = $el.text();
cy.stripHtmlTags(i18n.global.t('login.form.promptNoAccount')).then(
(text) => {
expect(content).to.contain(text);
},
);
});
// register
cy.dataCy(selectorLoginLinkRegister)
.should('be.visible')
.and('have.css', 'font-size', '14px')
.and('have.css', 'font-weight', '400')
.and('have.color', white)
.then(($el) => {
const content = $el.text();
cy.stripHtmlTags(i18n.global.t('login.form.linkRegister')).then(
(text) => {
expect(content).to.contain(text);
},
);
});
});

it('allows to navigate between states', () => {
cy.dataCy('form-login-forgotten-password').should('be.visible').click();
cy.dataCy('form-password-reset').should('be.visible');
Expand Down
Loading

0 comments on commit 83b1e19

Please sign in to comment.