| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /**
- * 票 24 离线回归:管线/设施几何图层(不联网)。
- *
- * 覆盖三件事:
- * 1. **契约**:后端 GeoJSON 形状 → 领域图层的转换([票 30](../issues/30-30.md) 交付物 1);
- * 2. **程序化构件分类**:样条管道(多段路径)/ 角管道(弯头)/ 阀门 / 支管管道(三通),
- * 以及未建模类型(调压等)**如实保留原文**而不是猜成已知类别;
- * 3. **坐标纪律**:未校验 / 零坐标 / 缺经度 一律**不得上图**,且必须带中文原因进「无地图位置」,
- * 既不被丢掉,也不被"挪一下"救回来。
- *
- * mock 样例在本脚本里现搭,不依赖 `mocks/contractMocks.js` 的注册时机,
- * 但形状必须与它一致(那才是浏览器里真正会吃到的载荷)。
- */
- import assert from 'node:assert/strict'
- import { toPipeNetwork, filterPipeNetwork, pipeWidth, PIPE_COMPONENT } from '../../../src/modules/cockpit/domain/pipeNetwork.js'
- const valid = { state: 'VALID', renderable: true, reason: null }
- const feature = (overrides) => ({
- kind: 'pipe',
- geometry: { type: 'LineString', coordinates: [[110.39, 28.44], [110.40, 28.45]] },
- properties: { id: 'P-1', industry: 'GAS', coordinateValidation: valid },
- ...overrides,
- })
- let failed = 0
- function check(name, action) {
- try {
- action()
- console.log(`PASS ${name}`)
- } catch (error) {
- failed += 1
- console.error(`FAIL ${name}: ${String(error.message).split('\n')[0]}`)
- }
- }
- const payload = {
- coverage: [
- { industry: 'GAS', geometryAvailable: true, pipeCount: 2, componentCount: 3 },
- { industry: 'WATER_SUPPLY', geometryAvailable: true, pipeCount: 1, componentCount: 0 },
- { industry: 'MANHOLE', geometryAvailable: false, pipeCount: 0, componentCount: 1 },
- ],
- features: [
- feature({}),
- // 多段路径 = 样条管道的输入(真实库多为两点,但契约必须支持多段)
- feature({ geometry: { type: 'LineString', coordinates: [[110.39, 28.44], [110.395, 28.445], [110.40, 28.44]] }, properties: { id: 'P-2', industry: 'GAS', diameter: 400, coordinateValidation: valid } }),
- feature({ properties: { id: 'P-3', industry: 'WATER_SUPPLY', coordinateValidation: valid } }),
- { kind: 'component', geometry: { type: 'Point', coordinates: [110.395, 28.445] }, properties: { id: 'C-1', pointType: '阀门', networkId: 'P-1', industry: 'GAS', coordinateValidation: valid } },
- { kind: 'component', geometry: { type: 'Point', coordinates: [110.40, 28.44] }, properties: { id: 'C-2', pointType: '弯头', networkId: 'P-1', industry: 'GAS', coordinateValidation: valid } },
- { kind: 'component', geometry: { type: 'Point', coordinates: [110.39, 28.44] }, properties: { id: 'C-3', pointType: '三通', networkId: 'P-2', industry: 'GAS', coordinateValidation: valid } },
- { kind: 'component', geometry: { type: 'Point', coordinates: [110.41, 28.46] }, properties: { id: 'C-4', pointType: '调压', networkId: 'P-1', industry: 'GAS', coordinateValidation: valid } },
- ],
- }
- const network = toPipeNetwork(payload)
- check('B1 管段与构件分开归类,不混为一类对象', () => {
- assert.equal(network.pipes.length, 3)
- assert.equal(network.components.length, 4)
- assert.ok(network.pipes.every((row) => row.kind === undefined), '管段不带构件类别')
- })
- check('B2 多段路径原样保留(样条管道的输入不被压成两点)', () => {
- const spline = network.pipes.find((row) => row.code === 'P-2')
- assert.equal(spline.positions.length, 3)
- })
- check('B3 四类构件按后端真实属性分类', () => {
- const byId = Object.fromEntries(network.components.map((row) => [row.code, row.kind]))
- assert.equal(byId['C-1'], PIPE_COMPONENT.VALVE)
- assert.equal(byId['C-2'], PIPE_COMPONENT.ELBOW)
- assert.equal(byId['C-3'], PIPE_COMPONENT.BRANCH)
- assert.equal(byId['C-4'], PIPE_COMPONENT.OTHER)
- })
- check('B4 未建模的构件类型保留后端原文,不被猜成已知类别', () => {
- const regulator = network.components.find((row) => row.code === 'C-4')
- assert.equal(regulator.label, '调压')
- })
- check('B5 构件记录它属于哪条管线(不做拓扑推断)', () => {
- const valve = network.components.find((row) => row.code === 'C-1')
- assert.equal(valve.networkId, 'P-1')
- })
- check('B6 行业覆盖按后端声明转述,没点名的行业如实记"无几何"', () => {
- assert.equal(network.coverage.GAS.geometryAvailable, true)
- assert.equal(network.coverage.MANHOLE.geometryAvailable, false, '窨井无管线几何必须如实说无')
- assert.equal(network.coverage.DRAINAGE.geometryAvailable, false, '后端没点名排水 → 不假装有')
- assert.equal(network.coverage.DRAINAGE.pipeCount, 0)
- })
- check('C1 未校验坐标不得上图,且带中文原因', () => {
- const blocked = toPipeNetwork({ features: [feature({ properties: { id: 'X-1', industry: 'GAS', coordinateValidation: { state: 'UNVERIFIED', renderable: false, reason: 'UNVERIFIED_COORDINATE' } } })] })
- assert.equal(blocked.pipes.length, 0)
- assert.equal(blocked.blocked.length, 1)
- assert.equal(blocked.blocked[0].reasonText, '坐标未经校验')
- })
- check('C2 零坐标不得上图', () => {
- const blocked = toPipeNetwork({ features: [feature({ properties: { id: 'X-2', industry: 'GAS', coordinateValidation: { state: 'INVALID', renderable: false, reason: 'ZERO_COORDINATE' } } })] })
- assert.equal(blocked.pipes.length, 0)
- assert.equal(blocked.blocked[0].reasonText, '零坐标(经纬度均为 0)')
- })
- check('C3 认不出的原因回「无地图位置」,不把原因码甩给界面', () => {
- const blocked = toPipeNetwork({ features: [feature({ properties: { id: 'X-3', industry: 'GAS', coordinateValidation: { state: 'INVALID', renderable: false, reason: 'SOMETHING_NEW' } } })] })
- assert.equal(blocked.blocked[0].reasonText, '无地图位置')
- })
- check('C4 点数不足的管段不得渲染(不补点、不截断成一点)', () => {
- const blocked = toPipeNetwork({ features: [feature({ geometry: { type: 'LineString', coordinates: [[110.39, 28.44]] } })] })
- assert.equal(blocked.pipes.length, 0)
- assert.equal(blocked.blocked.length, 1)
- })
- check('C5 缺少校验结论一律拦下("没说不"不等于"可以画")', () => {
- const blocked = toPipeNetwork({ features: [feature({ properties: { id: 'X-4', industry: 'GAS' } })] })
- assert.equal(blocked.pipes.length, 0)
- assert.equal(blocked.blocked[0].reasonText, '坐标未校验')
- })
- check('D1 行业筛选只留该行业,图层过滤只此一处', () => {
- const gas = filterPipeNetwork(network, { industry: 'gas' })
- assert.ok(gas.pipes.every((row) => row.industry === 'GAS'))
- assert.ok(gas.components.every((row) => row.industry === 'GAS'))
- })
- check('D2 全域筛选不裁剪', () => {
- const all = filterPipeNetwork(network, { industry: 'all' })
- assert.equal(all.pipes.length, network.pipes.length)
- })
- check('D3 片区筛选如实标记为未作用到管线(管线无片区字段)', () => {
- assert.equal(filterPipeNetwork(network, { industry: 'all' }).districtApplied, false)
- })
- check('E1 管径分档映射线宽,缺管径不炸', () => {
- assert.equal(pipeWidth(null), 2)
- assert.equal(pipeWidth(200), 2)
- assert.equal(pipeWidth(400), 3)
- assert.equal(pipeWidth(800), 4)
- assert.equal(pipeWidth(1200), 6)
- })
- check('E2 空载荷不抛,退化为空图层', () => {
- const empty = toPipeNetwork(null)
- assert.deepEqual(empty.pipes, [])
- assert.deepEqual(empty.components, [])
- assert.equal(empty.coverage.GAS.geometryAvailable, false)
- })
- console.log(`T24 管线图层: ${failed ? 'FAILED' : 'passed'}`)
- process.exitCode = failed ? 1 : 0
|