Files
mi-fitness-health/maintenance/legacy-tests/health-interaction.test.cjs

47 lines
3.3 KiB
JavaScript

const test=require('node:test');
const assert=require('node:assert/strict');
const vm=require('node:vm');
const fs=require('node:fs');
const HealthViews=require('../mi-fitness-mcp-cn/src/mi_fitness_mcp/web_assets/static/js/health-views.js');
function fixture(){
const nodes=new Map(),saved={};let callback;
const get=id=>{if(!nodes.has(id))nodes.set(id,{value:({startDate:'2026-10-15',endDate:'2026-10-17',napsSelect:'true'})[id]||'',textContent:'',innerHTML:'',checked:false,dataset:{},setAttribute(k,v){this[k]=v;},classList:{toggle(){},add(){},remove(){}}});return nodes.get(id);};
const c=vm.createContext({HealthViews,AbortController,console,performance,document:{getElementById:get,querySelectorAll(){return [];},addEventListener(name,fn){callback=fn;},documentElement:{setAttribute(){}}},localStorage:{getItem(k){return saved[k]||'';},setItem(k,v){saved[k]=v;}},setTimeout(){},setInterval(){},clearTimeout(){},clearInterval(){}});
vm.runInContext(fs.readFileSync('work/mi-fitness-mcp-cn/src/mi_fitness_mcp/web_assets/static/js/health-ui.js','utf8'),c);
vm.runInContext(fs.readFileSync('work/mi-fitness-mcp-cn/src/mi_fitness_mcp/web_assets/static/js/app.js','utf8'),c);
vm.runInContext('showToast=()=>{};',c);
return{c,get,saved};
}
test('切换到睡眠页自动查询并清空上个接口,修改日期会重新加载',async()=>{
const f=fixture();vm.runInContext('calls=[];api=async(method,path)=>{calls.push(path);return {status:"ok",data:[]};};state.lastResponse={old:true};',f.c);
await vm.runInContext("switchTab('sleep')",f.c);
assert.equal(vm.runInContext('state.lastResponse',f.c),null);
assert.equal(vm.runInContext('calls.length',f.c),1);
assert.match(f.get('healthView-sleep').innerHTML,/睡眠分析明细/);
await vm.runInContext("setDatePreset('7d')",f.c);
assert.equal(vm.runInContext('calls.length',f.c),2);
});
test('后返回的旧日期请求不会覆盖新日期结果或控制台',async()=>{
const f=fixture();const waits=[];f.c.pending=waits;
vm.runInContext('state.activeTab="sleep";api=(method,path,body,view)=>new Promise(resolve=>pending.push({resolve,view}));',f.c);
const first=vm.runInContext('querySleep()',f.c);
f.get('startDate').value='2026-10-16';
const second=vm.runInContext('querySleep()',f.c);
assert.equal(waits[0].view.isCurrent(),false);
waits[1].resolve({status:'ok',data:[{end_at:'2026-10-16T08:00:00+08:00',time_asleep_minutes:400}]});await second;
waits[0].resolve({status:'ok',data:[{end_at:'2026-10-15T08:00:00+08:00',time_asleep_minutes:100}]});await first;
assert.equal(vm.runInContext('state.healthViews.sleep.model.records[0].time_asleep_minutes',f.c),400);
});
test('失败与无数据分别显示,控制台开关会记忆选择',async()=>{
const f=fixture();vm.runInContext('state.activeTab="spo2";api=async()=>null;',f.c);
await vm.runInContext('querySpo2()',f.c);
assert.match(f.get('healthView-spo2').innerHTML,/查询失败/);
vm.runInContext('api=async()=>({status:"ok",data:[]});',f.c);
await vm.runInContext('querySpo2()',f.c);
assert.match(f.get('healthView-spo2').innerHTML,/未保存/);
vm.runInContext('setInspectorCollapsed(true)',f.c);
assert.equal(f.saved.mi_fitness_inspector_collapsed,'true');
assert.equal(f.get('inspectorToggle').textContent,'展开控制台');
assert.equal(f.get('inspectorToggle')['aria-expanded'],'false');
});