Skip to content

Commit

Permalink
feat(EMS-1739): Account suspended - invalid link page (#546)
Browse files Browse the repository at this point in the history
* feat(EMS-1739): account suspension - link invalid page

* chore(tech): add E2E test coverage for showing authenticated header on the cookies saved page

* feat(EMS-1739): rename 'link-invalid' to 'invalid-link'

* feat(EMS-1739): add invalid and expired to verifyAccountReactivationToken mutation

* feat(EMS-1739): fix/update E2E test. remove cypress deleteAccount 'catch and throw error'
  • Loading branch information
ttbarnes authored Jun 16, 2023
1 parent da3eeaf commit b4137ef
Show file tree
Hide file tree
Showing 27 changed files with 243 additions and 25 deletions.
1 change: 1 addition & 0 deletions e2e-tests/constants/routes/insurance/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const SUSPENDED = {
EMAIL_SENT: `${SUSPENDED_ROOT}/email-sent`,
VERIFY_EMAIL: `${SUSPENDED_ROOT}/verify-email`,
VERIFY_EMAIL_LINK_EXPIRED: `${SUSPENDED_ROOT}/link-expired`,
VERIFY_EMAIL_LINK_INVALID: `${SUSPENDED_ROOT}/invalid-link`,
};

export const ACCOUNT = {
Expand Down
1 change: 1 addition & 0 deletions e2e-tests/content-strings/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const BUTTONS = {
REACTIVATE_ACCOUNT: 'Reactivate account',
RETURN_TO_EXISTING_APPLICATION: 'Return to my existing application',
RETURN_TO_SERVICE: 'Return to service',
RETURN_TO_SIGN_IN: 'Return to sign in',
SAVE_CHANGES: 'Save changes',
SAVE_AND_BACK: 'Save and back to all sections',
SEARCH: 'Search',
Expand Down
4 changes: 4 additions & 0 deletions e2e-tests/content-strings/pages/insurance/account/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ const ACCOUNT = {
PAGE_TITLE: 'Your account has been reactivated',
THANK_YOU: 'Thank you for confirming your email address. Your account has been reactivated and you can now sign in.',
},
LINK_INVALID: {
PAGE_TITLE: 'Your link is not recognised',
BODY: 'Please make sure you have copied the link correctly from the email we sent you.',
},
};

export default ACCOUNT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { INSURANCE_ROUTES as ROUTES } from '../../../../../../../constants/routes/insurance';
import { PAGES } from '../../../../../../../content-strings';

const {
ACCOUNT: {
SUSPENDED: {
VERIFY_EMAIL,
VERIFY_EMAIL_LINK_INVALID,
},
},
} = ROUTES;

const CONTENT_STRINGS = PAGES.INSURANCE.ACCOUNT.LINK_INVALID;

context('Insurance - Account - Suspended - Verify email - Visit with an invalid token query param', () => {
const baseUrl = Cypress.config('baseUrl');
const verifyEmailUrl = `${baseUrl}${VERIFY_EMAIL}`;
const verifyEmailLinkInvalidUrl = `${baseUrl}${VERIFY_EMAIL_LINK_INVALID}`;

before(() => {
cy.createAnAccountAndBecomeBlocked({ startReactivationJourney: true });
});

after(() => {
cy.deleteAccount();
});

describe(`when the user navigates to ${VERIFY_EMAIL} with an invalid token`, () => {
it(`should redirect to ${VERIFY_EMAIL_LINK_INVALID} and render core page elements`, () => {
cy.navigateToUrl(`${verifyEmailUrl}?token=invalid`);

cy.assertUrl(verifyEmailLinkInvalidUrl);

cy.corePageChecks({
pageTitle: CONTENT_STRINGS.PAGE_TITLE,
currentHref: verifyEmailUrl,
assertBackLink: false,
assertAuthenticatedHeader: false,
assertSubmitButton: false,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ context('Insurance - Account - Suspended - Verify email - Visit with an expired
cy.deleteAccount();
});

describe(`when a reactivation token has expired and the useer navigates to ${VERIFY_EMAIL} with the expired token`, () => {
describe(`when a reactivation token has expired and the user navigates to ${VERIFY_EMAIL} with the expired token`, () => {
let updatedAccount;

beforeEach(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ const {
ACCOUNT: {
SUSPENDED: {
VERIFY_EMAIL,
VERIFY_EMAIL_LINK_EXPIRED,
VERIFY_EMAIL_LINK_INVALID,
},
},
} = ROUTES;

context('Insurance - Account - Suspended - verify email - Visit with an invalid token query param', () => {
const baseUrl = Cypress.config('baseUrl');
const verifyEmailUrl = `${baseUrl}${VERIFY_EMAIL}`;
const verifyEmailLinkExpiredUrl = `${baseUrl}${VERIFY_EMAIL_LINK_EXPIRED}`;
const verifyEmailLinkExpiredUrl = `${baseUrl}${VERIFY_EMAIL_LINK_INVALID}`;

before(() => {
cy.navigateToUrl(`${verifyEmailUrl}?token=invalid`);
});

it(`should redirect to ${VERIFY_EMAIL_LINK_EXPIRED}`, () => {
it(`should redirect to ${VERIFY_EMAIL_LINK_INVALID}`, () => {
cy.url().should('eq', verifyEmailLinkExpiredUrl);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,23 @@ context('Cookies saved page - Insurance - visit the page directly as a signed in
cy.deleteApplication(referenceNumber);
});

it(`should redirect to the ${DASHBOARD} when clicking 'return to service' link button link`, () => {
cookiesSavedPage.returnToServiceLinkButton().click();
it('should render an authenticated header', () => {
cy.checkAuthenticatedHeader();
});

describe('when clicking `return to service` link button', () => {
beforeEach(() => {
cy.navigateToUrl(COOKIES);

cookiesPage[FIELD_IDS.OPTIONAL_COOKIES].acceptInput().click();

cy.assertUrl(dashboardUrl);
submitButton().click();
});

it(`should redirect to the ${DASHBOARD}`, () => {
cookiesSavedPage.returnToServiceLinkButton().click();

cy.assertUrl(dashboardUrl);
});
});
});
4 changes: 2 additions & 2 deletions e2e-tests/cypress/support/insurance/account/delete-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const deleteAccount = (email = accountEmail) => {

return deleteResponse;
} catch (err) {
console.error(err);
console.error('Deleting account', err);

throw new Error('Deleting account');
return err;
}
};

Expand Down
6 changes: 4 additions & 2 deletions src/api/.keystone/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,7 @@ var typeDefs = `
type VerifyAccountReactivationTokenResponse {
success: Boolean!
expired: Boolean
invalid: Boolean
}

type AccountSendEmailReactivateAccountLinkResponse {
Expand Down Expand Up @@ -4098,9 +4099,10 @@ var verifyAccountReactivationToken = async (root, variables, context) => {
success: true
};
}
console.info("Unable to reactivate account - no account found");
console.info(`Unable to reactivate account - no account found from the provided ${REACTIVATION_HASH}`);
return {
success: false
success: false,
invalid: true
};
} catch (err) {
console.error(err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,29 @@ describe('custom-resolvers/verify-account-reactivation-token', () => {
});
});

describe(`when no account is found from the provided ${REACTIVATION_EXPIRY}`, () => {
test('it should return success=false and invalid=true', async () => {
variables.token = 'invalid';

result = await verifyAccountReactivationToken({}, variables, context);

const expected = { success: false, invalid: true };

expect(result).toEqual(expected);
});
});

describe('when no account is found', () => {
test('it should return success=false', async () => {
test('it should return success=false and invalid=true', async () => {
// ensure we have the valid token that was previously created
variables.token = reactivationHash;

// wipe accounts so an account will not be found.
await accounts.deleteAll(context);

result = await verifyAccountReactivationToken({}, variables, context);

const expected = { success: false };
const expected = { success: false, invalid: true };

expect(result).toEqual(expected);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ const verifyAccountReactivationToken = async (
};
}

console.info('Unable to reactivate account - no account found');
console.info(`Unable to reactivate account - no account found from the provided ${REACTIVATION_HASH}`);

return {
success: false,
invalid: true,
};
} catch (err) {
console.error(err);
Expand Down
1 change: 1 addition & 0 deletions src/api/custom-schema/type-defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ const typeDefs = `
type VerifyAccountReactivationTokenResponse {
success: Boolean!
expired: Boolean
invalid: Boolean
}

type AccountSendEmailReactivateAccountLinkResponse {
Expand Down
1 change: 1 addition & 0 deletions src/api/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2393,6 +2393,7 @@ type VerifyAccountEmailAddressResponse {
type VerifyAccountReactivationTokenResponse {
success: Boolean!
expired: Boolean
invalid: Boolean
}

type AccountSendEmailReactivateAccountLinkResponse {
Expand Down
1 change: 1 addition & 0 deletions src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ interface VerifyAccountReactivationTokenVariables {

interface VerifyAccountReactivationTokenResponse extends SuccessResponse {
expired?: boolean;
invalid?: boolean;
}

interface SendExporterEmailVariables {
Expand Down
1 change: 1 addition & 0 deletions src/ui/server/constants/routes/insurance/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const SUSPENDED = {
EMAIL_SENT: `${SUSPENDED_ROOT}/email-sent`,
VERIFY_EMAIL: `${SUSPENDED_ROOT}/verify-email`,
VERIFY_EMAIL_LINK_EXPIRED: `${SUSPENDED_ROOT}/link-expired`,
VERIFY_EMAIL_LINK_INVALID: `${SUSPENDED_ROOT}/invalid-link`,
};

export const ACCOUNT = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ export const ACCOUNT_TEMPLATES = {
VERIFY_EMAIL_LINK_EXPIRED: 'insurance/account/suspended/link-expired.njk',
},
REACTIVATED: 'insurance/account/reactivated.njk',
LINK_INVALID: 'insurance/account/invalid-link.njk',
};
1 change: 1 addition & 0 deletions src/ui/server/content-strings/buttons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const BUTTONS = {
REACTIVATE_ACCOUNT: 'Reactivate account',
RETURN_TO_EXISTING_APPLICATION: 'Return to my existing application',
RETURN_TO_SERVICE: 'Return to service',
RETURN_TO_SIGN_IN: 'Return to sign in',
SAVE_CHANGES: 'Save changes',
SAVE_AND_BACK: 'Save and back to all sections',
SEARCH: 'Search',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ const ACCOUNT = {
PAGE_TITLE: 'Your account has been reactivated',
THANK_YOU: 'Thank you for confirming your email address. Your account has been reactivated and you can now sign in.',
},
LINK_INVALID: {
PAGE_TITLE: 'Your link is not recognised',
BODY: 'Please make sure you have copied the link correctly from the email we sent you.',
},
};

export default ACCOUNT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { TEMPLATE, PAGE_CONTENT_STRINGS, get } from '.';
import { PAGES } from '../../../../content-strings';
import { TEMPLATES } from '../../../../constants';
import { INSURANCE_ROUTES } from '../../../../constants/routes/insurance';
import insuranceCorePageVariables from '../../../../helpers/page-variables/core/insurance';
import { Request, Response } from '../../../../../types';
import { mockAccount, mockReq, mockRes } from '../../../../test-mocks';

const {
ACCOUNT: {
SIGN_IN: { ROOT: SIGN_IN_ROOT },
},
} = INSURANCE_ROUTES;

describe('controllers/insurance/account/invalid-link', () => {
let req: Request;
let res: Response;

beforeEach(() => {
req = mockReq();
req.session.user = mockAccount;

res = mockRes();
});

describe('TEMPLATE', () => {
it('should have the correct template defined', () => {
expect(TEMPLATE).toEqual(TEMPLATES.INSURANCE.ACCOUNT.LINK_INVALID);
});
});

describe('PAGE_CONTENT_STRINGS', () => {
it('should have the correct strings', () => {
expect(PAGE_CONTENT_STRINGS).toEqual(PAGES.INSURANCE.ACCOUNT.LINK_INVALID);
});
});

describe('get', () => {
it('should render template', () => {
get(req, res);

const expectedVariables = {
...insuranceCorePageVariables({
PAGE_CONTENT_STRINGS,
BACK_LINK: req.headers.referer,
}),
SIGN_IN_URL: SIGN_IN_ROOT,
};

expect(res.render).toHaveBeenCalledWith(TEMPLATE, expectedVariables);
});
});
});
31 changes: 31 additions & 0 deletions src/ui/server/controllers/insurance/account/invalid-link/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PAGES } from '../../../../content-strings';
import { TEMPLATES } from '../../../../constants';
import { INSURANCE_ROUTES } from '../../../../constants/routes/insurance';
import insuranceCorePageVariables from '../../../../helpers/page-variables/core/insurance';
import { Request, Response } from '../../../../../types';

const {
ACCOUNT: {
SIGN_IN: { ROOT: SIGN_IN_ROOT },
},
} = INSURANCE_ROUTES;

export const TEMPLATE = TEMPLATES.INSURANCE.ACCOUNT.LINK_INVALID;

export const PAGE_CONTENT_STRINGS = PAGES.INSURANCE.ACCOUNT.LINK_INVALID;

/**
* get
* Render the generic "Account - invalid link" page
* @param {Express.Request} Express request
* @param {Express.Response} Express response
* @returns {Express.Response.render} Generic "Account - invalid link" page
*/
export const get = (req: Request, res: Response) =>
res.render(TEMPLATE, {
...insuranceCorePageVariables({
PAGE_CONTENT_STRINGS,
BACK_LINK: req.headers.referer,
}),
SIGN_IN_URL: SIGN_IN_ROOT,
});
Loading

0 comments on commit b4137ef

Please sign in to comment.