-
- Thank you... fantasy football draft, for letting me know that even
- in my fantasies, I am bad at sports.
-
-
Jimmy Fallon
+
+ {(isSignedIn === null || isSignedIn === true) &&
+
+ }
+ {isSignedIn === false &&
+ <>
+
+
+
+
+ Thank you... fantasy football draft, for letting me know that even
+ in my fantasies, I am bad at sports.
+
+
Jimmy Fallon
+
-
-
-
- Join Gridiron Survivor
-
-
- Log in to your existing account or{' '}
- sign up to get started
- with a league
-
+
+
+
+ Join Gridiron Survivor
+
+
+ Log in to your existing account or{' '}
+ sign up to get started
+ with a league
+
+
+
+
-
-
-
+ >
+ }
);
};
diff --git a/app/(main)/recover-password/page.tsx b/app/(main)/recover-password/page.tsx
index 6eca9c91..81937e63 100644
--- a/app/(main)/recover-password/page.tsx
+++ b/app/(main)/recover-password/page.tsx
@@ -67,7 +67,6 @@ const RecoverPassword = (): React.JSX.Element => {
const email = useWatch({
control: form.control,
name: 'email',
- defaultValue: '',
});
/**
diff --git a/app/(main)/register/Register.tsx b/app/(main)/register/Register.tsx
index 6c8d02b9..9338dc2d 100644
--- a/app/(main)/register/Register.tsx
+++ b/app/(main)/register/Register.tsx
@@ -67,6 +67,11 @@ const Register = (): JSX.Element => {
const form = useForm
({
resolver: zodResolver(RegisterUserSchema),
+ defaultValues: {
+ email: '',
+ password: '',
+ confirmPassword: ''
+ },
});
/**
@@ -76,7 +81,6 @@ const Register = (): JSX.Element => {
const email: string = useWatch({
control: form.control,
name: 'email',
- defaultValue: '',
});
/**
@@ -86,7 +90,6 @@ const Register = (): JSX.Element => {
const password: string = useWatch({
control: form.control,
name: 'password',
- defaultValue: '',
});
/**
@@ -96,7 +99,6 @@ const Register = (): JSX.Element => {
const confirmPassword: string = useWatch({
control: form.control,
name: 'confirmPassword',
- defaultValue: '',
});
/**
diff --git a/components/AdminNav/AdminNav.test.tsx b/components/AdminNav/AdminNav.test.tsx
index b0f3c7ad..c39a39e2 100644
--- a/components/AdminNav/AdminNav.test.tsx
+++ b/components/AdminNav/AdminNav.test.tsx
@@ -1,10 +1,31 @@
import { AdminNav } from './AdminNav';
+import { AuthContextProvider } from '@/context/AuthContextProvider';
import { render, screen } from '@testing-library/react';
import React from 'react';
+const mockPush = jest.fn();
+const mockUsePathname = jest.fn();
+
+jest.mock('next/navigation', () => ({
+ useRouter() {
+ return {
+ push: mockPush,
+ };
+ },
+ usePathname() {
+ return mockUsePathname();
+ },
+}));
+
describe('AdminNav Component', () => {
beforeEach(() => {
- render();
+ jest.clearAllMocks();
+
+ render(
+
+
+ ,
+ );
});
it('should render the navigation links with correct href attributes', () => {
diff --git a/components/AdminUserSettings/AdminUserSettings.test.tsx b/components/AdminUserSettings/AdminUserSettings.test.tsx
index e2048e49..6cf07921 100644
--- a/components/AdminUserSettings/AdminUserSettings.test.tsx
+++ b/components/AdminUserSettings/AdminUserSettings.test.tsx
@@ -1,12 +1,98 @@
import { AdminUserSettings } from './AdminUserSettings';
-import { render, screen } from '@testing-library/react';
+import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import React from 'react';
+const mockPush = jest.fn();
+const mockUsePathname = jest.fn();
+const mockLogoutAccount = jest.fn();
+
+const mockUseAuthContext = {
+ logoutAccount: mockLogoutAccount,
+};
+
+jest.mock('../../context/AuthContextProvider', () => ({
+ useAuthContext() {
+ return {
+ ...mockUseAuthContext,
+ };
+ },
+}));
+
+jest.mock('next/navigation', () => ({
+ useRouter() {
+ return {
+ push: mockPush,
+ };
+ },
+ usePathname() {
+ return mockUsePathname();
+ },
+}));
+
describe('AdminUserSettings Component', () => {
- it('should render the component', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+
render();
+ });
+
+ it('should render the component', async () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');
expect(adminUserSettings).toBeInTheDocument();
});
+
+ it('should show user options when clicked', () => {
+ const adminUserSettings = screen.getByTestId('admin-user-settings');
+
+ fireEvent.click(adminUserSettings);
+
+ waitFor(() => {
+ expect(screen.getByTestId('edit-profile-link')).toBeInTheDocument();
+ expect(screen.getByTestId('sign-out-button')).toBeInTheDocument();
+ });
+ });
+
+ it('should not show user options when closed', () => {
+ const adminUserSettings = screen.getByTestId('admin-user-settings');
+
+ fireEvent.click(adminUserSettings);
+
+ fireEvent.click(adminUserSettings);
+
+ waitFor(() => {
+ expect(screen.getByTestId('edit-profile-link')).not.toBeInTheDocument();
+ expect(screen.getByTestId('sign-out-button')).not.toBeInTheDocument();
+ });
+ });
+
+ it('should direct to /account/settings route when the edit profile button is clicked', () => {
+ const adminUserSettings = screen.getByTestId('admin-user-settings');
+
+ fireEvent.click(adminUserSettings);
+
+ waitFor(() => {
+ const editProfileButton = screen.getByTestId('edit-profile-link');
+ fireEvent.click(editProfileButton);
+ });
+
+ waitFor(() => {
+ expect(mockPush).toHaveBeenCalledWith('/account/settings');
+ });
+ });
+
+ it('should direct to /login route when the sign out button is clicked', () => {
+ const adminUserSettings = screen.getByTestId('admin-user-settings');
+
+ fireEvent.click(adminUserSettings);
+
+ waitFor(() => {
+ const signOutButton = screen.getByTestId('sign-out-button');
+ fireEvent.click(signOutButton);
+ });
+
+ waitFor(() => {
+ expect(mockPush).toHaveBeenCalledWith('/login');
+ });
+ });
});
diff --git a/components/AdminUserSettings/AdminUserSettings.tsx b/components/AdminUserSettings/AdminUserSettings.tsx
index e13e77cb..58bd6302 100644
--- a/components/AdminUserSettings/AdminUserSettings.tsx
+++ b/components/AdminUserSettings/AdminUserSettings.tsx
@@ -1,25 +1,75 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.
+'use client';
+import React, { JSX } from 'react';
+import { Button } from '../Button/Button';
+import { useDataStore } from '@/store/dataStore';
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from '../TableDropDownMenu/TableDropDownMenu';
import { LucideChevronsUpDown } from 'lucide-react';
-import React from 'react';
+import { useAuthContext } from '@/context/AuthContextProvider';
+import { useRouter } from 'next/navigation';
+import LinkCustom from '../LinkCustom/LinkCustom';
/**
- * The admin user settings component.
- * @returns The rendered admin user settings.
+ * Renders admin user settings.
+ * @returns {JSX.Element} The rendered admin user settings component.
*/
-export const AdminUserSettings = (): React.JSX.Element => {
+export const AdminUserSettings = (): JSX.Element => {
+ const router = useRouter();
+ const { logoutAccount } = useAuthContext();
+ const { user } = useDataStore((state) => state);
+
+ /**
+ * Handles the logout.
+ * @returns {Promise} The logout promise.
+ */
+ const handleLogout = async (): Promise => {
+ try {
+ await logoutAccount();
+ router.push('/login');
+ } catch (error) {
+ throw error;
+ }
+ };
+
return (
-
+
+
+
+
+
+
+
+ Edit Profile
+
+
+
+
+
+
+
);
};
diff --git a/components/LeagueEntries/LeagueEntries.interface.ts b/components/LeagueEntries/LeagueEntries.interface.ts
index 46d0b0ad..9bf96dff 100644
--- a/components/LeagueEntries/LeagueEntries.interface.ts
+++ b/components/LeagueEntries/LeagueEntries.interface.ts
@@ -6,6 +6,5 @@ export interface ILeagueEntriesProps {
linkUrl: string;
isEliminated?: boolean;
isPickSet?: boolean;
- userPickHistory: string[];
selectedTeamLogo?: string;
}
diff --git a/components/LeagueEntries/LeagueEntries.test.tsx b/components/LeagueEntries/LeagueEntries.test.tsx
index f8f99581..78c04c25 100644
--- a/components/LeagueEntries/LeagueEntries.test.tsx
+++ b/components/LeagueEntries/LeagueEntries.test.tsx
@@ -5,7 +5,7 @@ import React from 'react';
describe('LeagueEntries', () => {
it(`renders 'default' state without a pick made`, () => {
render(
- ,
+ ,
);
const leagueEntryContainerCard = screen.getByTestId(
@@ -16,13 +16,11 @@ describe('LeagueEntries', () => {
const leagueEntryPickButton = screen.getByTestId(
'league-entry-pick-button',
);
- const userHistoryPicks = screen.queryByTestId('user-pick-history');
expect(entryStatus).toHaveTextContent('alive');
expect(leagueEntryContainerCard).toBeInTheDocument();
expect(leagueEntryNumber).toHaveTextContent('Entry 1');
expect(leagueEntryPickButton).toHaveTextContent('Make Pick');
- expect(userHistoryPicks).not.toBeInTheDocument();
});
it('renders as if the user made a pick', () => {
@@ -31,7 +29,6 @@ describe('LeagueEntries', () => {
entryName="Entry 2"
linkUrl=""
isPickSet={true}
- userPickHistory={['/team-a-logo.png']}
/>,
);
@@ -48,7 +45,6 @@ describe('LeagueEntries', () => {
expect(leagueEntryContainerCard).toBeInTheDocument();
expect(leagueEntryNumber).toHaveTextContent('Entry 2');
expect(leagueEntryPickButton).toHaveTextContent('Change Pick');
- expect(screen.queryByTestId('user-pick-history')).toBeInTheDocument();
});
it('renders as if the user is eliminated', () => {
@@ -58,7 +54,6 @@ describe('LeagueEntries', () => {
isEliminated
isPickSet={false}
linkUrl=""
- userPickHistory={['/team-a-logo.png']}
/>,
);
@@ -73,7 +68,7 @@ describe('LeagueEntries', () => {
expect(leagueEntryNumber).toHaveTextContent('Entry 3');
});
- it('renders teamLogo when user makes a pick and shows user pick history logo', () => {
+ it('renders teamLogo when user makes a pick', () => {
const teamLogoUrl = 'https://example.com/logo.png';
const linkUrl = '/change-pick';
@@ -83,7 +78,6 @@ describe('LeagueEntries', () => {
isPickSet={true}
linkUrl={linkUrl}
selectedTeamLogo={teamLogoUrl}
- userPickHistory={['/team-a-logo.png']}
/>,
);
@@ -108,38 +102,5 @@ describe('LeagueEntries', () => {
'src',
'/_next/image?url=https%3A%2F%2Fexample.com%2Flogo.png&w=96&q=75',
);
- expect(screen.getByTestId('league-history-logo')).toHaveAttribute(
- 'src',
- '/_next/image?url=%2Fteam-a-logo.png&w=96&q=75',
- );
- });
- it('renders no pick when a previous week pick is not available', () => {
- const teamLogoUrl = 'https://example.com/logo.png';
- const linkUrl = '/change-pick';
-
- render(
- ,
- );
-
- const leagueEntryLogo = screen.getByTestId('league-entry-logo');
- const noPick = screen.getByTestId('no-pick');
-
- expect(leagueEntryLogo).toBeInTheDocument();
- expect(leagueEntryLogo).toHaveAttribute(
- 'src',
- '/_next/image?url=https%3A%2F%2Fexample.com%2Flogo.png&w=96&q=75',
- );
- expect(screen.getByTestId('league-history-logo')).toHaveAttribute(
- 'src',
- '/_next/image?url=%2Fteam-a-logo.png&w=96&q=75',
- );
- expect(noPick).toBeInTheDocument();
- expect(noPick).toHaveTextContent('No Pick');
});
});
diff --git a/components/LeagueEntries/LeagueEntries.tsx b/components/LeagueEntries/LeagueEntries.tsx
index 9b98d80e..7811c812 100644
--- a/components/LeagueEntries/LeagueEntries.tsx
+++ b/components/LeagueEntries/LeagueEntries.tsx
@@ -16,7 +16,6 @@ import Image from 'next/image';
* @param props.linkUrl - the url to the user's entry page
* @param props.isEliminated - If true, the user is flagged as eliminat4ed
* @param props.isPickSet - if true, the team logo of the picked team shows up on the LeagueEntries card and the button changes from "make a pick" to "chagne pick"
- * @param props.userPickHistory - the user's pick history for this entry
* @param props.selectedTeamLogo - the team logo
* @returns {React.JSX.Element} - A div element that contains the user's entry information
*/
@@ -25,16 +24,14 @@ const LeagueEntries = ({
linkUrl,
isEliminated = false,
isPickSet = false,
- userPickHistory,
selectedTeamLogo = '',
}: ILeagueEntriesProps): JSX.Element => {
return (
- {userPickHistory.length > 0 && (
-
- {userPickHistory?.map((logoURL, index) => (
-
- WEEK {index + 1}
- {logoURL ? (
-
- ) : (
-
- No Pick
-
- )}
-
- ))}
-
- )}
Promise;
login: (user: UserCredentials) => Promise; // eslint-disable-line no-unused-vars
logoutAccount: () => Promise;
- isSignedIn: boolean;
+ isSignedIn: boolean | null;
};
export const AuthContext = createContext(null);
@@ -39,7 +39,7 @@ export const AuthContextProvider = ({
}: {
children: React.ReactNode;
}): JSX.Element => {
- const [isSignedIn, setIsSignedIn] = useState(false);
+ const [isSignedIn, setIsSignedIn] = useState(null);
const { updateUser, resetUser, user } = useDataStore(
(state) => state,
);
@@ -86,6 +86,7 @@ export const AuthContextProvider = ({
*/
const getUser = async (): Promise => {
if (!isSessionInLocalStorage()) {
+ setIsSignedIn(false);
if (isAuthRequiredPath(pathname)) {
router.push('/login');
}
diff --git a/context/AuthHelper.interface.ts b/context/AuthHelper.interface.ts
index 44791ed4..d62abed6 100644
--- a/context/AuthHelper.interface.ts
+++ b/context/AuthHelper.interface.ts
@@ -7,5 +7,5 @@ import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.share
export interface ILogoutType {
resetUser: React.Dispatch>;
router: AppRouterInstance;
- setIsSignedIn: React.Dispatch>;
+ setIsSignedIn: React.Dispatch>;
}