201 lines
7.3 KiB
TypeScript
201 lines
7.3 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import type { RouteLocationNormalized } from 'vue-router'
|
|
|
|
import { createAuthGuard, router } from '@/router'
|
|
import type { useAuthStore } from '@/stores/authStore'
|
|
|
|
type AuthStoreForGuard = ReturnType<typeof useAuthStore>
|
|
|
|
function createRoute(
|
|
path: string,
|
|
meta: Record<string, unknown> = {},
|
|
overrides: Partial<RouteLocationNormalized> = {},
|
|
): RouteLocationNormalized {
|
|
return {
|
|
fullPath: path,
|
|
path,
|
|
name: undefined,
|
|
params: {},
|
|
query: {},
|
|
hash: '',
|
|
matched: [],
|
|
meta,
|
|
redirectedFrom: undefined,
|
|
...overrides,
|
|
} as RouteLocationNormalized
|
|
}
|
|
|
|
function createAuthStoreForGuard(overrides: Partial<AuthStoreForGuard> = {}): AuthStoreForGuard {
|
|
return {
|
|
restoreAttempted: true,
|
|
isAuthenticated: true,
|
|
firstMenuPath: '/reservation/orders',
|
|
hasStoredToken: () => false,
|
|
restoreFromSession: async () => true,
|
|
hasPermission: () => true,
|
|
...overrides,
|
|
} as unknown as AuthStoreForGuard
|
|
}
|
|
|
|
describe('reservation router', () => {
|
|
it('exposes the P0 frontend routes', () => {
|
|
expect(router.resolve('/login').name).toBe('login')
|
|
expect(router.resolve('/reservation/orders').name).toBe('reservation-order-list')
|
|
expect(router.resolve('/reservation/tasks').name).toBe('reservation-task-list')
|
|
expect(router.resolve('/reservation/invoices/new').name).toBe('reservation-manual-invoice')
|
|
expect(router.resolve('/reservation/rooming-lists/new').name).toBe('reservation-rooming-list')
|
|
expect(router.resolve('/reservation/orders/20001').name).toBe('reservation-order-detail')
|
|
expect(router.resolve('/reservation/tasks/10001').name).toBe('reservation-task-detail')
|
|
expect(router.resolve('/reservation/source-messages/30001/conversation').name).toBe(
|
|
'reservation-source-message-conversation',
|
|
)
|
|
})
|
|
|
|
it('exposes the Debug EML route', () => {
|
|
expect(router.resolve('/debug/eml-superagent').name).toBe('debug-eml-superagent')
|
|
})
|
|
|
|
it('exposes the System Admin V1 routes', () => {
|
|
expect(router.resolve('/system/users').name).toBe('system-users')
|
|
expect(router.resolve('/system/roles').name).toBe('system-roles')
|
|
expect(router.resolve('/system/menus').name).toBe('system-menus')
|
|
expect(router.resolve('/system/hotels').name).toBe('system-hotels')
|
|
expect(router.resolve('/system/reservation-catalogs').name).toBe('system-reservation-catalogs')
|
|
expect(router.resolve('/system/audits').name).toBe('system-audits')
|
|
expect(router.resolve('/system/not-ready').name).toBe('not-found')
|
|
})
|
|
|
|
it('declares permissions for protected P0 routes', () => {
|
|
expect(router.resolve('/reservation/orders').meta.permission).toBe('RESERVATION_ORDER_READ')
|
|
expect(router.resolve('/reservation/orders/20001').meta.permission).toBe('RESERVATION_ORDER_READ')
|
|
expect(router.resolve('/reservation/tasks').meta.permission).toBe('RESERVATION_TASK_READ')
|
|
expect(router.resolve('/reservation/tasks/10001').meta.permission).toBe('RESERVATION_TASK_READ')
|
|
expect(router.resolve('/reservation/invoices/new').meta.permission).toBe('RESERVATION_INVOICE_GENERATE')
|
|
expect(router.resolve('/reservation/rooming-lists/new').meta.permission).toBe(
|
|
'RESERVATION_ROOMING_LIST_GENERATE',
|
|
)
|
|
expect(router.resolve('/reservation/source-messages/30001/conversation').meta.permission).toBe(
|
|
'SOURCE_MESSAGE_ORIGINAL_READ',
|
|
)
|
|
expect(router.resolve('/debug/eml-superagent').meta.permission).toBe('SYSTEM_DEBUG_EML_RUN')
|
|
expect(router.resolve('/system/users').meta.permission).toBe('SYSTEM_USER_MANAGE')
|
|
expect(router.resolve('/system/roles').meta.permission).toBe('SYSTEM_ROLE_MANAGE')
|
|
expect(router.resolve('/system/menus').meta.permission).toBe('SYSTEM_MENU_MANAGE')
|
|
expect(router.resolve('/system/hotels').meta.permission).toBe('HOTEL_MANAGE')
|
|
expect(router.resolve('/system/reservation-catalogs').meta.permission).toBe('RESERVATION_CATALOG_MANAGE')
|
|
expect(router.resolve('/system/audits').meta.permission).toBe('SYSTEM_ADMIN_CONSOLE_ACCESS')
|
|
})
|
|
|
|
it('redirects anonymous users to login with the protected target as redirect', async () => {
|
|
const guard = createAuthGuard(() =>
|
|
createAuthStoreForGuard({
|
|
isAuthenticated: false,
|
|
}),
|
|
)
|
|
|
|
await expect(guard(createRoute('/reservation/orders', { permission: 'RESERVATION_ORDER_READ' }))).resolves.toEqual({
|
|
path: '/login',
|
|
query: {
|
|
redirect: '/reservation/orders',
|
|
},
|
|
})
|
|
})
|
|
|
|
it('redirects authenticated users without route permission to the unauthorized page', async () => {
|
|
const guard = createAuthGuard(() =>
|
|
createAuthStoreForGuard({
|
|
hasPermission: () => false,
|
|
}),
|
|
)
|
|
|
|
await expect(guard(createRoute('/debug/eml-superagent', { permission: 'SYSTEM_DEBUG_EML_RUN' }))).resolves.toEqual({
|
|
name: 'unauthorized',
|
|
})
|
|
})
|
|
|
|
it('redirects the root route to the restored first backend menu', async () => {
|
|
let restored = false
|
|
let authenticated = false
|
|
let firstMenuPath: string | null = null
|
|
const authStore = {
|
|
restoreAttempted: false,
|
|
get isAuthenticated() {
|
|
return authenticated
|
|
},
|
|
get firstMenuPath() {
|
|
return firstMenuPath
|
|
},
|
|
hasStoredToken: () => true,
|
|
restoreFromSession: async () => {
|
|
restored = true
|
|
authStore.restoreAttempted = true
|
|
authenticated = true
|
|
firstMenuPath = '/reservation/tasks'
|
|
return true
|
|
},
|
|
hasPermission: () => true,
|
|
} as unknown as AuthStoreForGuard
|
|
const guard = createAuthGuard(() => authStore)
|
|
|
|
await expect(guard(createRoute('/'))).resolves.toBe('/reservation/tasks')
|
|
expect(restored).toBe(true)
|
|
})
|
|
|
|
it('redirects the System Admin entry to the first allowed management page', async () => {
|
|
const guard = createAuthGuard(() =>
|
|
createAuthStoreForGuard({
|
|
hasPermission: (permission: string) =>
|
|
permission === 'SYSTEM_ADMIN_CONSOLE_ACCESS' || permission === 'HOTEL_MANAGE',
|
|
}),
|
|
)
|
|
|
|
await expect(guard(createRoute('/system', { permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS' }))).resolves.toBe(
|
|
'/system/hotels',
|
|
)
|
|
})
|
|
|
|
it('redirects the System Admin entry to catalog management when it is the first allowed admin page', async () => {
|
|
const guard = createAuthGuard(() =>
|
|
createAuthStoreForGuard({
|
|
hasPermission: (permission: string) =>
|
|
permission === 'SYSTEM_ADMIN_CONSOLE_ACCESS' || permission === 'RESERVATION_CATALOG_MANAGE',
|
|
}),
|
|
)
|
|
|
|
await expect(guard(createRoute('/system', { permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS' }))).resolves.toBe(
|
|
'/system/reservation-catalogs',
|
|
)
|
|
})
|
|
|
|
it('redirects the root route to the default page when the backend menu points to root', async () => {
|
|
const guard = createAuthGuard(() =>
|
|
createAuthStoreForGuard({
|
|
firstMenuPath: '/',
|
|
}),
|
|
)
|
|
|
|
await expect(guard(createRoute('/'))).resolves.toBe('/reservation/orders')
|
|
})
|
|
|
|
it('ignores root login redirects after authentication', async () => {
|
|
const guard = createAuthGuard(() => createAuthStoreForGuard())
|
|
|
|
await expect(
|
|
guard(
|
|
createRoute(
|
|
'/login',
|
|
{
|
|
public: true,
|
|
},
|
|
{
|
|
name: 'login',
|
|
query: {
|
|
redirect: '/',
|
|
},
|
|
},
|
|
),
|
|
),
|
|
).resolves.toBe('/reservation/orders')
|
|
})
|
|
})
|