e248b6e43a
- SPA 化:22 个 MPA html 入口与 *-main.ts 合并为 index.html + vue-router(URL 无 .html 后缀), 页面跳转全部 router-link,/new_web_source/xxx.html 旧路径归一为 /xxx - 任务面板统一:共享 TaskCenterPanel/TaskItemCard/TaskStatCards/HistoryTaskLayer, 16 个工具页右侧统一为统计卡 + 当前任务 + 历史任务弹层(任务ID/开始/结束/状态必展示) - 历史记录支持单条删除 + 批量勾选删除(确认框/全选/失败提示) - Java 7 模块(dedupe/convert/split/productrisk/shopmatch/pricetrack/deletebrand) history 接口补齐任务时间字段(VO+Service,复用 biz_file_task 列) - 图片工作台/API 层(brand/permission/user)既有未提交改动一并提交
91 lines
3.7 KiB
TypeScript
91 lines
3.7 KiB
TypeScript
import assert from 'node:assert/strict'
|
||
import test from 'node:test'
|
||
|
||
import {
|
||
filterGroupsByPermission,
|
||
filterWorkflowByPermission,
|
||
TOOL_DETAILS,
|
||
TOOL_GROUPS,
|
||
TOOL_ICON_GRADIENTS,
|
||
TOOL_ICON_SHAPES,
|
||
TOOL_MAP,
|
||
} from '../src/pages/amazon/tool-catalog.ts'
|
||
|
||
test('工具目录:20 个工具 id 唯一且每个都有图标与渐变配色', () => {
|
||
const ids = TOOL_GROUPS.flatMap((g) => g.tools.map((t) => t.id))
|
||
assert.equal(ids.length, 20, '工具总数应为 20(前端8 + 运营10 + 后勤2)')
|
||
assert.equal(new Set(ids).size, ids.length, '工具 id 不应重复')
|
||
for (const id of ids) {
|
||
assert.ok(TOOL_ICON_SHAPES[id], `图标形状缺失: ${id}`)
|
||
assert.ok(TOOL_ICON_GRADIENTS[id], `图标渐变缺失: ${id}`)
|
||
assert.equal(TOOL_MAP.get(id)?.id, id, `TOOL_MAP 应覆盖: ${id}`)
|
||
}
|
||
})
|
||
|
||
test('工具目录:无页面的工具应在 catalog 里标记为未开通(无 href)', () => {
|
||
const pending = TOOL_GROUPS.flatMap((g) => g.tools).filter((t) => !t.href)
|
||
const pendingIds = pending.map((t) => t.id).sort()
|
||
assert.deepEqual(pendingIds, ['erp', 'purchase', 'shop'], '只有 店铺状态查询/采购/ERP 未开通')
|
||
})
|
||
|
||
test('权限过滤:组键命中整组保留,未命中按工具权限过滤并隐藏空组', () => {
|
||
const allowedAll = ['brand_front_tools', 'brand_operation_tools', 'brand_logistics_tools']
|
||
const all = filterGroupsByPermission(TOOL_GROUPS, allowedAll)
|
||
assert.equal(all.length, 3)
|
||
assert.ok(all[0].tools.every((t) => t.permissionKeys.length > 0))
|
||
|
||
// 只给前端组键:仅前端工具整组可见
|
||
const frontOnly = filterGroupsByPermission(TOOL_GROUPS, ['brand_front_tools'])
|
||
assert.equal(frontOnly.length, 1)
|
||
assert.equal(frontOnly[0].key, 'front')
|
||
assert.equal(frontOnly[0].tools.length, 8)
|
||
|
||
// 无组键时按单个工具权限过滤
|
||
const partial = filterGroupsByPermission(TOOL_GROUPS, ['collect-data', 'publish'])
|
||
const groups = new Map(partial.map((g) => [g.key, g]))
|
||
assert.deepEqual(groups.get('front')?.tools.map((t) => t.id), ['collect'])
|
||
assert.deepEqual(groups.get('ops')?.tools.map((t) => t.id), ['list'])
|
||
assert.equal(groups.has('logi'), false, '后勤无可见工具应整体隐藏')
|
||
|
||
// 无任何权限:全部隐藏
|
||
assert.equal(filterGroupsByPermission(TOOL_GROUPS, []).length, 0)
|
||
})
|
||
|
||
test('权限过滤:工作流时间线按工具权限截断', () => {
|
||
const front = TOOL_GROUPS.find((g) => g.key === 'front')
|
||
assert.ok(front?.workflow?.length === 8)
|
||
|
||
// 只允许 采集数据,时间线只剩它一步
|
||
const steps = filterWorkflowByPermission(front?.workflow ?? [], ['collect-data'])
|
||
assert.equal(steps.length, 1)
|
||
assert.equal(steps[0].name, '采集数据')
|
||
|
||
// 无权限 → 空
|
||
assert.equal(filterWorkflowByPermission(front?.workflow ?? [], []).length, 0)
|
||
})
|
||
|
||
test('工具目录:页面链接与现有 BrandTopBar 导航映射一致', () => {
|
||
const expectHref = new Map<string, string>([
|
||
['collect', '/collect-data'],
|
||
['dedupe', '/dedupe'],
|
||
['source', '/similar-asin'],
|
||
['brand', '/brand'],
|
||
['list', '/publish'],
|
||
['follow', '/price-track'],
|
||
['scrape', '/shop-data-crawl'],
|
||
['cash', '/withdraw'],
|
||
])
|
||
for (const [id, href] of expectHref) {
|
||
assert.equal(TOOL_MAP.get(id)?.href, href, `工具 ${id} 应指向 ${href}`)
|
||
}
|
||
})
|
||
|
||
test('工具目录:页头长描述(detail)只覆盖已知工具,且不为空', () => {
|
||
for (const [id, detail] of Object.entries(TOOL_DETAILS)) {
|
||
assert.ok(TOOL_MAP.has(id), `TOOL_DETAILS 引用了未知工具: ${id}`)
|
||
assert.ok(detail.trim().length > 0, `工具 ${id} 的 detail 不应为空`)
|
||
const toolsWithHref = TOOL_MAP.get(id)
|
||
assert.ok(toolsWithHref?.href, `detail 只应用于有页面的工具: ${id}`)
|
||
}
|
||
})
|