Skip to content

Commit

Permalink
Fix tests and linting
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-elliott-nhsd committed Oct 4, 2024
1 parent 4cfbb23 commit ddc6406
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 83 deletions.
1 change: 1 addition & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SEE: https://github.com/gitleaks/gitleaks/blob/master/README.md#gitleaksignore

cd9c0efec38c5d63053dd865e5d4e207c0760d91:docs/guides/Perform_static_analysis.md:generic-api-key:37
src/__tests__/components/molecules/LoginStatus.test.tsx:jwt:23
9 changes: 9 additions & 0 deletions src/__tests__/app/auth/__snapshots__/page.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`MockAuthPage 1`] = `
<DocumentFragment>
<p>
redirect
</p>
</DocumentFragment>
`;
19 changes: 19 additions & 0 deletions src/__tests__/app/auth/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ReactNode, ComponentType } from 'react';
import MockAuthPage from '@app/auth/page.dev';
import { render } from '@testing-library/react';

jest.mock('@aws-amplify/ui-react', () => ({
Authenticator: {
Provider: ({ children }: { children: ReactNode }) => children,
},
withAuthenticator: (Component: ComponentType) => Component,
}));
jest.mock('@molecules/Redirect/Redirect', () => ({
Redirect: () => <p>redirect</p>,
}));

test('MockAuthPage', () => {
const container = render(<MockAuthPage />);

expect(container.asFragment()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`MockSignoutPage 1`] = `
<DocumentFragment>
<p>
redirect
</p>
</DocumentFragment>
`;
29 changes: 29 additions & 0 deletions src/__tests__/app/auth/signout/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ReactNode, ComponentType } from 'react';
import MockSignoutPage from '@app/auth/signout/page.dev';
import { render, screen } from '@testing-library/react';

jest.mock('@aws-amplify/auth', () => ({
signOut: () => Promise.resolve(),
}));

jest.mock('@molecules/Redirect/Redirect', () => ({
Redirect: () => <p>redirect</p>,
}));

jest.mock('@aws-amplify/ui-react', () => ({
Authenticator: {
Provider: ({ children }: { children: ReactNode }) => children,
},
withAuthenticator: (Component: ComponentType) => Component,
}));
jest.mock('@molecules/Redirect/Redirect', () => ({
Redirect: () => <p>redirect</p>,
}));

test('MockSignoutPage', async () => {
const container = render(<MockSignoutPage />);

await screen.findByText('redirect');

expect(container.asFragment()).toMatchSnapshot();
});
28 changes: 28 additions & 0 deletions src/__tests__/components/molecules/LoginStatus.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable unicorn/no-document-cookie */
import { render } from '@testing-library/react';
import { LoginStatus } from '@molecules/LoginStatus/LoginStatus';

test('LoginStatus - no cookie', () => {
document.cookie = '';

const container = render(<LoginStatus />);

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

test('LoginStatus - invalid cookie', () => {
document.cookie = 'CognitoIdentityServiceProvider.idToken=lemons';

const container = render(<LoginStatus />);

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

test('LoginStatus - valid cookie', () => {
document.cookie =
'CognitoIdentityServiceProvider.idToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImxvY2FsaG9zdEBuaHMubmV0In0.R0rk7pjJoU07efveI4p6W-xrTM-BnP8N-pU-RYczPBA';

const container = render(<LoginStatus />);

expect(container.asFragment()).toMatchSnapshot();
});
40 changes: 40 additions & 0 deletions src/__tests__/components/molecules/Redirect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { mockDeep } from 'jest-mock-extended';
import { render } from '@testing-library/react';
import { Redirect } from '@molecules/Redirect/Redirect';
import {
useSearchParams,
ReadonlyURLSearchParams,
redirect,
} from 'next/navigation';

jest.mock('next/navigation', () => ({
...jest.requireActual('next/navigation'),
redirect: jest.fn(),
useSearchParams: jest.fn(),
}));

test('Redirect - URL provided', () => {
const mockRedirect = jest.fn(mockDeep<typeof redirect>());
jest.mocked(redirect).mockImplementation(mockRedirect);

const mockSearchParams = new ReadonlyURLSearchParams({
redirect: 'redirect',
});
jest.mocked(useSearchParams).mockReturnValue(mockSearchParams);

render(<Redirect />);

expect(mockRedirect).toHaveBeenCalledWith('redirect');
});

test('Redirect - URL not provided', () => {
const mockRedirect = jest.fn(mockDeep<typeof redirect>());
jest.mocked(redirect).mockImplementation(mockRedirect);

const mockSearchParams = new ReadonlyURLSearchParams({});
jest.mocked(useSearchParams).mockReturnValue(mockSearchParams);

render(<Redirect />);

expect(mockRedirect).toHaveBeenCalledWith('/');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`LoginStatus - invalid cookie 1`] = `
<DocumentFragment>
<li
class="nhsuk-header__navigation-item"
>
<a
class="nhsuk-header__navigation-link"
href="/auth~featuredomain-testing?redirect=%2Ftemplatesnull"
>
Sign in
</a>
</li>
</DocumentFragment>
`;

exports[`LoginStatus - no cookie 1`] = `
<DocumentFragment>
<li
class="nhsuk-header__navigation-item"
>
<a
class="nhsuk-header__navigation-link"
href="/auth~featuredomain-testing?redirect=%2Ftemplatesnull"
>
Sign in
</a>
</li>
</DocumentFragment>
`;

exports[`LoginStatus - valid cookie 1`] = `
<DocumentFragment>
<div
class="nhsuk-header__transactional-service-name"
>
<a
class="nhsuk-header__transactional-service-name--link"
>
[email protected]
</a>
</div>
<li
class="nhsuk-header__navigation-item"
>
<a
class="nhsuk-header__navigation-link"
href="/auth~featuredomain-testing/signout?redirect=%2Ftemplatesnull"
>
Sign out
</a>
</li>
</DocumentFragment>
`;
40 changes: 7 additions & 33 deletions src/app/auth/page.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,24 @@
'use client';

import { Amplify } from 'aws-amplify';
import { Suspense, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
import { Suspense } from 'react';
import { Authenticator, withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import { Redirect } from '@molecules/Redirect/Redirect';

Amplify.configure(require('@/amplify_outputs.json'), { ssr: true });

const Redirect = () => {
const searchParams = useSearchParams();

const redirect = searchParams.get('redirect') ?? '/';

useEffect(() => {
location.href = redirect;
}, [redirect]);

if (redirect) {
return (
<h3>
Redirecting to{' '}
<code>
<a href={redirect}>{redirect}</a>
</code>
</h3>
);
}
};

const WrappedRedirect = () => (
<Suspense>
<Redirect />
</Suspense>
);

const MockAuthPage = () => {
return withAuthenticator(WrappedRedirect, {
const MockAuthPage = () =>
withAuthenticator(Redirect, {
variation: 'default',
hideSignUp: true,
})({});
};

const WrappedAuthPage = () => (
<Authenticator.Provider>
<MockAuthPage />
<Suspense>
<MockAuthPage />
</Suspense>
</Authenticator.Provider>
);

Expand Down
42 changes: 8 additions & 34 deletions src/app/auth/signout/page.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,13 @@

import { Amplify } from 'aws-amplify';
import { Suspense, useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
import { signOut } from '@aws-amplify/auth';
import { Authenticator } from '@aws-amplify/ui-react';
import { Redirect } from '@molecules/Redirect/Redirect';

Amplify.configure(require('@/amplify_outputs.json'), { ssr: true });

const Redirect = () => {
const searchParams = useSearchParams();

const redirect = searchParams.get('redirect') ?? '/';

useEffect(() => {
location.href = redirect;
}, [redirect]);

if (redirect) {
return (
<h3>
Redirecting to{' '}
<code>
<a href={redirect}>{redirect}</a>
</code>
</h3>
);
}
};

const MockAuthPage = () => {
const MockSignoutPage = () => {
const [signedOut, setSignedOut] = useState(false);

useEffect(() => {
Expand All @@ -42,20 +21,15 @@ const MockAuthPage = () => {
}
});

if (signedOut) {
return (
<Suspense>
<Redirect />
</Suspense>
);
}
return <p>Signing out</p>;
return signedOut ? <Redirect /> : <p>Signing out</p>;
};

const WrappedAuthPage = () => (
const WrappedSignoutPage = () => (
<Authenticator.Provider>
<MockAuthPage />
<Suspense>
<MockSignoutPage />
</Suspense>
</Authenticator.Provider>
);

export default WrappedAuthPage;
export default WrappedSignoutPage;
2 changes: 1 addition & 1 deletion src/components/molecules/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Link from 'next/link';
import concatClassNames from '@utils/concat-class-names';
import content from '@content/content';
import LoginStatus from '@molecules/LoginStatus/LoginStatus';
import { LoginStatus } from '@molecules/LoginStatus/LoginStatus';
import styles from './Header.module.scss';
import { HeaderType } from './header.types';

Expand Down
26 changes: 11 additions & 15 deletions src/components/molecules/LoginStatus/LoginStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import cookie from 'cookie';
import { getAuthBasePath, getBasePath } from '@utils/get-base-path';
import { usePathname } from 'next/navigation';

const getLoggedInUser = (cookieString: string) => {
const cookies = cookie.parse(cookieString);

if (!cookies) {
return;
const decodeCookie = (cookieValue: string) => {
try {
return jwtDecode<JwtPayload & { email: string }>(cookieValue);
} catch (error) {
console.error(error);
}
};

const getLoggedInUser = (cookieString: string) => {
const cookies = cookie.parse(cookieString);
const idTokenCookieName = Object.keys(cookies).find(
(cookieName) =>
cookieName.includes('CognitoIdentityServiceProvider') &&
Expand All @@ -27,14 +30,7 @@ const getLoggedInUser = (cookieString: string) => {
}

const idTokenCookieValue = cookies[idTokenCookieName];

if (!idTokenCookieValue) {
return;
}

const idTokenCookieDecoded = jwtDecode<JwtPayload & { email: string }>(
idTokenCookieValue
);
const idTokenCookieDecoded = decodeCookie(idTokenCookieValue);

if (!idTokenCookieDecoded) {
return;
Expand All @@ -43,7 +39,7 @@ const getLoggedInUser = (cookieString: string) => {
return idTokenCookieDecoded.email;
};

export default function LoginStatus() {
export const LoginStatus = () => {
const [browserCookie, setBrowserCookie] = useState<string>('');
const pathname = usePathname();

Expand Down Expand Up @@ -76,4 +72,4 @@ export default function LoginStatus() {
Sign in
</Header.NavItem>
);
}
};
12 changes: 12 additions & 0 deletions src/components/molecules/Redirect/Redirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import { getBasePath } from '@utils/get-base-path';
import { useSearchParams, redirect } from 'next/navigation';

export const Redirect = () => {
const searchParams = useSearchParams();

const redirectPath = searchParams.get('redirect') ?? '/';

redirect(redirectPath.replace(getBasePath(), ''));
};

0 comments on commit ddc6406

Please sign in to comment.