import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import ts from 'typescript'; const source = fs.readFileSync(new URL('../src/components/device-volume-state.ts', import.meta.url), 'utf8'); const module = { exports: {} }; new Function('module', 'exports', ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText)(module, module.exports); const { volumeSyncMessage, volumeSyncStatus } = module.exports; const twin = (desired, actual, desiredRevision = 2, reportedRevision = 2) => ({ desired_revision: desiredRevision, reported_revision: reportedRevision, desired_config: desired === undefined ? {} : { volume: { speaker: desired } }, reported_config: actual === undefined ? {} : { volume: { speaker: actual } }, }); test('volume status distinguishes a read in progress from an unreported volume', () => { assert.equal(volumeSyncStatus(undefined), '正在读取音量状态'); assert.equal(volumeSyncStatus(twin(undefined, undefined)), '等待设备上报音量'); assert.equal(volumeSyncStatus(twin(undefined, 0)), '已收到设备音量'); }); test('synchronized volume requires both the actual value and revision confirmation', () => { assert.equal(volumeSyncStatus(twin(0, 0)), '音量已同步'); assert.match(volumeSyncStatus(twin(60, 60, 2, 1)), /等待设备确认/); assert.match(volumeSyncStatus(twin(60, 40)), /等待设备确认/); assert.match(volumeSyncStatus(twin(60, undefined)), /等待设备确认/); }); test('offline changes remain pending, while last confirmed values remain confirmed', () => { assert.equal(volumeSyncStatus(twin(60, 40), false), '音量设置已保存,设备上线后会自动同步'); assert.equal(volumeSyncStatus(twin(60, 60), false), '音量已同步'); }); test('action confirmation retains the existing actual-volume information', () => { assert.equal(volumeSyncMessage(twin(0, 0)), '音量已生效,设备实际音量 0%'); assert.equal(volumeSyncMessage(twin(undefined, 40)), '设备当前音量 40%'); assert.equal(volumeSyncMessage(twin(60, 40), false), '音量设置已保存,设备上线后会自动同步'); });