2026-07-30 17:59:43 +08:00
|
|
|
import { describe, expect, it } from 'vitest'
|
2026-08-03 18:49:18 +08:00
|
|
|
import { adminNavigation, getNavigationLeaves } from '@/core/navigation/adminNavigation'
|
2026-07-30 17:59:43 +08:00
|
|
|
import router from './index'
|
|
|
|
|
|
|
|
|
|
describe('admin router access metadata', () => {
|
2026-08-03 18:49:18 +08:00
|
|
|
it('uses the root route only as a permission-aware entry point while retaining the dashboard prototype', () => {
|
2026-07-30 17:59:43 +08:00
|
|
|
const home = router.getRoutes().find((route) => route.name === 'home')
|
|
|
|
|
|
|
|
|
|
expect(home?.path).toBe('/')
|
|
|
|
|
expect(home?.meta.permission).toBeUndefined()
|
2026-08-03 18:49:18 +08:00
|
|
|
expect(router.getRoutes().some((route) => route.name === 'dashboard')).toBe(true)
|
2026-07-30 17:59:43 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('protects warehouse management with its stable list permission', () => {
|
|
|
|
|
const warehouseRoute = router.getRoutes().find((route) => route.name === 'warehouses')
|
|
|
|
|
|
|
|
|
|
expect(warehouseRoute?.path).toBe('/warehouses')
|
|
|
|
|
expect(warehouseRoute?.meta.permission).toBe('platform:warehouse:list')
|
|
|
|
|
})
|
|
|
|
|
|
2026-08-04 21:01:39 +08:00
|
|
|
it('protects phase-two inbound operations and master data with deployed permissions', () => {
|
|
|
|
|
const expected = [
|
|
|
|
|
['inbound-orders', '/inbounds', 'platform:firstleg:inbound:list'],
|
|
|
|
|
['inbound-order-detail', '/inbounds/:inboundId', 'platform:firstleg:inbound:view'],
|
|
|
|
|
['fba-customer-rules', '/first-leg-pricing/customer-rules', 'firstleg:fba-pricing:rule:view'],
|
|
|
|
|
['fba-carrier-rates', '/first-leg-pricing/carrier-rates', 'firstleg:fba-pricing:rate:view'],
|
|
|
|
|
['locations', '/master-data/locations', 'platform:location:list'],
|
|
|
|
|
['pallets', '/master-data/pallets', 'platform:pallet:list'],
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for (const [name, path, permission] of expected) {
|
|
|
|
|
const route = router.getRoutes().find((item) => item.name === name)
|
|
|
|
|
expect(route?.path).toBe(path)
|
|
|
|
|
expect(route?.meta.permission).toBe(permission)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2026-07-30 17:59:43 +08:00
|
|
|
it('protects express company records with a stable master-data permission', () => {
|
|
|
|
|
const route = router.getRoutes().find((item) => item.name === 'express-companies')
|
|
|
|
|
|
|
|
|
|
expect(route?.path).toBe('/master-data/express-companies')
|
|
|
|
|
expect(route?.meta.permission).toBe('platform:express:list')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('protects counterparty records with a stable master-data permission', () => {
|
|
|
|
|
const route = router.getRoutes().find((item) => item.name === 'counterparties')
|
|
|
|
|
expect(route?.path).toBe('/master-data/counterparties')
|
|
|
|
|
expect(route?.meta.permission).toBe('platform:counterparty:list')
|
|
|
|
|
})
|
|
|
|
|
|
2026-08-03 18:15:41 +08:00
|
|
|
it('protects the download center with its stable list permission', () => {
|
|
|
|
|
const route = router.getRoutes().find((item) => item.name === 'download-center')
|
|
|
|
|
expect(route?.path).toBe('/downloads')
|
|
|
|
|
expect(route?.meta.permission).toBe('platform:download:list')
|
|
|
|
|
})
|
|
|
|
|
|
2026-08-03 20:50:18 +08:00
|
|
|
it('redirects the removed enterprise review route to the protected customer list', () => {
|
2026-07-30 17:59:43 +08:00
|
|
|
const route = router.getRoutes().find((item) => item.name === 'enterprise-reviews')
|
|
|
|
|
|
|
|
|
|
expect(route?.path).toBe('/customers/reviews')
|
2026-08-03 20:50:18 +08:00
|
|
|
expect(route?.redirect).toBe('/customers')
|
|
|
|
|
expect(route?.meta.permission).toBe('platform:customer:list')
|
|
|
|
|
expect(route?.meta.permissionAnyOf).toContain('platform:customer:review')
|
2026-07-30 17:59:43 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('keeps forbidden inside the authenticated layout without a business permission', () => {
|
|
|
|
|
const authenticatedLayout = router.options.routes.find((route) => route.path === '/')
|
|
|
|
|
const forbidden = authenticatedLayout?.children?.find((route) => route.name === 'forbidden')
|
|
|
|
|
const resolved = router.resolve('/403')
|
|
|
|
|
|
|
|
|
|
expect(authenticatedLayout?.meta?.requiresAuth).toBe(true)
|
|
|
|
|
expect(forbidden?.path).toBe('403')
|
|
|
|
|
expect(forbidden?.meta?.permission).toBeUndefined()
|
|
|
|
|
expect(resolved.matched.some((record) => record.meta.requiresAuth)).toBe(true)
|
|
|
|
|
})
|
2026-08-03 18:49:18 +08:00
|
|
|
|
|
|
|
|
it('keeps visible navigation paths and permissions aligned with routes', () => {
|
|
|
|
|
for (const item of getNavigationLeaves(adminNavigation)) {
|
|
|
|
|
const resolved = router.resolve(item.path)
|
|
|
|
|
const pageRoute = resolved.matched.at(-1)
|
|
|
|
|
|
|
|
|
|
expect(pageRoute, `missing route for ${item.path}`).toBeDefined()
|
|
|
|
|
expect(pageRoute?.meta.permission, `permission mismatch for ${item.path}`).toBe(item.permission)
|
|
|
|
|
}
|
|
|
|
|
})
|
2026-07-30 17:59:43 +08:00
|
|
|
})
|