From 814b2f0c07165e2059e9e6641d4a3ecc870fda90 Mon Sep 17 00:00:00 2001 From: Afonso Jorge Ramos Date: Fri, 14 Jun 2024 18:59:10 +0100 Subject: [PATCH] refactor: create `Header` component --- src/components/Header.test.tsx | 26 ++++ src/components/Header.tsx | 29 ++++ .../__snapshots__/Header.test.tsx.snap | 124 ++++++++++++++++++ src/routes/Accounts.tsx | 24 +--- src/routes/LoginWithOAuthApp.tsx | 34 +---- src/routes/LoginWithPersonalAccessToken.tsx | 31 +---- src/routes/Settings.tsx | 20 +-- .../__snapshots__/Accounts.test.tsx.snap | 2 +- .../LoginWithOAuthApp.test.tsx.snap | 4 +- ...LoginWithPersonalAccessToken.test.tsx.snap | 4 +- .../__snapshots__/Settings.test.tsx.snap | 2 +- 11 files changed, 202 insertions(+), 98 deletions(-) create mode 100644 src/components/Header.test.tsx create mode 100644 src/components/Header.tsx create mode 100644 src/components/__snapshots__/Header.test.tsx.snap diff --git a/src/components/Header.test.tsx b/src/components/Header.test.tsx new file mode 100644 index 000000000..aec69a950 --- /dev/null +++ b/src/components/Header.test.tsx @@ -0,0 +1,26 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import { Header } from './Header'; + +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); + +describe('components/Header.tsx', () => { + it('should render itself & its children', () => { + const tree = render(
Test Header
); + + expect(tree).toMatchSnapshot(); + }); + + it('should navigate back', () => { + render(
Test Header
); + + fireEvent.click(screen.getByLabelText('Go Back')); + expect(mockNavigate).toHaveBeenNthCalledWith(1, -1); + + expect(mockNavigate).toHaveBeenCalledTimes(1); + expect(mockNavigate).toHaveBeenCalledWith(-1); + }); +}); diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 000000000..24a9333ed --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,29 @@ +import { ArrowLeftIcon } from '@primer/octicons-react'; +import type { ReactNode } from 'react'; +import { useNavigate } from 'react-router-dom'; + +interface IHeader { + children: ReactNode; +} + +export const Header = ({ children }: IHeader) => { + const navigate = useNavigate(); + return ( +
+ + +

{children}

+
+ ); +}; diff --git a/src/components/__snapshots__/Header.test.tsx.snap b/src/components/__snapshots__/Header.test.tsx.snap new file mode 100644 index 000000000..c7a82e24c --- /dev/null +++ b/src/components/__snapshots__/Header.test.tsx.snap @@ -0,0 +1,124 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`components/Header.tsx should render itself & its children 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ +

+ Test Header +

+
+
+ , + "container":
+
+ +

+ Test Header +

+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/src/routes/Accounts.tsx b/src/routes/Accounts.tsx index ede6e594d..1d7572e2f 100644 --- a/src/routes/Accounts.tsx +++ b/src/routes/Accounts.tsx @@ -1,5 +1,4 @@ import { - ArrowLeftIcon, KeyIcon, PersonIcon, PlusIcon, @@ -8,11 +7,10 @@ import { import { type FC, useCallback, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; - -import { AppContext } from '../context/App'; - +import { Header } from '../components/Header'; import { AuthMethodIcon } from '../components/icons/AuthMethodIcon'; import { PlatformIcon } from '../components/icons/PlatformIcon'; +import { AppContext } from '../context/App'; import { BUTTON_CLASS_NAME } from '../styles/gitify'; import type { Account } from '../types'; import { getAccountUUID } from '../utils/auth/utils'; @@ -47,23 +45,7 @@ export const AccountsRoute: FC = () => { return (
-
- - -

Accounts

-
- +
Accounts
{auth.accounts.map((account) => ( diff --git a/src/routes/LoginWithOAuthApp.tsx b/src/routes/LoginWithOAuthApp.tsx index fa9083122..25e0c64bc 100644 --- a/src/routes/LoginWithOAuthApp.tsx +++ b/src/routes/LoginWithOAuthApp.tsx @@ -1,12 +1,7 @@ -import { - ArrowLeftIcon, - BookIcon, - PersonIcon, - SignInIcon, -} from '@primer/octicons-react'; +import { BookIcon, PersonIcon, SignInIcon } from '@primer/octicons-react'; import { type FC, useCallback, useContext } from 'react'; import { Form, type FormRenderProps } from 'react-final-form'; -import { useNavigate } from 'react-router-dom'; +import { Header } from '../components/Header'; import { Button } from '../components/fields/Button'; import { FieldInput } from '../components/fields/FieldInput'; import { AppContext } from '../context/App'; @@ -58,7 +53,6 @@ export const validate = (values: IValues): IFormErrors => { export const LoginWithOAuthApp: FC = () => { const { loginWithOAuthApp } = useContext(AppContext); - const navigate = useNavigate(); const renderForm = (formProps: FormRenderProps) => { const { handleSubmit, submitting, pristine, values } = formProps; @@ -130,26 +124,10 @@ export const LoginWithOAuthApp: FC = () => { return (
-
- - -

- - Login with OAuth App -

-
- +
+ + Login with OAuth App +
{ return (
-
- - -

- - Login with Personal Access Token -

-
+
+ + Login with Personal Access Token +
{ return (
-
- - -

Settings

-
- +
Settings
diff --git a/src/routes/__snapshots__/Accounts.test.tsx.snap b/src/routes/__snapshots__/Accounts.test.tsx.snap index ed3bb523c..7a793f238 100644 --- a/src/routes/__snapshots__/Accounts.test.tsx.snap +++ b/src/routes/__snapshots__/Accounts.test.tsx.snap @@ -6,7 +6,7 @@ exports[`routes/Accounts.tsx General should render itself & its children 1`] = ` data-testid="accounts" >