diff --git a/src/main/app.ts b/src/main/app.ts
index f4a15a795..2d27ffbb8 100644
--- a/src/main/app.ts
+++ b/src/main/app.ts
@@ -7,7 +7,7 @@ import { glob } from 'glob';
import favicon from 'serve-favicon';
import { setupDev } from './development';
-import { caseReferenceParamMiddleware } from './middleware';
+import { caseReferenceParamMiddleware, pageTrackingUrlMiddleware } from './middleware';
import * as modules from './modules';
import { setupErrorHandlers } from './modules/error-handler';
import { registerAllJourneys } from './routes/registerSteps';
@@ -38,6 +38,8 @@ app.use((req, res, next) => {
next();
});
+app.use(pageTrackingUrlMiddleware);
+
// param middleware for caseReference
app.param('caseReference', caseReferenceParamMiddleware);
diff --git a/src/main/assets/locales/cy/common.json b/src/main/assets/locales/cy/common.json
index f8a8f60eb..84e91c3fd 100644
--- a/src/main/assets/locales/cy/common.json
+++ b/src/main/assets/locales/cy/common.json
@@ -1,7 +1,7 @@
{
"serviceName": "cyRespond to a property possession claim",
"phase": "cyALPHA",
- "feedback": "cyThis is a new service – your feedback will help us to improve it.",
+ "feedback": "cyThis is a new service – your feedback (opens in new tab) will help us to improve it.",
"languageToggle": "English",
"logout": "cySign out",
"navigationLabel": "cyService navigation",
diff --git a/src/main/assets/locales/en/common.json b/src/main/assets/locales/en/common.json
index a5a412aa2..ef4f324af 100644
--- a/src/main/assets/locales/en/common.json
+++ b/src/main/assets/locales/en/common.json
@@ -1,7 +1,7 @@
{
"serviceName": "Respond to a property possession claim",
"phase": "ALPHA",
- "feedback": "This is a new service – your feedback will help us to improve it.",
+ "feedback": "This is a new service – your feedback (opens in new tab) will help us to improve it.",
"languageToggle": "Cymraeg",
"logout": "Sign out",
"navigationLabel": "Service navigation",
diff --git a/src/main/middleware/index.ts b/src/main/middleware/index.ts
index 4d0884218..d8ed55b3b 100644
--- a/src/main/middleware/index.ts
+++ b/src/main/middleware/index.ts
@@ -1,2 +1,3 @@
export * from './oidc';
export * from './caseReference';
+export * from './pageTrackingUrl';
diff --git a/src/main/middleware/pageTrackingUrl.ts b/src/main/middleware/pageTrackingUrl.ts
new file mode 100644
index 000000000..61a4dba48
--- /dev/null
+++ b/src/main/middleware/pageTrackingUrl.ts
@@ -0,0 +1,21 @@
+import { NextFunction, Request, Response } from 'express';
+
+const getPageTrackingUrl = (path: string): string => {
+ const segments = path.split('/').filter(Boolean);
+
+ if (segments[0] === 'dashboard') {
+ return 'dashboard';
+ }
+
+ if (segments[0] === 'case' && segments.length > 2) {
+ return `${segments.slice(2).join('/')}`;
+ }
+
+ return path;
+};
+
+export const pageTrackingUrlMiddleware = (req: Request, res: Response, next: NextFunction): void => {
+ const pageTrackingUrl = getPageTrackingUrl(req.path);
+ res.locals.pageTrackingUrl = pageTrackingUrl;
+ next();
+};
diff --git a/src/main/modules/i18n/index.ts b/src/main/modules/i18n/index.ts
index bdaaa0230..9a9c8586e 100644
--- a/src/main/modules/i18n/index.ts
+++ b/src/main/modules/i18n/index.ts
@@ -67,7 +67,6 @@ export type AllowedLang = (typeof allowedLanguages)[number];
export const COMMON_TRANSLATION_KEYS = [
'serviceName',
'phase',
- 'feedback',
'back',
'languageToggle',
'contactUsForHelp',
diff --git a/src/main/modules/steps/formBuilder/formContent.ts b/src/main/modules/steps/formBuilder/formContent.ts
index 92416b37e..39696773a 100644
--- a/src/main/modules/steps/formBuilder/formContent.ts
+++ b/src/main/modules/steps/formBuilder/formContent.ts
@@ -72,7 +72,6 @@ export function buildFormContent(
errorSummary,
serviceName: t('serviceName'),
phase: t('phase'),
- feedback: t('feedback'),
back: t('back'),
contactUsForHelp: t('contactUsForHelp'),
contactUsForHelpText: t('contactUsForHelpText'),
diff --git a/src/main/views/journeyTemplate.njk b/src/main/views/journeyTemplate.njk
index 419b0bced..06c3cdec3 100644
--- a/src/main/views/journeyTemplate.njk
+++ b/src/main/views/journeyTemplate.njk
@@ -34,7 +34,7 @@
{{ govukPhaseBanner({
tag: { text: t('phase', 'Alpha') },
- html: (t('feedback') | safe)
+ html: (t('feedback', { pageTrackingUrl: pageTrackingUrl }) | safe)
}) }}
diff --git a/src/main/views/stepsTemplate.njk b/src/main/views/stepsTemplate.njk
index 5d14122d6..4d8f7db5c 100644
--- a/src/main/views/stepsTemplate.njk
+++ b/src/main/views/stepsTemplate.njk
@@ -46,7 +46,7 @@
tag: {
text: (phase or t('phase') or 'ALPHA') | safe
},
- html: ((feedback or t('feedback') or '')) | safe
+ html: ((feedback or t('feedback', { pageTrackingUrl: pageTrackingUrl }) or '')) | safe
}) }}
{% if backUrl %}
diff --git a/src/main/views/template.njk b/src/main/views/template.njk
index 82f1e8202..2bb581d55 100644
--- a/src/main/views/template.njk
+++ b/src/main/views/template.njk
@@ -47,7 +47,7 @@
tag: {
text: (phase or t('phase') or 'ALPHA') | safe
},
- html: ((feedback or t('feedback') or '')) | safe
+ html: ((feedback or t('feedback', { pageTrackingUrl: pageTrackingUrl }) or '')) | safe
}) }}
{% if backUrl %}
diff --git a/src/test/ui/data/page-data/confirmationOfNoticeGiven.page.data.ts b/src/test/ui/data/page-data/confirmationOfNoticeGiven.page.data.ts
index fad446c9e..9751877c6 100644
--- a/src/test/ui/data/page-data/confirmationOfNoticeGiven.page.data.ts
+++ b/src/test/ui/data/page-data/confirmationOfNoticeGiven.page.data.ts
@@ -17,4 +17,6 @@ export const confirmationOfNoticeGiven = {
selectIfNoticeOfIntentionGivenErrorMessage(claimantName: string): string {
return `Select if ${claimantName} gave you notice of their intention to begin possession proceedings`;
},
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `confirmation-of-notice-given`,
};
diff --git a/src/test/ui/data/page-data/contactPreferenceEmailOrPost.page.data.ts b/src/test/ui/data/page-data/contactPreferenceEmailOrPost.page.data.ts
index d7f3d22fb..7f35477e9 100644
--- a/src/test/ui/data/page-data/contactPreferenceEmailOrPost.page.data.ts
+++ b/src/test/ui/data/page-data/contactPreferenceEmailOrPost.page.data.ts
@@ -22,4 +22,6 @@ export const contactPreferenceEmailOrPost = {
selectHowYouWantToReceiveUpdatesErrorMessage: `Select how you want to receive updates`,
enterEmailAddressErrorMessage: `Enter your email address`,
invalidEmailAddressErrorMessage: `Enter an email address in the correct format, like name@example.com`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `contact-preferences-email-or-post`,
};
diff --git a/src/test/ui/data/page-data/contactPreferencesTelephone.page.data.ts b/src/test/ui/data/page-data/contactPreferencesTelephone.page.data.ts
index 6b5e69aa5..876f57564 100644
--- a/src/test/ui/data/page-data/contactPreferencesTelephone.page.data.ts
+++ b/src/test/ui/data/page-data/contactPreferencesTelephone.page.data.ts
@@ -18,4 +18,6 @@ export const contactPreferencesTelephone = {
selectWhetherHappyToBeContactedByTelephoneErrorMessage: `Select whether you’re happy to be contacted by telephone`,
enterUKPhoneNumberErrorMessage: `Enter a UK phone number`,
enterUKPhoneNumberFormatErrorMessage: `Enter a phone number, like 01632 960 001 or 07700 900 982`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `contact-preferences-telephone`,
};
diff --git a/src/test/ui/data/page-data/contactPreferencesTextMessage.page.data.ts b/src/test/ui/data/page-data/contactPreferencesTextMessage.page.data.ts
index 93aaf3595..0c41202b5 100644
--- a/src/test/ui/data/page-data/contactPreferencesTextMessage.page.data.ts
+++ b/src/test/ui/data/page-data/contactPreferencesTextMessage.page.data.ts
@@ -11,4 +11,6 @@ export const contactPreferencesTextMessage = {
backLink: `Back`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
selectIfYouWantErrorMessage: `Select if you want to be contacted by text message.`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `contact-preferences-text-message`,
};
diff --git a/src/test/ui/data/page-data/dateOfBirth.page.data.ts b/src/test/ui/data/page-data/dateOfBirth.page.data.ts
index f307ebc92..ce601bb71 100644
--- a/src/test/ui/data/page-data/dateOfBirth.page.data.ts
+++ b/src/test/ui/data/page-data/dateOfBirth.page.data.ts
@@ -25,4 +25,6 @@ export const dateOfBirth = {
backLink: `Back`,
saveAndContinueButton: `Save and continue`,
saveForLaterButton: `Save for later`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `date-of-birth`,
};
diff --git a/src/test/ui/data/page-data/defendantNameCapture.page.data.ts b/src/test/ui/data/page-data/defendantNameCapture.page.data.ts
index dabcad090..ee97169e1 100644
--- a/src/test/ui/data/page-data/defendantNameCapture.page.data.ts
+++ b/src/test/ui/data/page-data/defendantNameCapture.page.data.ts
@@ -14,4 +14,6 @@ export const defendantNameCapture = {
enterYourLastNameErrorMessage: `Enter your last name`,
enterFirstNameMaxLengthErrorMessage: `First name must be 60 characters or less`,
enterLastNameMaxLengthErrorMessage: `Last name must be 60 characters or less`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `defendant-name-capture`,
};
diff --git a/src/test/ui/data/page-data/defendantNameConfirmation.page.data.ts b/src/test/ui/data/page-data/defendantNameConfirmation.page.data.ts
index 633ab5283..4f16b3a94 100644
--- a/src/test/ui/data/page-data/defendantNameConfirmation.page.data.ts
+++ b/src/test/ui/data/page-data/defendantNameConfirmation.page.data.ts
@@ -24,4 +24,6 @@ export const defendantNameConfirmation = {
enterYourLastNameErrorMessage: `Enter your last name`,
enterFirstNameMaxLengthErrorMessage: `First name must be 60 characters or less`,
enterLastNameMaxLengthErrorMessage: `Last name must be 60 characters or less`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `defendant-name-confirmation`,
};
diff --git a/src/test/ui/data/page-data/disputeClaimInterstitial.page.data.ts b/src/test/ui/data/page-data/disputeClaimInterstitial.page.data.ts
index e14d80054..45098e782 100644
--- a/src/test/ui/data/page-data/disputeClaimInterstitial.page.data.ts
+++ b/src/test/ui/data/page-data/disputeClaimInterstitial.page.data.ts
@@ -17,4 +17,6 @@ export const disputeClaimInterstitial = {
cancelLink: `Cancel`,
cymraegLink: `Cymraeg`,
backLink: `Back`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `dispute-claim-interstitial`,
};
diff --git a/src/test/ui/data/page-data/feedback.page.data.ts b/src/test/ui/data/page-data/feedback.page.data.ts
new file mode 100644
index 000000000..4d6e88541
--- /dev/null
+++ b/src/test/ui/data/page-data/feedback.page.data.ts
@@ -0,0 +1,9 @@
+export const feedback = {
+ finishSurveyButton: `Finish Survey`,
+ tellUsWhatYouThinkParagraph: `Tell us what you think!`,
+ weReallyAppreciateYourFeedbackParagraph: `We'd really appreciate your feedback, but please note, you will not receive a reply to comments left here`,
+ ifYouHaveAProblemParagraph: `If you have a problem that needs a response, please contact us on;`,
+ telephoneNumberParagraph: `Phone: [telephone number tbc] (Opening times Monday to Friday, XXam to XXpm)`,
+ emailParagraph: `Email: [email TBC] (We aim to respond within 10 working days)`,
+ pleaseLeaveYourFeedbackHeader: `Please leave your feedback in the space below (make sure you do not include any personal or financial details).`,
+};
diff --git a/src/test/ui/data/page-data/freeLegalAdvice.page.data.ts b/src/test/ui/data/page-data/freeLegalAdvice.page.data.ts
index 6064d76a2..404ef4c58 100644
--- a/src/test/ui/data/page-data/freeLegalAdvice.page.data.ts
+++ b/src/test/ui/data/page-data/freeLegalAdvice.page.data.ts
@@ -25,4 +25,6 @@ export const freeLegalAdvice = {
backLink: `Back`,
youMustSayAboutFreeLegalAdviceErrorMessage: `You must say if you've had any free legal advice`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `free-legal-advice`,
};
diff --git a/src/test/ui/data/page-data/index.ts b/src/test/ui/data/page-data/index.ts
index 123623583..65b434706 100644
--- a/src/test/ui/data/page-data/index.ts
+++ b/src/test/ui/data/page-data/index.ts
@@ -25,3 +25,4 @@ export * from './tenancyDateDetails.page.data';
export * from './dashboard.page.data';
export * from './landlordLicensed.page.data';
export * from './writtenTerms.page.data';
+export * from './feedback.page.data';
diff --git a/src/test/ui/data/page-data/landlordLicensed.page.data.ts b/src/test/ui/data/page-data/landlordLicensed.page.data.ts
index 69264be77..1e9414a98 100644
--- a/src/test/ui/data/page-data/landlordLicensed.page.data.ts
+++ b/src/test/ui/data/page-data/landlordLicensed.page.data.ts
@@ -13,4 +13,6 @@ export const landlordLicensed = {
cymraegLink: `Cymraeg`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
selectIfYouAgreeWithLandlordsClaimLicensedErrorMessage: `Select if you agree with the landlord’s claim to be licensed`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `landlord-licensed`,
};
diff --git a/src/test/ui/data/page-data/landlordRegistered.page.data.ts b/src/test/ui/data/page-data/landlordRegistered.page.data.ts
index e99e57eb0..6627e5831 100644
--- a/src/test/ui/data/page-data/landlordRegistered.page.data.ts
+++ b/src/test/ui/data/page-data/landlordRegistered.page.data.ts
@@ -13,4 +13,6 @@ export const landlordRegistered = {
cymraegLink: `Cymraeg`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
selectIfYouAgreeWithLandlordsClaimRegisteredErrorMessage: `Select if you agree with the landlord’s claim to be registered`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `landlord-registered`,
};
diff --git a/src/test/ui/data/page-data/licensedLandlord.page.data.ts b/src/test/ui/data/page-data/licensedLandlord.page.data.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/test/ui/data/page-data/noticeDateWhenNotProvided.page.data.ts b/src/test/ui/data/page-data/noticeDateWhenNotProvided.page.data.ts
index 7b8aa054e..c18df6109 100644
--- a/src/test/ui/data/page-data/noticeDateWhenNotProvided.page.data.ts
+++ b/src/test/ui/data/page-data/noticeDateWhenNotProvided.page.data.ts
@@ -14,4 +14,6 @@ export const noticeDateWhenNotProvided = {
signOutLink: `Sign out`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
theDateYouReceiveNoticeErrorMessage: `The date you received notice must either be today’s date or in the past`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `confirmation-of-notice-date-when-not-provided`,
};
diff --git a/src/test/ui/data/page-data/noticeDateWhenProvided.page.data.ts b/src/test/ui/data/page-data/noticeDateWhenProvided.page.data.ts
index c9e1ac1c9..cad050b8a 100644
--- a/src/test/ui/data/page-data/noticeDateWhenProvided.page.data.ts
+++ b/src/test/ui/data/page-data/noticeDateWhenProvided.page.data.ts
@@ -18,6 +18,8 @@ export const noticeDateWhenProvided = {
signOutLink: `Sign out`,
thereIsAProblemErrorMessageHeader: `There is a problem`,
theDateYouReceiveNoticeErrorMessage: `The date you received notice must either be today’s date or in the past`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `confirmation-of-notice-date-when-provided`,
};
export function convertDateFormat(dateString: string): string {
diff --git a/src/test/ui/data/page-data/paymentInterstitial.page.data.ts b/src/test/ui/data/page-data/paymentInterstitial.page.data.ts
index ab884ebd3..99789dc19 100644
--- a/src/test/ui/data/page-data/paymentInterstitial.page.data.ts
+++ b/src/test/ui/data/page-data/paymentInterstitial.page.data.ts
@@ -10,4 +10,6 @@ export const paymentInterstitial = {
continueButton: `Continue`,
cancelLink: `Cancel`,
backLink: `Back`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `payment-interstitial`,
};
diff --git a/src/test/ui/data/page-data/repaymentsMade.page.data.ts b/src/test/ui/data/page-data/repaymentsMade.page.data.ts
index 9fd0d0f60..d6d56fd8c 100644
--- a/src/test/ui/data/page-data/repaymentsMade.page.data.ts
+++ b/src/test/ui/data/page-data/repaymentsMade.page.data.ts
@@ -15,4 +15,6 @@ export const repaymentsMade = {
mustBeUnderCharacterLimitErrorMessage: `Must be 500 characters or fewer`,
saveForLaterButton: `Save for later`,
backLink: `Back`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `repayments-made`,
};
diff --git a/src/test/ui/data/page-data/startNow.page.data.ts b/src/test/ui/data/page-data/startNow.page.data.ts
index db5d20b66..c28f6411c 100644
--- a/src/test/ui/data/page-data/startNow.page.data.ts
+++ b/src/test/ui/data/page-data/startNow.page.data.ts
@@ -23,4 +23,6 @@ export const startNow = {
contactUsForHelpText: `Contact us for help`,
backLink: `Back`,
cymraegLink: `Cymraeg`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `start-now`,
};
diff --git a/src/test/ui/data/page-data/tenancyDateDetails.page.data.ts b/src/test/ui/data/page-data/tenancyDateDetails.page.data.ts
index 46c33027f..cdc7f4ece 100644
--- a/src/test/ui/data/page-data/tenancyDateDetails.page.data.ts
+++ b/src/test/ui/data/page-data/tenancyDateDetails.page.data.ts
@@ -27,6 +27,8 @@ export const tenancyDateDetails = {
monthMissingErrorMessage: `Your tenancy start date must include a month`,
yearMissingErrorMessage: `Your tenancy start date must include a year`,
futureDateErrorMessage: `Tenancy start date must be in the past`,
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `tenancy-date-details`,
};
export function convertDateFormatTenancyDate(dateString: string): string {
diff --git a/src/test/ui/data/page-data/tenancyDateUnknown.page.data.ts b/src/test/ui/data/page-data/tenancyDateUnknown.page.data.ts
index 2a8b15f68..65131b100 100644
--- a/src/test/ui/data/page-data/tenancyDateUnknown.page.data.ts
+++ b/src/test/ui/data/page-data/tenancyDateUnknown.page.data.ts
@@ -17,4 +17,6 @@ export const tenancyDateUnknown = {
yearMissingErrorMessage: 'Your tenancy start date must include a year',
realDateErrorMessage: 'Tenancy start date must be a real date',
backLink: 'Back',
+ feedbackLink: `feedback (opens in new tab)`,
+ pageSlug: `tenancy-date-unknown`,
};
diff --git a/src/test/ui/e2eTest/respondToClaimWales.spec.ts b/src/test/ui/e2eTest/respondToClaimWales.spec.ts
index 798a9f26d..553052af2 100644
--- a/src/test/ui/e2eTest/respondToClaimWales.spec.ts
+++ b/src/test/ui/e2eTest/respondToClaimWales.spec.ts
@@ -24,6 +24,7 @@ const home_url = config.get('e2e.testUrl') as string;
test.beforeEach(async ({ page }) => {
initializeExecutor(page);
process.env.WALES_POSTCODE = 'YES';
+ process.env.CLAIMANT_NAME = submitCaseApiDataWales.submitCasePayload.claimantName;
await performAction('createCaseAPI', { data: createCaseApiWalesData.createCasePayload });
await performAction('submitCaseAPI', { data: submitCaseApiDataWales.submitCasePayload });
await performAction('fetchPINsAPI');
diff --git a/src/test/ui/functional/confirmationOfNoticeGiven.pft.ts b/src/test/ui/functional/confirmationOfNoticeGiven.pft.ts
index ccdc38c04..aa1cafda2 100644
--- a/src/test/ui/functional/confirmationOfNoticeGiven.pft.ts
+++ b/src/test/ui/functional/confirmationOfNoticeGiven.pft.ts
@@ -1,5 +1,5 @@
import { submitCaseApiData } from '../data/api-data';
-import { confirmationOfNoticeGiven, dashboard, tenancyDateUnknown } from '../data/page-data';
+import { confirmationOfNoticeGiven, dashboard, feedback, tenancyDateUnknown } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
let claimantName = '';
@@ -19,6 +19,10 @@ export async function confirmationOfNoticeGivenErrorValidation(): Promise
}
export async function confirmationOfNoticeGivenNavigationTests(): Promise {
+ await performValidation('pageNavigation', confirmationOfNoticeGiven.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: confirmationOfNoticeGiven.pageSlug,
+ });
await performValidation('pageNavigation', confirmationOfNoticeGiven.backLink, tenancyDateUnknown.mainHeader);
await performAction('clickRadioButton', confirmationOfNoticeGiven.yesRadioOption);
await performValidation('pageNavigation', confirmationOfNoticeGiven.saveForLaterButton, dashboard.mainHeader);
diff --git a/src/test/ui/functional/contactPreferenceEmailOrPost.pft.ts b/src/test/ui/functional/contactPreferenceEmailOrPost.pft.ts
index b546d709d..79a9eeebd 100644
--- a/src/test/ui/functional/contactPreferenceEmailOrPost.pft.ts
+++ b/src/test/ui/functional/contactPreferenceEmailOrPost.pft.ts
@@ -1,4 +1,4 @@
-import { contactPreferenceEmailOrPost } from '../data/page-data';
+import { contactPreferenceEmailOrPost, feedback } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function contactPreferenceEmailOrPostErrorValidation(): Promise {
@@ -85,9 +85,14 @@ export async function contactPreferenceEmailOrPostErrorValidation(): Promise {
- if (process.env.CORRESPONDENCE_ADDRESS === 'UNKNOWN') {
+
+export async function contactPreferenceEmailOrPostNavigationTests(): Promise {
+ await performValidation('pageNavigation', contactPreferenceEmailOrPost.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: contactPreferenceEmailOrPost.pageSlug,
+ });
+ //--The below line is commented out as we have an open bug - HDPI-5396
+ /*if (process.env.CORRESPONDENCE_ADDRESS === 'UNKNOWN') {
await performValidation(
'pageNavigation',
contactPreferenceEmailOrPost.backLink,
@@ -102,4 +107,5 @@ export async function contactPreferenceEmailOrPostErrorValidation(): Promise {
@@ -46,6 +46,10 @@ export async function contactPreferencesTelephoneErrorValidation(): Promise {
+ await performValidation('pageNavigation', contactPreferencesTelephone.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: contactPreferencesTelephone.pageSlug,
+ });
await performValidation(
'pageNavigation',
contactPreferencesTelephone.backLink,
diff --git a/src/test/ui/functional/contactPreferencesTextMessage.pft.ts b/src/test/ui/functional/contactPreferencesTextMessage.pft.ts
index 6a21e102d..cc30bb51a 100644
--- a/src/test/ui/functional/contactPreferencesTextMessage.pft.ts
+++ b/src/test/ui/functional/contactPreferencesTextMessage.pft.ts
@@ -1,4 +1,4 @@
-import { contactPreferencesTelephone, contactPreferencesTextMessage, dashboard } from '../data/page-data';
+import { contactPreferencesTelephone, contactPreferencesTextMessage, dashboard, feedback } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function contactPreferencesTextMessageErrorValidation(): Promise {
@@ -10,6 +10,10 @@ export async function contactPreferencesTextMessageErrorValidation(): Promise {
+ await performValidation('pageNavigation', contactPreferencesTextMessage.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: contactPreferencesTextMessage.pageSlug,
+ });
await performValidation(
'pageNavigation',
contactPreferencesTextMessage.backLink,
diff --git a/src/test/ui/functional/dateOfBirth.pft.ts b/src/test/ui/functional/dateOfBirth.pft.ts
index 0c428bb0a..960e6a2a1 100644
--- a/src/test/ui/functional/dateOfBirth.pft.ts
+++ b/src/test/ui/functional/dateOfBirth.pft.ts
@@ -1,7 +1,11 @@
-import { dashboard, dateOfBirth, defendantNameCapture } from '../data/page-data';
+import { dashboard, dateOfBirth, defendantNameCapture, feedback } from '../data/page-data';
import { performValidation } from '../utils/controller';
export async function dateOfBirthNavigationTests(): Promise {
+ await performValidation('pageNavigation', dateOfBirth.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: dateOfBirth.pageSlug,
+ });
await performValidation('pageNavigation', dateOfBirth.backLink, defendantNameCapture.mainHeader);
await performValidation('pageNavigation', dateOfBirth.saveForLaterButton, dashboard.mainHeader);
}
diff --git a/src/test/ui/functional/defendantNameCapture.pft.ts b/src/test/ui/functional/defendantNameCapture.pft.ts
index f62be60a5..d7dff357f 100644
--- a/src/test/ui/functional/defendantNameCapture.pft.ts
+++ b/src/test/ui/functional/defendantNameCapture.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, defendantNameCapture, freeLegalAdvice } from '../data/page-data';
+import { dashboard, defendantNameCapture, feedback, freeLegalAdvice } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
const overMaxLengthString = 'A'.repeat(61);
@@ -33,6 +33,10 @@ export async function defendantNameCaptureErrorValidation(): Promise {
});
}
export async function defendantNameCaptureNavigationTests(): Promise {
+ await performValidation('pageNavigation', defendantNameCapture.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: defendantNameCapture.pageSlug,
+ });
await performValidation('pageNavigation', defendantNameCapture.backLink, freeLegalAdvice.mainHeader);
await defendantNameCaptureInputValuesPrePopulated();
}
diff --git a/src/test/ui/functional/defendantNameConfirmation.pft.ts b/src/test/ui/functional/defendantNameConfirmation.pft.ts
index e2fad7c6e..23e640d05 100644
--- a/src/test/ui/functional/defendantNameConfirmation.pft.ts
+++ b/src/test/ui/functional/defendantNameConfirmation.pft.ts
@@ -1,4 +1,4 @@
-import { defendantNameConfirmation, freeLegalAdvice } from '../data/page-data';
+import { defendantNameConfirmation, feedback, freeLegalAdvice } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
import { defendantNameCaptureInputValuesPrePopulated } from './defendantNameCapture.pft';
@@ -46,6 +46,10 @@ export async function defendantNameConfirmationErrorValidation(): Promise
});
}
export async function defendantNameConfirmationNavigationTests(): Promise {
+ await performValidation('pageNavigation', defendantNameConfirmation.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: defendantNameConfirmation.pageSlug,
+ });
await performValidation('pageNavigation', defendantNameConfirmation.backLink, freeLegalAdvice.mainHeader);
await performAction('clickRadioButton', {
question: defendantNameConfirmation.mainHeader,
diff --git a/src/test/ui/functional/disputeClaimInterstitial.pft.ts b/src/test/ui/functional/disputeClaimInterstitial.pft.ts
index 57bd221eb..e6ea8cb21 100644
--- a/src/test/ui/functional/disputeClaimInterstitial.pft.ts
+++ b/src/test/ui/functional/disputeClaimInterstitial.pft.ts
@@ -3,10 +3,15 @@ import {
contactPreferencesTextMessage,
dashboard,
disputeClaimInterstitial,
+ feedback,
} from '../data/page-data';
import { performValidation } from '../utils/controller';
export async function disputeClaimInterstitialNavigationTests(): Promise {
+ await performValidation('pageNavigation', disputeClaimInterstitial.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: disputeClaimInterstitial.pageSlug,
+ });
if (process.env.CONTACT_PREFERENCES_TELEPHONE === 'YES') {
await performValidation(
'pageNavigation',
diff --git a/src/test/ui/functional/freeLegalAdvice.pft.ts b/src/test/ui/functional/freeLegalAdvice.pft.ts
index 6508bbb9c..4df11f34d 100644
--- a/src/test/ui/functional/freeLegalAdvice.pft.ts
+++ b/src/test/ui/functional/freeLegalAdvice.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, freeLegalAdvice, startNow } from '../data/page-data';
+import { dashboard, feedback, freeLegalAdvice, startNow } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function freeLegalAdviceErrorValidation(): Promise {
@@ -10,6 +10,10 @@ export async function freeLegalAdviceErrorValidation(): Promise {
}
export async function freeLegalAdviceNavigationTests(): Promise {
+ await performValidation('pageNavigation', freeLegalAdvice.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: freeLegalAdvice.pageSlug,
+ });
await performValidation('pageNavigation', freeLegalAdvice.backLink, startNow.mainHeader);
await performAction('clickRadioButton', freeLegalAdvice.yesRadioOption);
await performValidation('pageNavigation', freeLegalAdvice.saveForLaterButton, dashboard.mainHeader);
diff --git a/src/test/ui/functional/landlordLicensed.pft.ts b/src/test/ui/functional/landlordLicensed.pft.ts
index fc21f565f..69f32ec38 100644
--- a/src/test/ui/functional/landlordLicensed.pft.ts
+++ b/src/test/ui/functional/landlordLicensed.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, landlordLicensed, landlordRegistered, writtenTerms } from '../data/page-data';
+import { dashboard, feedback, landlordLicensed, landlordRegistered, writtenTerms } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
import { setTenancyTypeDetailsBackNavigation } from './tenancyTypeDetails.pft';
@@ -12,6 +12,10 @@ export async function landlordLicensedErrorValidation(): Promise {
}
export async function landlordLicensedNavigationTests(): Promise {
+ await performValidation('pageNavigation', landlordLicensed.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: landlordLicensed.pageSlug,
+ });
await performValidation('pageNavigation', landlordLicensed.backLink, landlordRegistered.mainHeader);
await performAction('clickRadioButton', landlordLicensed.yesRadioOption);
await performValidation('pageNavigation', landlordLicensed.saveForLaterButton, dashboard.mainHeader);
diff --git a/src/test/ui/functional/landlordRegistered.pft.ts b/src/test/ui/functional/landlordRegistered.pft.ts
index 7b8b1dc73..8d6f177b8 100644
--- a/src/test/ui/functional/landlordRegistered.pft.ts
+++ b/src/test/ui/functional/landlordRegistered.pft.ts
@@ -1,5 +1,5 @@
import { submitCaseApiData } from '../data/api-data';
-import { dashboard, disputeClaimInterstitial, landlordRegistered } from '../data/page-data';
+import { dashboard, disputeClaimInterstitial, feedback, landlordRegistered } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function landlordRegisteredErrorValidation(): Promise {
@@ -12,6 +12,10 @@ export async function landlordRegisteredErrorValidation(): Promise {
export async function landlordRegisteredNavigationTests(): Promise {
const claimantsName = submitCaseApiData.submitCasePayload.claimantName;
+ await performValidation('pageNavigation', landlordRegistered.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: landlordRegistered.pageSlug,
+ });
await performValidation(
'pageNavigation',
landlordRegistered.backLink,
diff --git a/src/test/ui/functional/noticeDateWhenNotProvided.pft.ts b/src/test/ui/functional/noticeDateWhenNotProvided.pft.ts
index 0108c784e..20871a6a7 100644
--- a/src/test/ui/functional/noticeDateWhenNotProvided.pft.ts
+++ b/src/test/ui/functional/noticeDateWhenNotProvided.pft.ts
@@ -1,4 +1,4 @@
-import { confirmationOfNoticeGiven, dashboard, noticeDateWhenNotProvided } from '../data/page-data';
+import { confirmationOfNoticeGiven, dashboard, feedback, noticeDateWhenNotProvided } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function noticeDateWhenNotProvidedErrorValidation(): Promise {
@@ -15,6 +15,10 @@ export async function noticeDateWhenNotProvidedErrorValidation(): Promise
}
export async function noticeDateWhenNotProvidedNavigationTests(): Promise {
+ await performValidation('pageNavigation', noticeDateWhenNotProvided.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: noticeDateWhenNotProvided.pageSlug,
+ });
await performValidation('pageNavigation', noticeDateWhenNotProvided.backLink, confirmationOfNoticeGiven.mainHeader);
await performValidation('pageNavigation', noticeDateWhenNotProvided.saveForLaterButton, dashboard.mainHeader);
}
diff --git a/src/test/ui/functional/paymentInterstitial.pft.ts b/src/test/ui/functional/paymentInterstitial.pft.ts
index 7eacfc840..782493ace 100644
--- a/src/test/ui/functional/paymentInterstitial.pft.ts
+++ b/src/test/ui/functional/paymentInterstitial.pft.ts
@@ -1,7 +1,11 @@
-import { counterClaim, dashboard, paymentInterstitial } from '../data/page-data';
+import { counterClaim, dashboard, feedback, paymentInterstitial } from '../data/page-data';
import { performValidation } from '../utils/controller';
export async function paymentInterstitialNavigationTests(): Promise {
+ await performValidation('pageNavigation', paymentInterstitial.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: paymentInterstitial.pageSlug,
+ });
await performValidation('pageNavigation', paymentInterstitial.backLink, counterClaim.mainHeader);
await performValidation('pageNavigation', paymentInterstitial.cancelLink, dashboard.mainHeader);
}
diff --git a/src/test/ui/functional/repaymentsMade.pft.ts b/src/test/ui/functional/repaymentsMade.pft.ts
index 616d73161..0acc127ed 100644
--- a/src/test/ui/functional/repaymentsMade.pft.ts
+++ b/src/test/ui/functional/repaymentsMade.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, paymentInterstitial, repaymentsMade } from '../data/page-data';
+import { dashboard, feedback, paymentInterstitial, repaymentsMade } from '../data/page-data';
import { performAction, performValidation } from '../utils/controller';
export async function repaymentsMadeErrorValidation(): Promise {
@@ -25,6 +25,10 @@ export async function repaymentsMadeErrorValidation(): Promise {
}
export async function repaymentsMadeNavigationTests(): Promise {
+ await performValidation('pageNavigation', repaymentsMade.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: repaymentsMade.pageSlug,
+ });
await performValidation('pageNavigation', repaymentsMade.backLink, paymentInterstitial.mainHeader);
await performAction('clickRadioButton', repaymentsMade.yesRadioOption);
await performAction('inputText', repaymentsMade.giveDetailsHiddenTextLabel, repaymentsMade.detailsTextInput);
diff --git a/src/test/ui/functional/startNow.pft.ts b/src/test/ui/functional/startNow.pft.ts
new file mode 100644
index 000000000..176ae6c12
--- /dev/null
+++ b/src/test/ui/functional/startNow.pft.ts
@@ -0,0 +1,10 @@
+import { dashboard, feedback, startNow } from '../data/page-data';
+import { performValidation } from '../utils/controller';
+
+export async function startNowNavigationTests(): Promise {
+ await performValidation('pageNavigation', startNow.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: startNow.pageSlug,
+ });
+ await performValidation('pageNavigation', startNow.backLink, dashboard.mainHeader);
+}
diff --git a/src/test/ui/functional/tenancyDateDetails.pft.ts b/src/test/ui/functional/tenancyDateDetails.pft.ts
index 5a93cdcef..9d6dd0772 100644
--- a/src/test/ui/functional/tenancyDateDetails.pft.ts
+++ b/src/test/ui/functional/tenancyDateDetails.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, tenancyDateDetails, tenancyDetails } from '../data/page-data';
+import { dashboard, feedback, tenancyDateDetails, tenancyTypeDetails } from '../data/page-data';
import { performAction, performActions, performValidation } from '../utils/controller';
export async function tenancyDateDetailsErrorValidation(): Promise {
@@ -50,7 +50,11 @@ export async function tenancyDateDetailsErrorValidation(): Promise {
}
export async function tenancyDateDetailsNavigationTests(): Promise {
- await performValidation('pageNavigation', tenancyDateDetails.backLink, tenancyDetails.mainHeader);
+ await performValidation('pageNavigation', tenancyDateDetails.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: tenancyDateDetails.pageSlug,
+ });
+ await performValidation('pageNavigation', tenancyDateDetails.backLink, tenancyTypeDetails.mainHeader);
await performAction('clickRadioButton', tenancyDateDetails.yesRadioOption);
await performValidation('pageNavigation', tenancyDateDetails.saveForLaterButton, dashboard.mainHeader);
}
diff --git a/src/test/ui/functional/tenancyDateUnknown.pft.ts b/src/test/ui/functional/tenancyDateUnknown.pft.ts
index 803124d83..e830f63a1 100644
--- a/src/test/ui/functional/tenancyDateUnknown.pft.ts
+++ b/src/test/ui/functional/tenancyDateUnknown.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, tenancyDateUnknown, tenancyTypeDetails } from '../data/page-data';
+import { dashboard, feedback, tenancyDateUnknown, tenancyTypeDetails } from '../data/page-data';
import { performAction, performActions, performValidation } from '../utils/controller';
export async function tenancyDateUnknownErrorValidation(): Promise {
@@ -40,6 +40,10 @@ export async function tenancyDateUnknownErrorValidation(): Promise {
}
export async function tenancyDateUnknownNavigationTests(): Promise {
+ await performValidation('pageNavigation', tenancyDateUnknown.feedbackLink, {
+ element: feedback.tellUsWhatYouThinkParagraph,
+ pageSlug: tenancyDateUnknown.pageSlug,
+ });
await performValidation('pageNavigation', tenancyDateUnknown.backLink, tenancyTypeDetails.mainHeader);
await performActions(
'Enter Date',
diff --git a/src/test/ui/functional/tenancyTypeDetails.pft.ts b/src/test/ui/functional/tenancyTypeDetails.pft.ts
index f900f45de..ec0ba372b 100644
--- a/src/test/ui/functional/tenancyTypeDetails.pft.ts
+++ b/src/test/ui/functional/tenancyTypeDetails.pft.ts
@@ -1,4 +1,4 @@
-import { dashboard, disputeClaimInterstitial, tenancyTypeDetails } from '../data/page-data';
+import { dashboard, disputeClaimInterstitial, tenancyTypeDetails, writtenTerms } from '../data/page-data';
import { claimantsName } from '../utils/actions/custom-actions';
import { performAction, performValidation } from '../utils/controller';
@@ -25,10 +25,18 @@ export async function tenancyTypeDetailsErrorValidation(): Promise {
}
export async function tenancyTypeDetailsNavigationTests(): Promise {
- if (claimantsName) {
- const backHeader = _backNavigationHeader ?? disputeClaimInterstitial.getMainHeader(claimantsName);
- _backNavigationHeader = null;
- await performValidation('pageNavigation', tenancyTypeDetails.backLink, backHeader);
+ if (process.env.WALES_POSTCODE === 'YES') {
+ if (claimantsName) {
+ await performValidation('pageNavigation', tenancyTypeDetails.backLink, writtenTerms.mainHeader);
+ }
+ } else {
+ if (claimantsName) {
+ await performValidation(
+ 'pageNavigation',
+ tenancyTypeDetails.backLink,
+ disputeClaimInterstitial.getMainHeader(claimantsName)
+ );
+ }
}
await performAction('clickRadioButton', tenancyTypeDetails.yesRadioOption);
await performValidation('pageNavigation', tenancyTypeDetails.saveForLaterButton, dashboard.mainHeader);
diff --git a/src/test/ui/utils/controller.ts b/src/test/ui/utils/controller.ts
index d77bc965d..7cdb99f5c 100644
--- a/src/test/ui/utils/controller.ts
+++ b/src/test/ui/utils/controller.ts
@@ -40,8 +40,6 @@ async function detectPageNavigation(): Promise {
const currentUrl = executor.page.url();
if (!startAxeAudit && executor.page.url().includes('start-now')) {
startAxeAudit = true;
- }
- if (!startFunctionalTests && executor.page.url().includes('free-legal-advice')) {
startFunctionalTests = true;
}
const pageNavigated = currentUrl !== previousUrl;
@@ -54,7 +52,7 @@ async function detectPageNavigation(): Promise {
}
async function validatePageIfNavigated(action: string): Promise {
- if (action.includes('click') || action.includes('navigate')) {
+ if (action.includes('click') || action.includes('navigateToUrl')) {
const pageNavigated = await detectPageNavigation();
const executor = getExecutor();
if (pageNavigated) {
diff --git a/src/test/ui/utils/validations/custom-validations/pageContent.validation.ts b/src/test/ui/utils/validations/custom-validations/pageContent.validation.ts
index cb01d0d93..a56ce5167 100644
--- a/src/test/ui/utils/validations/custom-validations/pageContent.validation.ts
+++ b/src/test/ui/utils/validations/custom-validations/pageContent.validation.ts
@@ -149,6 +149,7 @@ export class PageContentValidation implements IValidation {
key.includes('Input') ||
key.includes('Hidden') ||
key.includes('Validation') ||
+ key.includes('pageSlug') ||
key.includes('ErrorMessage')
) {
continue;
diff --git a/src/test/ui/utils/validations/custom-validations/pageNavigation.validation.ts b/src/test/ui/utils/validations/custom-validations/pageNavigation.validation.ts
index b3c84128f..82f4375e1 100644
--- a/src/test/ui/utils/validations/custom-validations/pageNavigation.validation.ts
+++ b/src/test/ui/utils/validations/custom-validations/pageNavigation.validation.ts
@@ -4,7 +4,7 @@ import * as path from 'path';
import { Page, expect } from '@playwright/test';
import { performAction } from '../../controller';
-import { IValidation } from '../../interfaces';
+import { IValidation, validationRecord } from '../../interfaces';
type NavigationTestResult = {
pageUrl: string;
@@ -16,6 +16,7 @@ type NavigationTestResult = {
error?: string;
hasPFTFile: boolean;
sourcePage?: string;
+ validationType?: 'element' | 'url';
};
export class PageNavigationValidation implements IValidation {
@@ -29,7 +30,7 @@ export class PageNavigationValidation implements IValidation {
private static readonly MAPPING_PATH = path.join(__dirname, '../../../config/urlToFileMapping.config.ts');
private static readonly PFT_DIR = path.join(__dirname, '../../../functional');
private static currentPageUrl: string = '';
- private static currentSourcePage: string | null = null; // Track the source page that initiated navigation
+ private static currentSourcePage: string | null = null;
static setSourcePage(pageName: string): void {
PageNavigationValidation.currentSourcePage = pageName;
@@ -39,103 +40,154 @@ export class PageNavigationValidation implements IValidation {
PageNavigationValidation.currentSourcePage = null;
}
- async validate(page: Page, validation: string, navigateButton: string, fieldName: string): Promise {
+ async validate(page: Page, validation: string, navigateButton: string, fieldName: validationRecord): Promise {
PageNavigationValidation.currentPageUrl = page.url();
+ let newPage: Page | null = null;
+ let isNewWindow = false;
+
if (navigateButton) {
- if (navigateButton.includes('Back')) {
+ const popupPromise = page
+ .context()
+ .waitForEvent('page')
+ .catch(() => null);
+
+ if (navigateButton.includes('Back') || navigateButton.includes('feedback')) {
await performAction('clickLink', navigateButton);
+ await page.waitForTimeout(200);
} else {
await performAction('clickButton', navigateButton);
}
- }
- if (validation !== 'mainHeader' && validation !== 'pageNavigation') {
- if (PageNavigationValidation.currentPageUrl) {
- await performAction('navigateToUrl', PageNavigationValidation.currentPageUrl);
+
+ const popup = await Promise.race([popupPromise, new Promise(resolve => setTimeout(() => resolve(null), 1000))]);
+
+ if (popup && (popup as Page).url() !== 'about:blank') {
+ newPage = popup as Page;
+ isNewWindow = true;
+ await newPage.waitForLoadState();
}
- return;
}
+ const pageToValidate = isNewWindow && newPage ? newPage : page;
+
try {
- if (validation === 'mainHeader') {
- await this.validateMainHeader(page, fieldName);
- } else if (validation === 'pageNavigation') {
- await this.validatePageNavigation(page, fieldName);
- }
+ await this.validatePageNavigation(pageToValidate, fieldName);
} finally {
- if (PageNavigationValidation.currentPageUrl) {
+ if (newPage && !newPage.isClosed()) {
+ await newPage.close();
+ }
+ if (
+ PageNavigationValidation.currentPageUrl &&
+ !isNewWindow &&
+ page.url() !== PageNavigationValidation.currentPageUrl
+ ) {
await performAction('navigateToUrl', PageNavigationValidation.currentPageUrl);
}
}
}
- private async validateMainHeader(page: Page, expectedHeader: string): Promise {
- try {
- const locator = page.locator('h1, h1.govuk-heading-xl, h1.govuk-heading-l');
- await expect(locator).toHaveText(expectedHeader);
+ private async validatePageNavigation(page: Page, fieldName: validationRecord): Promise {
+ let elementPassed = true;
+ let urlPassed = true;
+ let elementError: string | undefined;
+ let urlError: string | undefined;
+ let actualElementText = '';
+ let expectedElementText = '';
+ let actualUrl = '';
+ let expectedUrlPattern = '';
- const pageName = await PageNavigationValidation.getPageNameFromUrl(page.url(), page);
- const hasPFTFile = await PageNavigationValidation.hasPFTFile(pageName);
-
- PageNavigationValidation.navigationResults.push({
- pageUrl: page.url(),
- pageName,
- sourcePage: PageNavigationValidation.currentSourcePage || undefined,
- testName: 'Main Header Validation',
- passed: true,
- expected: expectedHeader,
- actual: expectedHeader,
- hasPFTFile,
- });
+ try {
+ if (fieldName && typeof fieldName === 'object') {
+ const validationData = fieldName as any;
+
+ if (validationData.element) {
+ expectedElementText = validationData.element;
+ const locator = page.locator(
+ `h1, h1.govuk-heading-xl, h1.govuk-heading-l, span:text-is("${expectedElementText}")`
+ );
+ try {
+ await expect(locator).toHaveText(expectedElementText);
+ actualElementText = expectedElementText;
+ } catch (error) {
+ elementPassed = false;
+ actualElementText =
+ (await locator
+ .first()
+ .textContent()
+ .catch(() => 'Not found')) || 'Not found';
+ elementError = error instanceof Error ? error.message.split('\n')[0] : String(error);
+ }
+ }
- if (hasPFTFile) {
- PageNavigationValidation.pagesPassed.add(pageName);
+ if (validationData.pageSlug) {
+ try {
+ expectedUrlPattern = `https://www.smartsurvey.co.uk/s/Poss_feedback/?pageurl=respond-to-claim/${validationData.pageSlug}`;
+ actualUrl = page.url();
+ if (actualUrl !== expectedUrlPattern) {
+ urlPassed = false;
+ urlError = `URL mismatch. Expected: ${expectedUrlPattern}, Actual: ${actualUrl}`;
+ }
+ } catch (error) {
+ urlPassed = false;
+ actualUrl = page.url();
+ urlError = error instanceof Error ? error.message.split('\n')[0] : String(error);
+ }
+ }
+ } else {
+ expectedElementText = String(fieldName);
+ const locator = page.locator('h1, h1.govuk-heading-xl, h1.govuk-heading-l');
+ await expect(locator).toHaveText(expectedElementText);
+ actualElementText = expectedElementText;
}
- } catch (error) {
- const actualText = await page
- .locator('h1')
- .first()
- .textContent()
- .catch(() => 'Not found');
const pageName = await PageNavigationValidation.getPageNameFromUrl(page.url(), page);
const hasPFTFile = await PageNavigationValidation.hasPFTFile(pageName);
+ const overallPassed = elementPassed && urlPassed;
+
+ if (!elementPassed) {
+ PageNavigationValidation.navigationResults.push({
+ pageUrl: page.url(),
+ pageName,
+ sourcePage: PageNavigationValidation.currentSourcePage || undefined,
+ testName: 'Page Navigation Element Validation',
+ passed: false,
+ expected: expectedElementText,
+ actual: actualElementText,
+ error: elementError,
+ hasPFTFile,
+ validationType: 'element',
+ });
+ }
- PageNavigationValidation.navigationResults.push({
- pageUrl: page.url(),
- pageName,
- sourcePage: PageNavigationValidation.currentSourcePage || undefined,
- testName: 'Main Header Validation',
- passed: false,
- expected: expectedHeader,
- actual: actualText || 'Not found',
- error: error instanceof Error ? error.message.split('\n')[0] : String(error),
- hasPFTFile,
- });
- }
- }
-
- private async validatePageNavigation(page: Page, expectedHeader: string): Promise {
- try {
- const locator = page.locator('h1, h1.govuk-heading-xl, h1.govuk-heading-l');
- await expect(locator).toHaveText(expectedHeader);
-
- const pageName = await PageNavigationValidation.getPageNameFromUrl(page.url(), page);
- const actualText = await locator.first().textContent();
- const hasPFTFile = await PageNavigationValidation.hasPFTFile(pageName);
-
- PageNavigationValidation.navigationResults.push({
- pageUrl: page.url(),
- pageName,
- sourcePage: PageNavigationValidation.currentSourcePage || undefined,
- testName: 'Page Navigation Validation',
- passed: true,
- expected: expectedHeader,
- actual: actualText || '',
- hasPFTFile,
- });
+ if (!urlPassed && fieldName && typeof fieldName === 'object' && (fieldName as any).pageSlug) {
+ PageNavigationValidation.navigationResults.push({
+ pageUrl: page.url(),
+ pageName,
+ sourcePage: PageNavigationValidation.currentSourcePage || undefined,
+ testName: 'Page Navigation URL Validation',
+ passed: false,
+ expected: expectedUrlPattern,
+ actual: actualUrl,
+ error: urlError || 'Page slug validation failed',
+ hasPFTFile,
+ validationType: 'url',
+ });
+ }
- if (hasPFTFile) {
- PageNavigationValidation.pagesPassed.add(pageName);
+ if (overallPassed) {
+ PageNavigationValidation.navigationResults.push({
+ pageUrl: page.url(),
+ pageName,
+ sourcePage: PageNavigationValidation.currentSourcePage || undefined,
+ testName: 'Page Navigation Validation',
+ passed: true,
+ expected: expectedElementText || 'URL validation passed',
+ actual: actualElementText || page.url(),
+ hasPFTFile,
+ });
+
+ if (hasPFTFile) {
+ PageNavigationValidation.pagesPassed.add(pageName);
+ }
}
} catch (error) {
const pageName = await PageNavigationValidation.getPageNameFromUrl(page.url(), page);
@@ -146,13 +198,28 @@ export class PageNavigationValidation implements IValidation {
.catch(() => 'Not found');
const hasPFTFile = await PageNavigationValidation.hasPFTFile(pageName);
+ let expectedValue: string;
+ if (typeof fieldName === 'object' && fieldName !== null) {
+ const obj = fieldName as any;
+ const parts: string[] = [];
+ if (obj.element) {
+ parts.push(`element: "${obj.element}"`);
+ }
+ if (obj.pageSlug) {
+ parts.push(`pageSlug: "${obj.pageSlug}"`);
+ }
+ expectedValue = `{ ${parts.join(', ')} }`;
+ } else {
+ expectedValue = String(fieldName);
+ }
+
PageNavigationValidation.navigationResults.push({
pageUrl: page.url(),
pageName,
sourcePage: PageNavigationValidation.currentSourcePage || undefined,
testName: 'Page Navigation Validation',
passed: false,
- expected: expectedHeader,
+ expected: expectedValue,
actual: actualText || 'Not found',
error: error instanceof Error ? error.message.split('\n')[0] : String(error),
hasPFTFile,
@@ -296,43 +363,36 @@ export class PageNavigationValidation implements IValidation {
return;
}
- // Track failures by the source page (the page that initiated the navigation)
- const failureDetails = new Map();
+ const failureDetails = new Map();
const failedPages = new Set();
const passedPages = new Set();
- // First, identify all failures
for (const result of PageNavigationValidation.navigationResults) {
if (!result.passed) {
- // If this failure has a source page, mark that source page as failed
if (result.sourcePage) {
failedPages.add(result.sourcePage);
if (result.expected && result.actual) {
failureDetails.set(result.sourcePage, {
expected: result.expected,
actual: result.actual,
+ validationType: result.validationType,
});
}
- }
- // If no source page but the page itself has a PFT file, mark it as failed
- else if (result.hasPFTFile) {
+ } else if (result.hasPFTFile) {
failedPages.add(result.pageName);
if (result.expected && result.actual) {
failureDetails.set(result.pageName, {
expected: result.expected,
actual: result.actual,
+ validationType: result.validationType,
});
}
- }
- // If it's a page without PFT file and no source page (like Dashboard), we can't attribute it
- // So we log it but don't fail any specific page
- else {
+ } else {
console.log(` ⚠️ Unattributed failure on ${result.pageName}: ${result.error}`);
}
}
}
- // A page passes only if it has no failures and has a PFT file
for (const result of PageNavigationValidation.navigationResults) {
if (
result.passed &&
@@ -344,7 +404,6 @@ export class PageNavigationValidation implements IValidation {
}
}
- // Add pages that were explicitly marked as passed (and haven't failed)
for (const pageName of PageNavigationValidation.pagesPassed) {
if (!failedPages.has(pageName)) {
passedPages.add(pageName);
@@ -379,7 +438,6 @@ export class PageNavigationValidation implements IValidation {
);
}
- // Show failure details
if (failedPages.size > 0) {
console.log('\n❌ FAILED NAVIGATION TESTS:');
@@ -389,6 +447,9 @@ export class PageNavigationValidation implements IValidation {
if (details) {
console.log(` Expected: ${details.expected}`);
console.log(` Actual: ${details.actual}`);
+ if (details.validationType === 'url') {
+ console.log(` Note: Page slug URL validation failed`);
+ }
}
console.log('');
}
diff --git a/src/test/unit/app/controller/controllerFactory.test.ts b/src/test/unit/app/controller/controllerFactory.test.ts
index fa4021cda..30dc5b11e 100644
--- a/src/test/unit/app/controller/controllerFactory.test.ts
+++ b/src/test/unit/app/controller/controllerFactory.test.ts
@@ -78,7 +78,6 @@ describe('createGetController', () => {
const translations: Record = {
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
};
@@ -115,7 +114,6 @@ describe('createGetController', () => {
backUrl: null,
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
})
@@ -127,7 +125,6 @@ describe('createGetController', () => {
const translations: Record = {
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
};
@@ -163,7 +160,6 @@ describe('createGetController', () => {
backUrl: null,
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
})
@@ -175,7 +171,6 @@ describe('createGetController', () => {
const translations: Record = {
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
};
@@ -208,7 +203,6 @@ describe('createGetController', () => {
backUrl: null,
serviceName: 'Test Service',
phase: 'ALPHA',
- feedback: 'Feedback text',
back: 'Back',
languageToggle: 'Language toggle',
})
diff --git a/src/test/unit/middleware/pageTrackingUrl.test.ts b/src/test/unit/middleware/pageTrackingUrl.test.ts
new file mode 100644
index 000000000..211ecc5ea
--- /dev/null
+++ b/src/test/unit/middleware/pageTrackingUrl.test.ts
@@ -0,0 +1,60 @@
+import type { NextFunction, Request, Response } from 'express';
+
+import { pageTrackingUrlMiddleware } from '../../../main/middleware/pageTrackingUrl';
+
+describe('pageTrackingUrlMiddleware', () => {
+ let req: Partial;
+ let res: Partial;
+ let next: NextFunction;
+
+ beforeEach(() => {
+ res = {
+ locals: {},
+ };
+ next = jest.fn();
+ });
+
+ it('should set dashboard as the tracking URL for dashboard routes', () => {
+ req = {
+ path: '/dashboard/active',
+ };
+
+ pageTrackingUrlMiddleware(req as Request, res as Response, next);
+
+ expect(res.locals?.pageTrackingUrl).toBe('dashboard');
+ expect(next).toHaveBeenCalledTimes(1);
+ });
+
+ it('should strip the case id from case routes', () => {
+ req = {
+ path: '/case/1234567890123456/respond-to-claim/start-now',
+ };
+
+ pageTrackingUrlMiddleware(req as Request, res as Response, next);
+
+ expect(res.locals?.pageTrackingUrl).toBe('respond-to-claim/start-now');
+ expect(next).toHaveBeenCalledTimes(1);
+ });
+
+ it('should leave non-dashboard and non-case routes unchanged', () => {
+ req = {
+ path: '/contact-us',
+ };
+
+ pageTrackingUrlMiddleware(req as Request, res as Response, next);
+
+ expect(res.locals?.pageTrackingUrl).toBe('/contact-us');
+ expect(next).toHaveBeenCalledTimes(1);
+ });
+
+ it('should leave short case routes unchanged', () => {
+ req = {
+ path: '/case/1234567890123456',
+ };
+
+ pageTrackingUrlMiddleware(req as Request, res as Response, next);
+
+ expect(res.locals?.pageTrackingUrl).toBe('/case/1234567890123456');
+ expect(next).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/src/test/unit/modules/error-handler/index.test.ts b/src/test/unit/modules/error-handler/index.test.ts
index dab370f3c..49a8ab74d 100644
--- a/src/test/unit/modules/error-handler/index.test.ts
+++ b/src/test/unit/modules/error-handler/index.test.ts
@@ -33,7 +33,6 @@ describe('error-handler', () => {
'errorPages.500.paragraph': 'Please try again in a few minutes.',
serviceName: 'Possession claims',
phase: 'ALPHA',
- feedback: 'Feedback text',
languageToggle: 'Language toggle',
back: 'Back',
};
@@ -337,7 +336,6 @@ describe('error-handler', () => {
expect(res.locals.serviceName).toBe('Possession claims');
expect(res.locals.phase).toBe('ALPHA');
- expect(res.locals.feedback).toBe('Feedback text');
expect(res.locals.languageToggle).toBe('Language toggle');
expect(res.locals.back).toBe('Back');
});
diff --git a/src/test/unit/modules/i18n/index.test.ts b/src/test/unit/modules/i18n/index.test.ts
index 7b4e90c26..7b6c0fa58 100644
--- a/src/test/unit/modules/i18n/index.test.ts
+++ b/src/test/unit/modules/i18n/index.test.ts
@@ -264,7 +264,6 @@ describe('i18n module', () => {
const translations: Record = {
serviceName: 'Test Service',
phase: 'BETA',
- feedback: 'Feedback',
back: 'Back',
languageToggle: 'Language',
contactUsForHelp: 'Contact',
@@ -277,7 +276,8 @@ describe('i18n module', () => {
expect(result.serviceName).toBe('Test Service');
expect(result.phase).toBe('BETA');
- expect(result.feedback).toBe('Feedback');
+ expect(result.back).toBe('Back');
+ expect(result.languageToggle).toBe('Language');
});
it('should exclude keys that return themselves', () => {