-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feat: - added a menu for the user settings in the /admin route that includes edit profile and sign out buttons - the sign out button logs a user out and redirects to /login page - the edit profile button directs user to /admin/edit-profile page --------- Co-authored-by: Ryan Furrer <[email protected]> Co-authored-by: Chris Nowicki <[email protected]> Co-authored-by: Mai Vang <[email protected]> Co-authored-by: Alex Appleget <[email protected]> Co-authored-by: Jennifer Tieu <[email protected]> Co-authored-by: Shashi Lo <[email protected]> Co-authored-by: Cody Epstein <[email protected]> Co-authored-by: Danielle Lindblom <[email protected]>
- Loading branch information
1 parent
491d856
commit f92114f
Showing
3 changed files
with
175 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(<AdminUserSettings />); | ||
}); | ||
|
||
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'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<void>} The logout promise. | ||
*/ | ||
const handleLogout = async (): Promise<void> => { | ||
try { | ||
await logoutAccount(); | ||
router.push('/login'); | ||
} catch (error) { | ||
throw error; | ||
} | ||
}; | ||
|
||
return ( | ||
<div | ||
className="admin-user-settings flex gap-2 px-2 py-2 items-center outline outline-border rounded text-foreground" | ||
data-testid="admin-user-settings" | ||
> | ||
<span className="bg-cyan-500 w-8 h-8 rounded-full" /> | ||
<p>Users Name</p> | ||
<LucideChevronsUpDown | ||
className="ml-auto text-muted-foreground" | ||
size={16} | ||
/> | ||
</div> | ||
<DropdownMenu> | ||
<DropdownMenuTrigger | ||
className="w-56 focus:outline-none mx-auto" | ||
data-testid="admin-user-settings" | ||
> | ||
<div className="admin-user-settings w-full flex space-between gap-2 px-2 py-2 items-center border border-border rounded-lg text-foreground overflow-hidden"> | ||
<span className="bg-cyan-500 w-8 h-8 rounded-full" /> | ||
<p className="truncate ... w-36 ">{user.email}</p> | ||
<LucideChevronsUpDown className="text-muted-foreground" size={16} /> | ||
</div> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent className="border border-border rounded-lg p-0 w-56 "> | ||
<DropdownMenuItem className="cursor-pointer rounded-b-none flex focus:bg-muted"> | ||
<LinkCustom | ||
className="text-base no-underline hover:text-foreground w-full py-2 px-0 text-muted-foreground hover:underline" | ||
href="/account/settings" | ||
data-testid="edit-profile-link" | ||
> | ||
Edit Profile | ||
</LinkCustom> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem className="cursor-pointer rounded-none focus:bg-muted"> | ||
<Button | ||
className="w-full text-base no-underline py-2 px-0 h-auto text-muted-foreground hover:text-foreground font-normal justify-normal hover:underline" | ||
variant="link" | ||
label="Sign Out" | ||
onClick={handleLogout} | ||
data-testid="sign-out-button" | ||
/> | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
); | ||
}; |