feat(ST-nma6ylbl): requireAdmin() guard + /admin layout-shell + tests

- lib/auth-guard.ts: requireAdmin() toegevoegd — redirect /dashboard bij !userId of !isAdmin
- app/(app)/admin/layout.tsx: admin-sidebar met links naar /admin/users, /admin/jobs, /admin/products
- app/(app)/admin/page.tsx: redirect-stub naar /admin/users
- __tests__/lib/auth-guard.test.ts: 3 tests voor requireAdmin() (geen userId, isAdmin=false, isAdmin=true)
This commit is contained in:
Scrum4Me Agent 2026-05-05 14:26:03 +02:00
parent 8af5354f22
commit c0ded1f482
4 changed files with 64 additions and 0 deletions

View file

@ -8,6 +8,41 @@ vi.mock('@/lib/auth', () => ({ getSession: getSessionMock }))
vi.mock('@/lib/auth/pairing', () => ({ isPairedSessionExpired: isPairedSessionExpiredMock }))
vi.mock('next/navigation', () => ({ redirect: redirectMock }))
describe('requireAdmin', () => {
beforeEach(() => {
getSessionMock.mockReset()
isPairedSessionExpiredMock.mockReset()
redirectMock.mockClear()
})
afterEach(() => {
vi.resetModules()
})
it('redirect /dashboard als userId ontbreekt', async () => {
getSessionMock.mockResolvedValue({ userId: undefined, isAdmin: false })
const { requireAdmin } = await import('@/lib/auth-guard')
await expect(requireAdmin()).rejects.toThrow('REDIRECT_CALLED')
expect(redirectMock).toHaveBeenCalledWith('/dashboard')
})
it('redirect /dashboard als isAdmin false is', async () => {
getSessionMock.mockResolvedValue({ userId: 'u1', isAdmin: false })
const { requireAdmin } = await import('@/lib/auth-guard')
await expect(requireAdmin()).rejects.toThrow('REDIRECT_CALLED')
expect(redirectMock).toHaveBeenCalledWith('/dashboard')
})
it('geeft sessie terug als isAdmin true is', async () => {
const sess = { userId: 'u1', isAdmin: true }
getSessionMock.mockResolvedValue(sess)
const { requireAdmin } = await import('@/lib/auth-guard')
const result = await requireAdmin()
expect(result).toBe(sess)
expect(redirectMock).not.toHaveBeenCalled()
})
})
describe('requireSession', () => {
beforeEach(() => {
getSessionMock.mockReset()