import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import test from 'node:test' function readPanelSource() { return readFileSync( fileURLToPath(new URL('../src/pages/admin/panels/ConsignmentConfigPanel.tsx', import.meta.url)), 'utf8', ).replace(/\r\n/g, '\n') } test('从接单模板生成:factor 模式必须显式推荐「规格字段(多字段矩阵)」', () => { const source = readPanelSource() assert.ok( source.includes('推荐使用:规格字段(多字段矩阵)'), 'factor 模式必须给出推荐文案,运营才知道该用多字段矩阵', ) assert.ok( source.includes("proposal.mode === 'factor' ? ("), '推荐文案必须按 proposal.mode 分支渲染', ) }) test('从接单模板生成:product 模式必须显式推荐「商品名下拉」并解释原因', () => { const source = readPanelSource() assert.ok(source.includes('推荐使用:商品名下拉'), '降级为商品下拉时必须说明推荐该模式') assert.ok(source.includes('拆不成同一组维度'), '必须解释为什么不能拆成多字段矩阵') assert.ok( source.includes('无法纳入统一维度的模板(前 5 条)'), '必须列出拆不动的模板示例,便于运营判断是否改名', ) }) test('从接单模板生成:无模板时必须给配置引导,而不是只显示一句报错', () => { const source = readPanelSource() assert.ok( source.includes('请先在「接单模板」里为该分类配置至少 1 条启用模板'), '空状态必须引导去接单模板配置', ) assert.ok( source.includes('该分类的启用模板都没有报酬或单价'), '有模板但无价时必须区分提示,避免误以为没有模板', ) assert.ok( source.includes('推荐规则:商品名能拆成同一组维度时'), '空状态也要说明两种模式的推荐规则', ) assert.ok( !source.includes('该分类没有启用且有价的接单模板,无法生成规格字段'), '旧的死板提示必须被 Empty 引导替换', ) }) test('从接单模板生成:应用按钮按「有价组合数」禁用,空提案不能被应用', () => { const source = readPanelSource() assert.ok( source.includes('templateProposalQuery.data.data.matrix.length === 0'), '应用按钮必须在没有组合价时禁用', ) assert.ok( source.includes('proposal.matrix.length === 0 || proposal.fields.length === 0'), '应用动作本身也要兜底拦截空提案', ) })