Files
crawler-plugin/frontend-vue/tests/amazon-tool-catalog.test.ts
huangzd1997 e248b6e43a feat(web): 前端 SPA 化 + 工具页任务面板统一与历史批量删除
- 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)既有未提交改动一并提交
2026-09-08 10:02:55 +08:00

91 lines
3.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}`)
}
})