| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /**
- * T29 底图影像(配置驱动)纯逻辑检查。
- *
- * 覆盖:配置归一化(source 白名单 / 子域 / 级别)、四种来源的计划、天地图模板拼装(开发代理 vs 生产子域)、
- * 缺 tk 与未知来源的失败态、以及宿主状态措辞。
- *
- * 运行:node .scratch/cockpit-shell-panel-layout/verify/t29-basemap.mjs
- */
- import assert from 'node:assert/strict'
- import {
- BASEMAP_SOURCE,
- BASEMAP_STATE,
- NATURAL_EARTH_TMS,
- TIANDITU_SUBDOMAINS,
- basemapStatusText,
- planBasemap,
- tiandituTileUrl,
- } from '../../../src/modules/cockpit/domain/basemap.js'
- import { builtinConfig, normalizeConfig } from '../../../src/modules/cockpit/services/cockpitConfig.js'
- // ---------------------------------------------------------------- 1. 默认不配底图(票 27 行为不变)
- const defaults = builtinConfig()
- assert.equal(defaults.map.basemap.source, BASEMAP_SOURCE.NONE, '默认必须是 none(不伪造配准)')
- assert.equal(defaults.map.tianditu.layer, 'img', '天地图默认影像底图')
- const nonePlan = planBasemap(defaults.map, { dev: true })
- assert.equal(nonePlan.ready, false, 'none 不可用')
- assert.equal(nonePlan.state, BASEMAP_STATE.NOT_CONFIGURED, 'none 的状态是 not-configured')
- assert.match(basemapStatusText(nonePlan), /底图未配置/, '未配置时保持票 27 的原话')
- // ---------------------------------------------------------------- 2. 归一化
- const normalized = normalizeConfig({
- map: {
- basemap: { source: 'natural-earth', url: ' x ', subdomains: ['a', ' b ', ''], minimumLevel: 2, maximumLevel: 'ten' },
- tianditu: { token: ' tk ', layer: 'vec' },
- },
- })
- assert.equal(normalized.config.map.basemap.source, 'natural-earth', '合法 source 应被接受')
- assert.equal(normalized.config.map.basemap.url, 'x', 'url 应去空白')
- assert.deepEqual(normalized.config.map.basemap.subdomains, ['a', 'b'], '子域应过滤空串并去空白')
- assert.equal(normalized.config.map.basemap.minimumLevel, 2, '级别应接受非负整数')
- assert.equal(normalized.config.map.basemap.maximumLevel, null, '非整数级别应被忽略')
- assert.equal(normalized.config.map.tianditu.layer, 'vec', '天地图图层应被接受')
- assert.equal(normalized.config.map.tianditu.token, 'tk', 'tk 应去空白')
- assert.equal(normalized.issues.length, 1, `只应记一条 issue,实际 ${JSON.stringify(normalized.issues)}`)
- const badSource = normalizeConfig({ map: { basemap: { source: 'baidu' }, tianditu: { layer: '影像' } } })
- assert.equal(badSource.config.map.basemap.source, BASEMAP_SOURCE.NONE, '未知来源应退回 none')
- assert.equal(badSource.config.map.tianditu.layer, 'img', '未知图层应退回 img')
- assert.equal(badSource.issues.length, 2, `两条非法取值各记一条,实际 ${JSON.stringify(badSource.issues)}`)
- const badSubdomains = normalizeConfig({ map: { basemap: { source: 'xyz', url: 't/{z}/{x}/{y}.png', subdomains: 't0' } } })
- assert.deepEqual(badSubdomains.config.map.basemap.subdomains, [], '非数组子域应被忽略')
- assert.equal(badSubdomains.issues.length, 1, '非数组子域应记一条 issue')
- // ---------------------------------------------------------------- 3. 内置离线影像
- const naturalPlan = planBasemap({ basemap: { source: 'natural-earth' } })
- assert.equal(naturalPlan.ready, true, 'natural-earth 应可用')
- assert.equal(naturalPlan.kind, 'tms', 'natural-earth 走 TMS')
- assert.equal(naturalPlan.url, NATURAL_EARTH_TMS, 'TMS 路径应是 Cesium 自带资源目录(相对 CESIUM_BASE_URL)')
- assert.match(naturalPlan.label, /离线/, '标签应说明是离线影像')
- // 免费免 key 的在线全局层(本机外网被挡,模板与署名在这里断言)
- const arcgisPlan = planBasemap({ basemap: { source: 'arcgis-imagery' } })
- assert.equal(arcgisPlan.ready, true, 'arcgis-imagery 应可用(免费免 key)')
- assert.equal(arcgisPlan.kind, 'xyz', 'arcgis 走 XYZ 模板')
- assert.match(arcgisPlan.url, /^https:\/\/services\.arcgisonline\.com\/.*\/tile\/\{z\}\/\{y\}\/\{x\}$/, 'ArcGIS 的模板顺序是 {z}/{y}/{x}')
- assert.match(arcgisPlan.credit, /Esri/, '应带上 Esri 署名')
- // ---------------------------------------------------------------- 4. 自定义 XYZ
- const xyzPlan = planBasemap({
- basemap: { source: 'xyz', url: 'tiles/{z}/{x}/{y}.png', subdomains: ['a'], minimumLevel: 1, maximumLevel: 18, credit: '甲方' },
- })
- assert.equal(xyzPlan.ready, true, 'xyz 应可用')
- assert.equal(xyzPlan.kind, 'xyz', 'xyz 走模板 provider')
- assert.equal(xyzPlan.url, 'tiles/{z}/{x}/{y}.png', '模板应原样透传')
- assert.deepEqual(xyzPlan.subdomains, ['a'], '子域应透传')
- assert.equal(xyzPlan.minimumLevel, 1, '最小级别应透传')
- assert.equal(xyzPlan.maximumLevel, 18, '最大级别应透传')
- assert.equal(xyzPlan.credit, '甲方', '署名应透传')
- const xyzNoUrl = planBasemap({ basemap: { source: 'xyz' } })
- assert.equal(xyzNoUrl.ready, false, 'xyz 缺 url 不可用')
- assert.equal(xyzNoUrl.state, BASEMAP_STATE.INVALID, '缺字段应是 invalid 而不是静默无底图')
- assert.match(xyzNoUrl.issue, /url/, '失败原因应点明缺 url')
- // ---------------------------------------------------------------- 5. 天地图(开发代理 vs 生产子域)
- const tiandituDev = planBasemap({ basemap: { source: 'tianditu' }, tianditu: { token: 'TK', layer: 'img' } }, { dev: true })
- assert.equal(tiandituDev.ready, true, '带 tk 的天地图应可用')
- assert.match(tiandituDev.url, /^\/tianditu\.map\/img_w\/wmts\?/, '开发态应走仓库自带的 /tianditu.map 代理')
- assert.match(tiandituDev.url, /tk=TK/, 'tk 应拼进查询串')
- assert.match(tiandituDev.url, /TILEMATRIX=\{z\}&TILEROW=\{y\}&TILECOL=\{x\}/, 'WMTS 的占位符顺序应是 {z}/{y}/{x}')
- assert.deepEqual(tiandituDev.subdomains, [], '代理是单主机,不加子域')
- assert.equal(tiandituDev.credit, '天地图', '应有署名')
- const tiandituProd = planBasemap({ basemap: { source: 'tianditu' }, tianditu: { token: 'TK', layer: 'vec' } }, { dev: false })
- assert.match(tiandituProd.url, /^https:\/\/t\{s\}\.tianditu\.gov\.cn\/vec_w\//, '生产应直连带子域的主机')
- assert.deepEqual(tiandituProd.subdomains, TIANDITU_SUBDOMAINS, '生产应给出子域列表')
- assert.match(tiandituProd.label, /矢量/, '标签应反映图层')
- const tiandituNoToken = planBasemap({ basemap: { source: 'tianditu' } }, { dev: true })
- assert.equal(tiandituNoToken.ready, false, '缺 tk 不可用')
- assert.equal(tiandituNoToken.state, BASEMAP_STATE.INVALID, '缺 tk 应是 invalid')
- assert.match(tiandituNoToken.issue, /tk/, '失败原因应点明缺 tk')
- assert.match(basemapStatusText(tiandituNoToken), /配置无效.*回退临时影像/, '失败措辞应说明回退')
- assert.equal(
- planBasemap({ basemap: { source: 'baidu' } }).state,
- BASEMAP_STATE.INVALID,
- '未知来源(绕过归一化直接调计划)也应判 invalid',
- )
- assert.match(tiandituTileUrl('/x/', 'T', 'ter'), /^\/x\/ter_w\/wmts\?.*tk=T$/, '模板拼装应处理尾部斜杠')
- // ---------------------------------------------------------------- 6. 状态措辞
- assert.match(basemapStatusText(naturalPlan), /底图:/, '可用时措辞应带底图名')
- assert.equal(basemapStatusText(null), '底图未配置(正式底图见票 21)', '缺省计划应回落到未配置措辞')
- console.log(
- `T29 检查通过:默认不配底图(票 27 行为不变)/ 归一化(source 白名单、子域、级别、图层)/ 四来源计划(none · natural-earth · xyz · tianditu)/ 天地图开发代理与生产子域模板 / 缺 tk 与未知来源的失败态(${BASEMAP_STATE.INVALID})。`,
- )
|