优化
This commit is contained in:
@@ -5,15 +5,10 @@ import { fileURLToPath } from 'node:url'
|
||||
import { join } from 'node:path'
|
||||
import test from 'node:test'
|
||||
import {
|
||||
Building2,
|
||||
CircleUserRound,
|
||||
ClipboardList,
|
||||
KeyRound,
|
||||
LayoutGrid,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Truck,
|
||||
Users,
|
||||
} from '@lucide/vue'
|
||||
|
||||
import {
|
||||
@@ -32,7 +27,7 @@ function collectNavigationNodes(nodes) {
|
||||
])
|
||||
}
|
||||
|
||||
test('keeps the confirmed personal entries at the top level', () => {
|
||||
test('keeps the confirmed top-level sequence from the client workbench prototype', () => {
|
||||
assert.deepEqual(
|
||||
clientNavigation.filter((node) => node.path).map(({ title, path, permission }) => ({
|
||||
title,
|
||||
@@ -50,101 +45,119 @@ test('keeps the confirmed navigation groups and leaf order', () => {
|
||||
assert.deepEqual(
|
||||
clientNavigation.map((node) => ({
|
||||
title: node.title,
|
||||
children: node.children?.map(({ title, path, permission }) => ({
|
||||
title,
|
||||
path,
|
||||
permission,
|
||||
})),
|
||||
children: node.children?.map(({ title }) => title),
|
||||
})),
|
||||
[
|
||||
{ title: '业务总览', children: undefined },
|
||||
{ title: '我的信息', children: undefined },
|
||||
{
|
||||
title: '头程业务',
|
||||
children: [
|
||||
{
|
||||
title: '头程订单',
|
||||
path: '/orders/first-leg',
|
||||
permission: 'order:first-leg:list',
|
||||
},
|
||||
],
|
||||
title: '头程物流',
|
||||
children: ['头程下单', '一键导入', '快速下单'],
|
||||
},
|
||||
{
|
||||
title: '出海下单',
|
||||
children: ['海外采购', '美国本土卡', '美本土散板'],
|
||||
},
|
||||
{
|
||||
title: '海外仓',
|
||||
children: ['贴标申请', '退货入库', '退货换标', '退货出库'],
|
||||
},
|
||||
{
|
||||
title: '订单管理',
|
||||
children: ['我的订单', '入库订单列表', '派送订单列表'],
|
||||
},
|
||||
{
|
||||
title: '财务结算',
|
||||
children: ['应付账单'],
|
||||
},
|
||||
{
|
||||
title: '企业管理',
|
||||
children: [
|
||||
{
|
||||
title: '企业资料',
|
||||
path: '/company/profile',
|
||||
permission: 'company:profile:view',
|
||||
},
|
||||
{
|
||||
title: '企业成员',
|
||||
path: '/organization/members',
|
||||
permission: 'company:member:list',
|
||||
},
|
||||
{
|
||||
title: '角色管理',
|
||||
path: '/organization/roles',
|
||||
permission: 'company:role:list',
|
||||
},
|
||||
{
|
||||
title: '菜单权限',
|
||||
path: '/organization/permissions',
|
||||
permission: 'company:permission:list',
|
||||
},
|
||||
],
|
||||
children: ['企业资料', '企业成员', '角色管理', '菜单权限'],
|
||||
},
|
||||
{ title: '我的信息', children: undefined },
|
||||
],
|
||||
)
|
||||
})
|
||||
|
||||
test('provides confirmed icons and unique keys recursively', () => {
|
||||
const expectedIcons = new Map([
|
||||
['dashboard', LayoutGrid],
|
||||
['account-profile', CircleUserRound],
|
||||
['first-leg', Truck],
|
||||
['first-leg-orders', ClipboardList],
|
||||
['company', Settings],
|
||||
['company-profile', Building2],
|
||||
['company-members', Users],
|
||||
['company-roles', ShieldCheck],
|
||||
['company-permissions', KeyRound],
|
||||
])
|
||||
test('provides icons and unique keys recursively for every prototype item', () => {
|
||||
const nodes = collectNavigationNodes(clientNavigation)
|
||||
|
||||
for (const node of nodes) {
|
||||
assert.equal(node.icon, expectedIcons.get(node.key), `${node.key} has the confirmed icon`)
|
||||
assert.ok(node.icon, `${node.key} has an icon`)
|
||||
}
|
||||
assert.equal(new Set(nodes.map((node) => node.key)).size, nodes.length)
|
||||
})
|
||||
|
||||
test('flattens leaves with unique paths and non-empty permissions', () => {
|
||||
test('flattens the complete prototype tree with unique paths', () => {
|
||||
const leaves = getNavigationLeaves(clientNavigation)
|
||||
const paths = leaves.map((leaf) => leaf.path)
|
||||
|
||||
assert.deepEqual(paths, [
|
||||
'/',
|
||||
'/account/profile',
|
||||
'/orders/first-leg',
|
||||
'/first-leg/import',
|
||||
'/first-leg/quick-order',
|
||||
'/cross-border/procurement',
|
||||
'/cross-border/domestic-trucking',
|
||||
'/cross-border/pallet-shipping',
|
||||
'/overseas-warehouse/labeling',
|
||||
'/overseas-warehouse/return-inbound',
|
||||
'/overseas-warehouse/return-relabel',
|
||||
'/overseas-warehouse/return-outbound',
|
||||
'/orders/my',
|
||||
'/orders/inbound',
|
||||
'/orders/delivery',
|
||||
'/finance/payables',
|
||||
'/company/profile',
|
||||
'/organization/members',
|
||||
'/organization/roles',
|
||||
'/organization/permissions',
|
||||
'/account/profile',
|
||||
])
|
||||
assert.equal(new Set(paths).size, paths.length)
|
||||
assert.ok(leaves.every((leaf) => leaf.permission.trim().length > 0))
|
||||
assert.equal(new Set(leaves.map((leaf) => leaf.permission)).size, leaves.length)
|
||||
assert.ok(leaves.filter((leaf) => leaf.permission).every((leaf) => leaf.permission?.trim().length > 0))
|
||||
})
|
||||
|
||||
test('filters inaccessible leaves and empty navigation groups', () => {
|
||||
const visible = filterNavigationByPermissions(clientNavigation, ['account:profile:view', 'order:first-leg:list'])
|
||||
|
||||
assert.deepEqual(getNavigationLeaves(visible).map((item) => item.path), ['/account/profile', '/orders/first-leg'])
|
||||
assert.deepEqual(visible.map((item) => item.title), ['我的信息', '头程业务'])
|
||||
assert.deepEqual(getNavigationLeaves(visible).map((item) => item.path), [
|
||||
'/orders/first-leg',
|
||||
'/first-leg/import',
|
||||
'/first-leg/quick-order',
|
||||
'/cross-border/procurement',
|
||||
'/cross-border/domestic-trucking',
|
||||
'/cross-border/pallet-shipping',
|
||||
'/overseas-warehouse/labeling',
|
||||
'/overseas-warehouse/return-inbound',
|
||||
'/overseas-warehouse/return-relabel',
|
||||
'/overseas-warehouse/return-outbound',
|
||||
'/orders/my',
|
||||
'/orders/inbound',
|
||||
'/orders/delivery',
|
||||
'/finance/payables',
|
||||
'/account/profile',
|
||||
])
|
||||
assert.deepEqual(visible.map((item) => item.title), ['头程物流', '出海下单', '海外仓', '订单管理', '财务结算', '我的信息'])
|
||||
assert.equal(getFirstAccessiblePath(['account:profile:view']), '/account/profile')
|
||||
assert.equal(getFirstAccessiblePath([]), '/forbidden')
|
||||
})
|
||||
|
||||
test('excludes entries marked for manual hiding without affecting other visible items', () => {
|
||||
const visible = filterNavigationByPermissions([
|
||||
{ key: 'shown', title: '显示入口', icon: LayoutGrid, path: '/shown' },
|
||||
{ key: 'hidden', title: '隐藏入口', icon: LayoutGrid, path: '/hidden', hidden: true },
|
||||
], [])
|
||||
|
||||
assert.deepEqual(getNavigationLeaves(visible).map((item) => item.path), ['/shown'])
|
||||
})
|
||||
|
||||
test('puts enterprise management behind the prototype settings divider', () => {
|
||||
const company = clientNavigation.find((node) => node.key === 'company')
|
||||
|
||||
assert.ok(company)
|
||||
assert.equal(company.dividerBefore, true)
|
||||
})
|
||||
|
||||
test('flattens a synthetic three-level navigation tree recursively', () => {
|
||||
const nestedLeaf = {
|
||||
key: 'nested-leaf',
|
||||
@@ -324,3 +337,26 @@ test('keeps the dashboard route permission synchronized with navigation', () =>
|
||||
assert.ok(dashboardRoute)
|
||||
assert.match(dashboardRoute, /permission: 'dashboard:view'/)
|
||||
})
|
||||
|
||||
test('registers every prototype-only view through its corresponding business directory', () => {
|
||||
const routerSource = readFileSync(new URL('../router/index.ts', import.meta.url), 'utf8')
|
||||
const routes = [
|
||||
['first-leg/import', 'first-leg/BatchImportView.vue'],
|
||||
['first-leg/quick-order', 'first-leg/QuickOrderView.vue'],
|
||||
['cross-border/procurement', 'cross-border/ProcurementView.vue'],
|
||||
['cross-border/domestic-trucking', 'cross-border/DomesticTruckingView.vue'],
|
||||
['cross-border/pallet-shipping', 'cross-border/PalletShippingView.vue'],
|
||||
['overseas-warehouse/labeling', 'overseas-warehouse/LabelingView.vue'],
|
||||
['overseas-warehouse/return-inbound', 'overseas-warehouse/ReturnInboundView.vue'],
|
||||
['overseas-warehouse/return-relabel', 'overseas-warehouse/ReturnRelabelView.vue'],
|
||||
['overseas-warehouse/return-outbound', 'overseas-warehouse/ReturnOutboundView.vue'],
|
||||
['orders/my', 'order-management/MyOrdersView.vue'],
|
||||
['orders/inbound', 'order-management/InboundOrdersView.vue'],
|
||||
['orders/delivery', 'order-management/DeliveryOrdersView.vue'],
|
||||
['finance/payables', 'finance/PayableBillsView.vue'],
|
||||
]
|
||||
|
||||
for (const [path, view] of routes) {
|
||||
assert.match(routerSource, new RegExp(`path: '${path}'.*?@/views/${view.replace('.', '\\.')}`))
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user