Skip to content

Commit

Permalink
CN-754: Fix issue with Contact Form back links
Browse files Browse the repository at this point in the history
  • Loading branch information
gtvj committed Nov 16, 2023
1 parent ca3136c commit d02c87b
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 29 deletions.
54 changes: 50 additions & 4 deletions src/components/contact-us/contact-us-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { logger } from "../../utils/logger";
import {
getClientNameThatDirectsAllContactFormSubmissionsToSmartAgent,
getServiceDomain,
getSupportLinkUrl,
} from "../../config";
import { contactUsServiceSmartAgent } from "./contact-us-service-smart-agent";

Expand Down Expand Up @@ -114,9 +115,12 @@ export function contactUsGet(req: Request, res: Response): void {
}
}

const supportLinkURL = getSupportLinkUrl();

const options = {
referer: referer,
fromURL: fromURL,
hrefBack: prepareBackLink(req, supportLinkURL, serviceDomain),
...(getAppSessionId(req.query.appSessionId as string) && {
appSessionId: getAppSessionId(req.query.appSessionId as string),
}),
Expand All @@ -125,6 +129,45 @@ export function contactUsGet(req: Request, res: Response): void {
return res.render("contact-us/index-public-contact-us.njk", options);
}

export function prepareBackLink(
req: Request,
supportLinkURL: string,
serviceDomain: string
): string {
let hrefBack: string;

if (req.path.endsWith(PATH_NAMES.CONTACT_US)) {
hrefBack = supportLinkURL;
} else if (req.path.endsWith(PATH_NAMES.CONTACT_US_FURTHER_INFORMATION)) {
if (req.query.fromURL && req.query.theme === ZENDESK_THEMES.ID_CHECK_APP) {
hrefBack = supportLinkURL;
} else {
hrefBack = PATH_NAMES.CONTACT_US;
}
} else if (req.path.endsWith(PATH_NAMES.CONTACT_US_QUESTIONS)) {
hrefBack = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
} else {
hrefBack = PATH_NAMES.CONTACT_US;
}

const queryParams = new URLSearchParams();

if (validateReferer(req.query.fromURL as string, serviceDomain)) {
queryParams.append("fromURL", req.query.fromURL as string);
}

if (
req.query.theme &&
Object.values(ZENDESK_THEMES).includes(req.query.theme as string)
) {
queryParams.append("theme", req.query.theme as string);
}

return queryParams.toString().length > 0
? hrefBack + "?" + queryParams.toString()
: hrefBack;
}

export function contactUsGetFromTriagePage(req: Request, res: Response): void {
const queryParams = new URLSearchParams({
...(validateAppId(req.query.appSessionId as string) && {
Expand Down Expand Up @@ -261,13 +304,13 @@ export function contactUsFormPost(req: Request, res: Response): void {
}

export function furtherInformationGet(req: Request, res: Response): void {
const supportLinkURL = getSupportLinkUrl();
const backLinkHref = prepareBackLink(req, supportLinkURL, serviceDomain);

if (!req.query.theme) {
return res.redirect(PATH_NAMES.CONTACT_US);
}

const backLinkHref =
validateReferer(req.get("referer"), serviceDomain) || PATH_NAMES.CONTACT_US;

if (isAppJourney(req.query.appSessionId as string)) {
return res.render("contact-us/further-information/index.njk", {
theme: req.query.theme,
Expand Down Expand Up @@ -328,6 +371,9 @@ export function setContactFormSubmissionUrlBasedOnClientName(
}

export function contactUsQuestionsGet(req: Request, res: Response): void {
const supportLinkURL = getSupportLinkUrl();
const backLinkHref = prepareBackLink(req, supportLinkURL, serviceDomain);

const formSubmissionUrl = setContactFormSubmissionUrlBasedOnClientName(
req?.session?.client?.name,
getClientNameThatDirectsAllContactFormSubmissionsToSmartAgent()
Expand All @@ -349,7 +395,7 @@ export function contactUsQuestionsGet(req: Request, res: Response): void {
formSubmissionUrl: formSubmissionUrl,
theme: req.query.theme,
subtheme: req.query.subtheme,
backurl: validateReferer(req.headers.referer, serviceDomain),
backurl: backLinkHref,
referer: validateReferer(req.query.referer as string, serviceDomain),
...(validateReferer(req.query.fromURL as string, serviceDomain) && {
fromURL: validateReferer(req.query.fromURL as string, serviceDomain),
Expand Down
1 change: 0 additions & 1 deletion src/components/contact-us/index-public-contact-us.njk
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
{% from "govuk/components/warning-text/macro.njk" import govukWarningText %}

{% set showBack = true %}
{% set hrefBack = referer %}
{% set pageTitleName = 'pages.contactUsPublic.title' | translateEnOnly %}

{% block content %}
Expand Down
104 changes: 104 additions & 0 deletions src/components/contact-us/tests/contact-us-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
contactUsGetFromTriagePage,
setContactFormSubmissionUrlBasedOnClientName,
validateReferer,
prepareBackLink,
} from "../contact-us-controller";
import {
PATH_NAMES,
Expand All @@ -24,6 +25,7 @@ import {
CONTACT_US_REFERER_ALLOWLIST,
} from "../../../app.constants";
import { RequestGet, ResponseRedirect } from "../../../types";
import { getServiceDomain, getSupportLinkUrl } from "../../../config";

describe("contact us controller", () => {
let sandbox: sinon.SinonSandbox;
Expand All @@ -35,6 +37,7 @@ describe("contact us controller", () => {
sandbox = sinon.createSandbox();

req = {
path: PATH_NAMES.CONTACT_US,
body: {},
query: {},
headers: {},
Expand Down Expand Up @@ -399,3 +402,104 @@ describe("appErrorCode and appSessionId query parameters", () => {
});
});
});

describe("prepareBackLink", () => {
let sandbox: sinon.SinonSandbox;
let req: Partial<Request>;
let supportLinkURL: string;
let serviceDomain: string;

beforeEach(() => {
sandbox = sinon.createSandbox();

serviceDomain = getServiceDomain();
supportLinkURL = getSupportLinkUrl();

req = {
url: "",
path: "",
body: {},
query: {},
headers: {},
get: sandbox.fake() as unknown as RequestGet,
};
});

afterEach(() => {
sandbox.restore();
});

it("should return the supportLinkURL when the req.path ends with the CONTACT_US path", () => {
req.path = PATH_NAMES.CONTACT_US;
expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(supportLinkURL);
});

it("should return the CONTACT_US path when the req.path ends with the CONTACT_US_FURTHER_INFORMATION path", () => {
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(PATH_NAMES.CONTACT_US);
});

it("should return the CONTACT_US_FURTHER_INFORMATION path when the req.path ends with the CONTACT_US_QUESTIONS path", () => {
req.path = PATH_NAMES.CONTACT_US_QUESTIONS;
expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(PATH_NAMES.CONTACT_US_FURTHER_INFORMATION);
});

it("should return the supportLinkURL with a fromURL parameter when one is included in the req.url", () => {
req.query.fromURL = `https://${getServiceDomain()}${PATH_NAMES.CONTACT_US}`;
const fromURL =
"?fromURL=" +
encodeURIComponent(
`https://${getServiceDomain()}${PATH_NAMES.CONTACT_US}`
);

expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(supportLinkURL + fromURL);
});

it("should omit the fromURL from the backlink where the one included in req.url is not valid", () => {
req.url = `https://${getServiceDomain()}${
PATH_NAMES.CONTACT_US
}?fromURL=${encodeURIComponent("https://www.example.com")}`;

expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(supportLinkURL);
});

it("should include the `theme` where the theme is valid", () => {
req.query.theme = ZENDESK_THEMES.ACCOUNT_CREATION;
req.url = `https://${getServiceDomain()}${PATH_NAMES.CONTACT_US}?theme=${
ZENDESK_THEMES.ACCOUNT_CREATION
}`;

const theme = `?theme=${ZENDESK_THEMES.ACCOUNT_CREATION}`;

expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(supportLinkURL + theme);
});

describe("dynamic back links on CONTACT_US_FURTHER_INFORMATION", () => {
it("should default to returning the CONTACT_US path", () => {
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(PATH_NAMES.CONTACT_US);
});
it("should return the `supportLinkURL` if there is a fromURL and the theme is ID_CHECK_APP", () => {
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
req.query.fromURL = PATH_NAMES.DOC_CHECKING_APP;
req.query.theme = ZENDESK_THEMES.ID_CHECK_APP;
expect(
prepareBackLink(req as Request, supportLinkURL, serviceDomain)
).to.equal(`${supportLinkURL}?theme=${ZENDESK_THEMES.ID_CHECK_APP}`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,21 @@ describe("contact us further information controller", () => {
it("should render signing in further information if a problem signing in to your account radio option was chosen", () => {
req.query.theme = ZENDESK_THEMES.SIGNING_IN;
req.query.referer = REFERER;
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
furtherInformationGet(req as Request, res as Response);

expect(res.render).to.have.calledWith(
"contact-us/further-information/index.njk",
{
theme: "signing_in",
referer: REFERER,
hrefBack: PATH_NAMES.CONTACT_US,
hrefBack: `${PATH_NAMES.CONTACT_US}?theme=${ZENDESK_THEMES.SIGNING_IN}`,
}
);
});

it("should render account creation further information if a creating an account radio option was chosen", () => {
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
req.query.theme = ZENDESK_THEMES.ACCOUNT_CREATION;
req.query.referer = REFERER;
furtherInformationGet(req as Request, res as Response);
Expand All @@ -57,12 +59,13 @@ describe("contact us further information controller", () => {
{
theme: "account_creation",
referer: REFERER,
hrefBack: PATH_NAMES.CONTACT_US,
hrefBack: `${PATH_NAMES.CONTACT_US}?theme=${ZENDESK_THEMES.ACCOUNT_CREATION}`,
}
);
});

it("should redirect to contact-us when no theme is present in request", () => {
req.path = PATH_NAMES.CONTACT_US_FURTHER_INFORMATION;
furtherInformationGet(req as Request, res as Response);

expect(res.redirect).to.have.calledWith("/contact-us");
Expand Down
Loading

0 comments on commit d02c87b

Please sign in to comment.