131 lines
4.2 KiB
TypeScript
131 lines
4.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { resolveDashboardRoutePolicy, roleCanAccessPolicy } from '@/lib/dashboardRoutePolicies'
|
|
import { buildSignInRedirect, flattenInternalRoutes, getBaselineInternalRoutes, isAllowedRoute, resolveAccessRedirect, resolveAllowedRoutes } from './DashboardAccessGuard'
|
|
|
|
describe('DashboardAccessGuard route helpers', () => {
|
|
it('normalizes dashboard-prefixed menu routes before checking access', () => {
|
|
const routes = flattenInternalRoutes([
|
|
{
|
|
id: 'dashboard',
|
|
itemType: 'INTERNAL_PAGE',
|
|
routeOrUrl: '/dashboard',
|
|
children: [],
|
|
},
|
|
{
|
|
id: 'fleet',
|
|
itemType: 'INTERNAL_PAGE',
|
|
routeOrUrl: '/dashboard/fleet',
|
|
children: [],
|
|
},
|
|
{
|
|
id: 'external',
|
|
itemType: 'EXTERNAL_LINK',
|
|
routeOrUrl: '/dashboard/dashboard',
|
|
children: [],
|
|
},
|
|
])
|
|
|
|
expect(routes).toEqual(['/', '/fleet'])
|
|
expect(isAllowedRoute('/', routes)).toBe(true)
|
|
expect(isAllowedRoute('/fleet/123', routes)).toBe(true)
|
|
})
|
|
|
|
it('does not redirect forever when an authenticated employee has no visible menu routes', () => {
|
|
expect(resolveAccessRedirect('/', [])).toBeNull()
|
|
expect(resolveAccessRedirect('/fleet', [])).toBeNull()
|
|
})
|
|
|
|
it('uses the approved baseline routes when active subscription menu data is empty or root-only', () => {
|
|
expect(resolveAllowedRoutes({ items: [], subscriptionAccessLevel: 'full' }, 'OWNER')).toEqual([
|
|
'/',
|
|
'/reservations',
|
|
'/fleet',
|
|
'/customers',
|
|
'/reports',
|
|
'/billing',
|
|
'/settings',
|
|
])
|
|
|
|
expect(resolveAllowedRoutes({
|
|
subscriptionAccessLevel: 'full',
|
|
items: [
|
|
{
|
|
id: 'dashboard',
|
|
itemType: 'INTERNAL_PAGE',
|
|
routeOrUrl: '/',
|
|
children: [],
|
|
},
|
|
],
|
|
}, 'MANAGER')).toEqual([
|
|
'/',
|
|
'/reservations',
|
|
'/fleet',
|
|
'/customers',
|
|
'/reports',
|
|
'/billing',
|
|
])
|
|
})
|
|
|
|
it('uses baseline routes when the production menu only contains dashboard and billing recovery links', () => {
|
|
expect(resolveAllowedRoutes({
|
|
subscriptionAccessLevel: 'full',
|
|
items: [
|
|
{
|
|
id: 'dashboard',
|
|
itemType: 'INTERNAL_PAGE',
|
|
routeOrUrl: '/',
|
|
children: [],
|
|
},
|
|
{
|
|
id: 'subscription',
|
|
itemType: 'INTERNAL_PAGE',
|
|
routeOrUrl: '/subscription',
|
|
children: [],
|
|
},
|
|
],
|
|
}, 'OWNER')).toEqual([
|
|
'/',
|
|
'/reservations',
|
|
'/fleet',
|
|
'/customers',
|
|
'/reports',
|
|
'/billing',
|
|
'/settings',
|
|
])
|
|
})
|
|
|
|
it('does not apply baseline fallback when subscription access is none', () => {
|
|
expect(resolveAllowedRoutes({ items: [], subscriptionAccessLevel: 'none' }, 'OWNER')).toEqual([])
|
|
})
|
|
|
|
it('filters baseline routes by role', () => {
|
|
expect(getBaselineInternalRoutes('AGENT')).toEqual(['/', '/reservations', '/fleet', '/customers'])
|
|
expect(getBaselineInternalRoutes('MANAGER')).toEqual(['/', '/reservations', '/fleet', '/customers', '/reports', '/billing'])
|
|
})
|
|
|
|
it('redirects disallowed routes to the first visible internal route', () => {
|
|
expect(resolveAccessRedirect('/settings', ['/', '/fleet'])).toBe('/')
|
|
expect(resolveAccessRedirect('/fleet/123', ['/', '/fleet'])).toBeNull()
|
|
})
|
|
|
|
it('builds sign-in redirects with public dashboard return paths', () => {
|
|
expect(buildSignInRedirect('/reservations')).toBe('/dashboard/sign-in?redirect=%2Fdashboard%2Freservations')
|
|
expect(buildSignInRedirect('/dashboard/fleet')).toBe('/dashboard/sign-in?redirect=%2Fdashboard%2Ffleet')
|
|
})
|
|
|
|
it('treats subscription as an owner-only recovery route independent of menu registration', () => {
|
|
const policy = resolveDashboardRoutePolicy('/subscription')
|
|
|
|
expect(policy).toMatchObject({
|
|
authenticationRequired: true,
|
|
allowedRoles: ['OWNER'],
|
|
subscriptionRequired: false,
|
|
menuRegistrationRequired: false,
|
|
billingRecoveryRoute: true,
|
|
})
|
|
expect(roleCanAccessPolicy('OWNER', policy)).toBe(true)
|
|
expect(roleCanAccessPolicy('MANAGER', policy)).toBe(false)
|
|
expect(roleCanAccessPolicy('AGENT', policy)).toBe(false)
|
|
})
|
|
})
|