Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions frontend/src/__tests__/helpers/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { mockDeep } from 'jest-mock-extended';
import {
ContactDetailDto,
LetterVariant,
ProofRequest,
RoutingConfig,
Expand Down Expand Up @@ -225,3 +226,25 @@ export const makeSmsProofRequest = (
contactDetailValue: '07123456789',
...overrides,
});

export const makeEmailContactDetail = (
overrides: Partial<ContactDetailDto> = {}
): ContactDetailDto => ({
id: 'contact-123',
rawValue: ' TEST@example.com ',
value: 'test@example.com',
type: 'EMAIL',
status: 'VERIFIED',
...overrides,
});

export const makeSmsContactDetail = (
overrides: Partial<ContactDetailDto> = {}
): ContactDetailDto => ({
id: 'contact-456',
rawValue: ' 0712 345 6789 ',
value: '+447123456789',
type: 'SMS',
status: 'VERIFIED',
...overrides,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders page correctly should match snapshot with templateId 1`] = `
<DocumentFragment>
<div
class="nhsuk-width-container"
>
<main
class="nhsuk-main-wrapper"
id="maincontent"
role="main"
>
<div
class="nhsuk-grid-row"
>
<div
class="nhsuk-grid-column-two-thirds"
>
<div
class="nhsuk-panel"
>
<h1
class="nhsuk-panel__title"
data-testid="banner-heading"
>
Email address confirmed
</h1>
<div
class="nhsuk-panel__body"
>
<p>
You can now send test emails to
<strong>
TEST@example.com
</strong>
</p>
<p>
This email address will only be available for you to use. If someone else needs to send test emails to it, they must add it to their own account.
</p>
</div>
</div>
<a
class="nhsuk-link"
data-testid="back-link-bottom"
href="/send-test-email/template-456"
>
Continue to send a test email
</a>
</div>
</div>
</main>
</div>
</DocumentFragment>
`;

exports[`renders page correctly should match snapshot without templateId 1`] = `
<DocumentFragment>
<div
class="nhsuk-width-container"
>
<main
class="nhsuk-main-wrapper"
id="maincontent"
role="main"
>
<div
class="nhsuk-grid-row"
>
<div
class="nhsuk-grid-column-two-thirds"
>
<div
class="nhsuk-panel"
>
<h1
class="nhsuk-panel__title"
data-testid="banner-heading"
>
Email address confirmed
</h1>
<div
class="nhsuk-panel__body"
>
<p>
You can now send test emails to
<strong>
TEST@example.com
</strong>
</p>
<p>
This email address will only be available for you to use. If someone else needs to send test emails to it, they must add it to their own account.
</p>
</div>
</div>
<a
class="nhsuk-link"
data-testid="back-link-bottom"
href="/message-templates"
>
Back to all templates
</a>
</div>
</div>
</main>
</div>
</DocumentFragment>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { render } from '@testing-library/react';
import { redirect } from 'next/navigation';
import { serverIsFeatureEnabled } from '@utils/server-features';
import Page, {
generateMetadata,
} from '@app/email-address-confirmed/[contactDetailId]/page';
import { getContactDetailById } from '@utils/contact-details';
import content from '@content/content';
import {
makeEmailContactDetail,
makeSmsContactDetail,
} from '@testhelpers/helpers';

const { pageTitle, bannerHeading, sendLink, templatesLink } =
content.pages.emailAddressConfirmedPage;

jest.mock('next/navigation');
jest.mock('@utils/contact-details');
jest.mock('@utils/server-features');

const EMAIL_CONTACT_DETAIL = makeEmailContactDetail();

beforeEach(() => {
jest.resetAllMocks();
jest.mocked(serverIsFeatureEnabled).mockResolvedValue(true);
jest.mocked(getContactDetailById).mockResolvedValue(EMAIL_CONTACT_DETAIL);
});

it('should generate correct metadata', async () => {
const metadata = await generateMetadata();

expect(metadata).toEqual({ title: pageTitle });
});

describe('renders page correctly', () => {
it('should render banner heading', async () => {
const { getByTestId } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
})
);

expect(getByTestId('banner-heading')).toHaveTextContent(bannerHeading);
});

it('should render email address from contact detail', async () => {
const { getByText } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
})
);

expect(getByText('TEST@example.com')).toBeInTheDocument();
});

it('should render back link to send-test-email when templateId is provided', async () => {
const templateId = 'template-456';
const { getByTestId } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({ templateId }),
})
);

expect(getByTestId('back-link-bottom')).toHaveAttribute(
'href',
`/send-test-email/${templateId}`
);
expect(getByTestId('back-link-bottom')).toHaveTextContent(sendLink.text);
});

it('should render back link to message-templates when no templateId', async () => {
const { getByTestId } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
})
);

expect(getByTestId('back-link-bottom')).toHaveAttribute(
'href',
templatesLink.href
);
expect(getByTestId('back-link-bottom')).toHaveTextContent(
templatesLink.text
);
});

it('should match snapshot without templateId', async () => {
const { asFragment } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
})
);

expect(asFragment()).toMatchSnapshot();
});

it('should match snapshot with templateId', async () => {
const { asFragment } = render(
await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({ templateId: 'template-456' }),
})
);

expect(asFragment()).toMatchSnapshot();
});
});

describe('redirects', () => {
it('should redirect to message-templates when digitalProofingEmail is disabled', async () => {
jest.mocked(serverIsFeatureEnabled).mockResolvedValueOnce(false);

await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
});

expect(redirect).toHaveBeenCalledWith('/message-templates', 'replace');
expect(getContactDetailById).not.toHaveBeenCalled();
});

it('should redirect to message-templates when contact detail is not found', async () => {
jest.mocked(getContactDetailById).mockResolvedValueOnce(undefined);

await Page({
params: Promise.resolve({ contactDetailId: 'not-found' }),
searchParams: Promise.resolve({}),
});

expect(redirect).toHaveBeenCalledWith('/message-templates', 'replace');
});

it('should redirect to message-templates when contact detail is not verified', async () => {
jest
.mocked(getContactDetailById)
.mockResolvedValueOnce(
makeEmailContactDetail({ status: 'PENDING_VERIFICATION' })
);

await Page({
params: Promise.resolve({ contactDetailId: 'not-found' }),
searchParams: Promise.resolve({}),
});

expect(redirect).toHaveBeenCalledWith('/message-templates', 'replace');
});

it('should redirect to message-templates when contact detail type is not EMAIL', async () => {
jest
.mocked(getContactDetailById)
.mockResolvedValueOnce(makeSmsContactDetail());

await Page({
params: Promise.resolve({ contactDetailId: 'contact-123' }),
searchParams: Promise.resolve({}),
});

expect(redirect).toHaveBeenCalledWith('/message-templates', 'replace');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use server';

import { NHSNotifyMain } from '@atoms/NHSNotifyMain/NHSNotifyMain';
import content from '@content/content';
import { NHSNotifyContainer } from '@layouts/container/container';
import { ContentRenderer } from '@molecules/ContentRenderer/ContentRenderer';
import { getContactDetailById } from '@utils/contact-details';
import { interpolate } from '@utils/interpolate';
import { $ContactDetailsSearchParams } from '@utils/schemas';
import { serverIsFeatureEnabled } from '@utils/server-features';
import { Metadata } from 'next';
import Link from 'next/link';
import { redirect, RedirectType } from 'next/navigation';
import type { ContactDetailPageProps } from 'nhs-notify-web-template-management-utils';

const { pageTitle, bannerHeading, bannerBody, sendLink, templatesLink } =
content.pages.emailAddressConfirmedPage;

export async function generateMetadata(): Promise<Metadata> {
return {
title: pageTitle,
};
}

const EmailAddressConfirmedPage = async ({
params,
searchParams,
}: ContactDetailPageProps) => {
const isDigitalProofingEmailEnabled = await serverIsFeatureEnabled(
'digitalProofingEmail'
);

if (!isDigitalProofingEmailEnabled) {
return redirect(`/message-templates`, RedirectType.replace);
}

const { contactDetailId } = await params;
const { templateId } = $ContactDetailsSearchParams.parse(await searchParams);

const contactDetail = await getContactDetailById(contactDetailId);

if (
!contactDetail ||
contactDetail.status !== 'VERIFIED' ||
contactDetail.type !== 'EMAIL'
) {
return redirect('/message-templates', RedirectType.replace);
}

const backLink = templateId ? sendLink : templatesLink;

return (
<NHSNotifyContainer>
<NHSNotifyMain>
<div className='nhsuk-grid-row'>
<div className='nhsuk-grid-column-two-thirds'>
<div className='nhsuk-panel'>
<h1 className='nhsuk-panel__title' data-testid='banner-heading'>
{bannerHeading}
</h1>
<div className='nhsuk-panel__body'>
<ContentRenderer
content={bannerBody}
variables={{
contactDetail: contactDetail.rawValue.trim(),
}}
/>
</div>
</div>
{
<Link
href={
templateId
? interpolate(backLink.href, { templateId })
: backLink.href
}
data-testid='back-link-bottom'
className='nhsuk-link'
>
{backLink.text}
</Link>
}
</div>
</div>
</NHSNotifyMain>
</NHSNotifyContainer>
);
};

export default EmailAddressConfirmedPage;
Loading
Loading