Files
order_site/apps/frontend/tests/consignment-matching-config.test.ts
T

197 lines
10 KiB
TypeScript
Raw 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 { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import test from 'node:test'
function read(relativePath: string) {
return readFileSync(fileURLToPath(new URL(relativePath, import.meta.url)), 'utf8')
}
test('管理端:订单服务之后必须存在寄卖配置 tab', () => {
const tabs = read('../src/utils/admin-worker-platform-tabs.ts')
assert.ok(tabs.includes("'consignment-config'"), '合法 tab 名单必须包含 consignment-config')
assert.ok(
tabs.includes("'consignment-config': [['admin-consignment-profiles']"),
'切到寄卖配置必须刷新配置查询',
)
const page = read('../src/pages/admin/AdminWorkerPlatformPage.tsx')
assert.ok(page.includes('ConsignmentConfigPanel'), '页面必须挂载寄卖配置面板')
const orderServiceIndex = page.indexOf("label: '订单服务'")
const consignmentIndex = page.indexOf("label: '寄卖配置'")
assert.ok(
orderServiceIndex > 0 && consignmentIndex > orderServiceIndex,
'寄卖配置必须在订单服务之后',
)
})
test('寄卖配置面板:必须覆盖保证金/服务费/数量限制/匹配/内部匹配/超时/降价', () => {
const panel = read('../src/pages/admin/panels/ConsignmentConfigPanel.tsx')
for (const label of [
'打手端 tab 名称',
'开启保证金',
'按数量',
'开启服务费',
'开启单人寄售上限',
'匹配模式',
'关闭匹配',
'手动匹配等待(分钟)',
'代练超时(小时)',
'重新匹配并退还押金',
'开启降价提示',
]) {
assert.ok(panel.includes(label), `寄卖配置面板缺少「${label}」`)
}
})
test('打手端:寄卖页必须按已发布配置动态生成 tab,并支持改价', () => {
const page = read('../src/pages/worker/WorkerConsignmentPage.tsx')
assert.ok(page.includes('fetchWorkerConsignmentProfiles'), '必须拉取已发布寄卖配置')
assert.ok(page.includes('profileTreeData'), '必须按配置生成 tab/分类树')
assert.ok(page.includes('修改售价'), '在售寄卖必须提供改价入口')
assert.ok(page.includes('updateWorkerConsignmentPrice'), '改价必须调用专用接口')
assert.ok(page.includes('priceDropSuggestion'), '必须展示降价建议')
assert.ok(page.includes('寄售数量'), '发布表单必须支持数量')
})
test('工单页:必须挂载内部库存匹配弹窗,并支持状态 internal_matching', () => {
const panel = read('../src/pages/admin/panels/WorkOrdersPanel.tsx')
assert.ok(panel.includes('ConsignmentWorkOrderMatchModal'), '工单页必须挂载内部匹配弹窗')
assert.ok(panel.includes("'internal_matching'"), '状态筛选必须支持内部匹配中')
const shared = read('../src/pages/admin/panels/shared.tsx')
assert.ok(shared.includes("internal_matching: '内部匹配中'"), '状态文案必须包含内部匹配中')
assert.ok(shared.includes("internal_matching: 'magenta'"), '状态配色必须包含内部匹配中')
})
test('寄卖配置面板:订单服务风格分类树、独立分区与价格配置', () => {
const panel = read('../src/pages/admin/panels/ConsignmentConfigPanel.tsx')
for (const label of [
'搜索分类',
'个分类已配置',
'规格字段',
'添加字段',
'基础信息',
'价格配置',
'履约保证金',
'服务费',
'库存数量限制',
'匹配设置',
'超时设置',
'降价提示',
'联系方式与游戏凭据',
'接单模板价打折',
'模板价固定下调',
'模板折扣',
'物品名模板',
]) {
assert.ok(panel.includes(label), `寄卖配置面板缺少「${label}」`)
}
assert.ok(panel.includes('order-service-category-group'), '分类必须按订单服务风格分组')
assert.ok(
panel.indexOf('title="规格字段"') < panel.indexOf('title="联系方式与游戏凭据"') &&
panel.indexOf('title="联系方式与游戏凭据"') < panel.indexOf('title="价格配置"'),
'联系方式与游戏凭据必须紧跟在规格字段之后、价格配置之前',
)
assert.ok(panel.includes('order-service-subcategory-list'), '二级分类必须缩进展示')
assert.ok(panel.includes('resolveInheritedProfileStatus'), '子分类必须展示继承父级状态')
assert.ok(panel.includes('order-service-save-bar'), '底部必须使用订单服务保存栏')
assert.ok(panel.includes('ConsignmentSectionTitle'), '配置分区必须使用编号标题')
assert.ok(!panel.includes('DEFAULT_SPEC_FIELDS'), '面板不能预置任何内置字段')
assert.ok(panel.includes('useState<ConsignmentSpecField[]>([])'), '规格字段初始必须为空')
assert.ok(panel.includes('specDrafts.map'), '规格字段必须可动态增删/排序')
assert.ok(panel.includes('SPEC_FIELD_TYPE_OPTIONS'), '字段类型必须支持 6 种选项')
assert.ok(panel.includes('addonBefore="选项"'), '下拉/单选项必须使用订单服务式逗号输入')
assert.ok(panel.includes('placeholder="选项1,选项2,选项3"'), '选项输入必须使用订单服务占位文案')
assert.ok(panel.includes('updateOptionText'), '选项编辑必须把逗号分隔文本解析为选项')
assert.ok(!panel.includes('添加选项'), '选项不再逐行编辑')
})
test('打手端:动态规格 + 系统建议价 + 改价不得高于建议价', () => {
const page = read('../src/pages/worker/WorkerConsignmentPage.tsx')
assert.ok(page.includes('selectedSpecs.map'), '规格必须按配置动态渲染')
assert.ok(page.includes('fetchWorkerConsignmentPricePreview'), '必须走动态价格预览')
assert.ok(page.includes('不能高于系统建议价'), '前端必须提示改价上限')
assert.ok(page.includes('specValues'), '发布必须提交动态规格值')
assert.ok(page.includes('config.pricing.allowWorkerPrice'), '改价能力必须按配置')
})
test('寄卖配置:未售出时长支持一位小数', () => {
const panel = read('../src/pages/admin/panels/ConsignmentConfigPanel.tsx')
const start = panel.indexOf("name={['priceDrop', 'hours']}")
assert.ok(start > 0, '必须存在未售出时长配置')
const block = panel.slice(start, panel.indexOf('</Form.Item>', start))
assert.ok(block.includes('precision={1}'), '未售出时长必须支持一位小数')
assert.ok(block.includes('min={0.1}'), '未售出时长下限应为 0.1 小时')
})
test('寄卖配置:保证金支持按数量(规格),弹窗内配置选项价格', () => {
const panel = read('../src/pages/admin/panels/ConsignmentConfigPanel.tsx')
assert.ok(
panel.includes("{ value: 'per_spec', label: '按数量(规格)' }"),
'保证金模式必须包含「按数量(规格)」',
)
assert.ok(panel.includes('title="按数量(规格)保证金"'), '必须提供规格价格配置弹窗')
assert.ok(panel.includes('specPricesYuan'), '选项价格必须写回配置')
assert.ok(panel.includes('填充全部选项'), '弹窗必须支持批量填充选项价格')
})
test('寄卖配置:规格字段与联系方式区块提供复制模板配置入口', () => {
const panel = read('../src/pages/admin/panels/ConsignmentConfigPanel.tsx')
assert.ok(panel.includes('复制模板配置'), '两个区块都要有复制模板配置按钮')
assert.ok(panel.includes("setCopyTemplateMode('specs')"), '规格字段入口必须打开规格复制')
assert.ok(panel.includes("setCopyTemplateMode('intake')"), '联系方式入口必须打开凭据复制')
assert.ok(panel.includes('ConsignmentTemplateCopyModal'), '必须挂载复制模板弹窗')
const modal = read('../src/components/admin/ConsignmentTemplateCopyModal.tsx')
assert.ok(modal.includes('已发布版本'), '复制来源必须支持已发布版本')
assert.ok(modal.includes('当前草稿'), '复制来源必须支持当前草稿')
assert.ok(modal.includes('publishedConfig'), '已发布版本必须读取发布快照配置')
assert.ok(modal.includes('不影响价格、保证金、服务费、匹配和超时设置'), '复制只替换当前区块')
assert.ok(modal.includes('ruleKey'), '模板驱动规格必须提示 ruleKey 仍指向来源模板')
assert.ok(modal.includes('TreeSelect'), '来源选择必须使用折叠树')
assert.ok(
modal.includes('treeDefaultExpandAll') && !modal.includes('treeDefaultExpandAll={false}'),
'来源树默认必须展开二级',
)
assert.ok(modal.includes('treeTitleRender'), '来源树必须自定义层级标题')
assert.ok(
!modal.includes('key: `') && modal.includes('.map((node) => node.value)'),
'展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效',
)
})
test('打手端:寄卖分类按一二级层级展示', () => {
const page = read('../src/pages/worker/WorkerConsignmentPage.tsx')
assert.ok(page.includes('categoryParentName'), '必须使用父分类名称')
assert.ok(page.includes('orderWorkerProfiles'), '必须按一级/二级排序')
assert.ok(page.includes('profileTreeData'), '必须构建一级/二级树')
assert.ok(page.includes('TreeSelect'), '必须使用可折叠的 TreeSelect')
assert.ok(
page.includes('treeDefaultExpandAll') && !page.includes('treeDefaultExpandAll={false}'),
'默认必须展开二级',
)
assert.ok(page.includes('treeTitleRender'), '必须自定义层级标题')
assert.ok(
!page.includes('key: `') && page.includes('.map((node) => node.value)'),
'展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效',
)
assert.ok(page.includes('二级'), '二级分类必须有层级标签')
})
test('寄售仓库:寄卖分类筛选按一二级层级展示', () => {
const panel = read('../src/pages/admin/panels/ConsignmentInventoryPanel.tsx')
assert.ok(panel.includes('categoryTreeData'), '必须构建一级/二级树')
assert.ok(panel.includes('TreeSelect'), '必须使用可折叠的 TreeSelect')
assert.ok(
panel.includes('treeDefaultExpandAll') && !panel.includes('treeDefaultExpandAll={false}'),
'默认必须展开二级',
)
assert.ok(panel.includes('treeTitleRender'), '必须自定义层级标题')
assert.ok(
!panel.includes('key: `') && panel.includes('.map((node) => node.value)'),
'展开键必须来自节点 value(rc-tree 内部 key 即 value),否则默认展开失效',
)
assert.ok(panel.includes('继承'), '继承型二级分类必须有继承标记')
})