Files
docs/悦/货代SAAS平台后台/tests/verify-fee-flow-diagram.cjs
T
2026-08-21 09:20:26 +08:00

47 lines
3.2 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const root = path.resolve(__dirname, '..');
const file = path.join(root, '流程图', '费用流转流程图.html');
assert.ok(fs.existsSync(file), '缺少费用流转流程图 HTML');
const html = fs.readFileSync(file, 'utf8');
assert.match(html, /data-flow-direction="vertical"/, '流程方向必须为由上向下');
assert.match(html, /data-department-layout="columns"/, '部门必须横向排列为四列');
const departmentColumns = [...html.matchAll(/<div class="lane" data-department="([^"]+)">/g)].map(match => match[1]);
assert.deepEqual(departmentColumns, ['业务订单', '系统', '财务', '客户与供应商'], '部门列顺序不正确');
const canvasSize = html.match(/data-canvas-width="(\d+)" data-canvas-height="(\d+)"/);
assert.ok(canvasSize, '缺少竖向画布尺寸标记');
assert.ok(Number(canvasSize[2]) > Number(canvasSize[1]), '竖向画布高度必须大于宽度');
for (const label of ['业务订单', '系统', '财务', '客户与供应商']) {
assert.match(html, new RegExp(label), `缺少泳道:${label}`);
}
for (const label of ['应收', '应付', '待审核', '审核通过', '审核驳回', '待确认', '已确认', '待审批', '生效', '部分收款', '部分付款', '已结清', '禁止结算', '原型未定义']) {
assert.match(html, new RegExp(label), `缺少流程节点或图例:${label}`);
}
for (const marker of ['data-node-id=', 'contenteditable', 'localStorage', 'download', 'Blob', '打印', '恢复默认']) {
assert.match(html, new RegExp(marker), `缺少可编辑能力:${marker}`);
}
assert.doesNotMatch(html, /<script[^>]+src=|<link[^>]+href=/i, '流程图不应依赖外部脚本或样式');
const expectedNodeIds = [
'order-fee-source', 'fee-generated', 'fee-pending-audit', 'fee-audit-decision',
'fee-rejected', 'fee-approved', 'join-settlement-decision', 'fee-archived',
'ar-bill', 'ar-bill-audit', 'ar-push', 'customer-confirm', 'ar-confirm-wait',
'ar-settlement', 'ar-approve', 'ar-payment', 'ar-paid', 'ar-undefined',
'ap-bill', 'ap-settlement', 'ap-approval', 'ap-rejected', 'ap-effective',
'ap-voucher', 'ap-payment', 'ap-paid', 'supplier-undefined'
];
const nodeIds = [...html.matchAll(/data-node-id="([^"]+)"/g)].map(match => match[1]);
assert.equal(nodeIds.length, expectedNodeIds.length, '费用节点数量不正确');
assert.equal(new Set(nodeIds).size, nodeIds.length, '费用节点 ID 必须唯一');
assert.deepEqual(new Set(nodeIds), new Set(expectedNodeIds), '费用节点 ID 清单不完整');
assert.match(html, /function readNodeText\(textEl\)/, '缺少保留换行的纯文本读取函数');
assert.match(html, /const safeStorage\s*=\s*\{/, '缺少 localStorage 安全访问封装');
assert.match(html, /addEventListener\('paste'/, '缺少纯文本粘贴处理');
assert.match(html, /height:74px[^}]*overflow:hidden/, '节点必须保持固定高度,避免覆盖相邻节点和连线');
assert.match(html, /textEl\.textContent\s*=\s*exportedTexts\[/, '下载文件必须使用清洗后的纯文本节点内容');
console.log('验证通过:费用流转流程图 HTML 结构完整且为离线自包含文件。');