'use strict' const assert = require('node:assert/strict') const fs = require('node:fs') const os = require('node:os') const path = require('node:path') const test = require('node:test') const { DEFAULTS, loadConfig } = require('./config') function makeDir(t) { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scoreboard-config-')) t.after(() => fs.rmSync(dir, { recursive: true, force: true })) return dir } // 现场机器上那份用户配置:内容原样写进文件,读的也必须是文件里真实写了什么 function loadWith(t, raw) { const dir = makeDir(t) const file = path.join(dir, 'config.json') fs.writeFileSync(file, typeof raw === 'string' ? raw : JSON.stringify(raw, null, 2), 'utf8') return loadConfig(file) } test('缺省的 allowClickThrough 不穿透(默认值就是 false)', (t) => { assert.equal(DEFAULTS.display.allowClickThrough, false) const cfg = loadWith(t, { display: {} }) assert.equal(cfg.values.display.allowClickThrough, false) assert.deepEqual(cfg.notices, []) }) test('显式写 allowClickThrough: true 才穿透,且不产生废弃提示', (t) => { const cfg = loadWith(t, { display: { allowClickThrough: true } }) assert.equal(cfg.values.display.allowClickThrough, true) assert.deepEqual(cfg.notices, []) }) // 本次修复的核心回归钉子:老机器升级后,用户配置文件里那个旧版模板写下的 // ignoreMouse: true 必须彻底失效(userpaths.js 不会覆盖用户文件,只能靠不读旧键) test('老配置里的旧键 ignoreMouse 已失效:既不生效、也不再是穿透开关', (t) => { const cfg = loadWith(t, { display: { ignoreMouse: true } }) assert.equal('ignoreMouse' in DEFAULTS.display, false, 'DEFAULTS 里不能再有旧键') assert.equal(cfg.values.display.allowClickThrough, false, '旧键 true 不能把穿透带回来') assert.equal(cfg.values.display.ignoreMouse, undefined, '旧键不该被 merge 进最终配置') // 但必须留下一条一次性提示,让现场知道该改哪个键 assert.equal(cfg.notices.length, 1) const [notice] = cfg.notices assert.match(notice, /display\.ignoreMouse/) assert.match(notice, /display\.allowClickThrough/) assert.match(notice, /废弃/, '要明说这个键已经不用了') assert.match(notice, /不穿透/, '要明说现在的默认是不穿透') assert.match(notice, /true/, '要给出「确实想穿透」的写法') }) test('旧键提示只跟着「文件里写了旧键」出现,缺省或新键都不提示', (t) => { // 旧版模板整份配置(现场最常见的形态):只提示一次,不会按重排/每帧刷 const legacyTemplate = loadWith(t, { display: { selection: 'all-secondary', kiosk: true, ignoreMouse: true } }) assert.equal(legacyTemplate.notices.length, 1) // 新模板(已去掉旧键、写上 new key)不再提示 const currentTemplate = loadWith(t, { display: { selection: 'all-secondary', kiosk: true, allowClickThrough: false } }) assert.deepEqual(currentTemplate.notices, []) // 两个键都在:仍然按「有旧键」提示一次(提示说的是旧键不生效,与新键无关) const both = loadWith(t, { display: { ignoreMouse: true, allowClickThrough: true } }) assert.equal(both.notices.length, 1) assert.equal(both.values.display.allowClickThrough, true, '新键显式 true 仍然算数') }) test('配置文件读不出来/内容不是对象时不报废弃键、也不炸', (t) => { const missing = loadConfig(path.join(makeDir(t), 'nope.json')) assert.deepEqual(missing.notices, []) assert.equal(missing.warning !== null, true) assert.equal(missing.values.display.allowClickThrough, false) const broken = loadWith(t, '{ 这不是 JSON') assert.deepEqual(broken.notices, []) assert.deepEqual(loadWith(t, 'null').notices, []) assert.deepEqual(loadWith(t, '[1,2,3]').notices, []) })