main
John Lauer Refresh asset hashes and verify independent fan instances 0f6d815 12d ago
import assert from 'node:assert/strict';import fs from 'node:fs';import {bindFanMotion} from '../states/controller.mjs';
const manifest=JSON.parse(fs.readFileSync(new URL('../states.json',import.meta.url)));let rotor={name:'Fan.Rotor'};let group={name:'Fan.Rotor.Revolution',targetedAnimations:[{target:rotor}],isStarted:false,stop(){this.isStarted=false},pause(){this.paused=true},start(loop,rate){this.isStarted=true;this.speedRatio=rate;this.paused=false},play(){this.paused=false}};
const c=bindFanMotion({animationGroups:[group],transformNodes:[rotor]},manifest);
assert.equal(c.apply({state:'on',speed:6000}).playbackRate,100);assert.equal(c.apply({state:'on',speed:6000,timeScale:.02}).playbackRate,2);
c.apply({state:'off',speed:0});assert(group.paused);assert.throws(()=>c.apply({state:'off',speed:7000}));assert.throws(()=>c.apply({state:'on',speed:NaN}));assert.throws(()=>c.apply({state:'on',speed:10001}));assert.equal(c.apply({state:'on',speed:null,valid:false,source:'measured'}).state,'unknown');assert(group.paused);
assert.throws(()=>bindFanMotion({animationGroups:[group,group],transformNodes:[rotor]},manifest));
console.log('motion adapter: rate mapping, off, invalid/stale and ambiguous binding checks passed');
// Repeated component instances with identical GLB names must remain independent.
const rotor2={name:'Fan.Rotor'};
const group2={...group,targetedAnimations:[{target:rotor2}],isStarted:false,paused:true};
const c2=bindFanMotion({animationGroups:[group2],transformNodes:[rotor2]},manifest);
c.apply({state:'on',speed:3000});c2.apply({state:'on',speed:7000});
assert.equal(group.speedRatio,50);assert.equal(group2.speedRatio,7000/60);
c.apply({state:'off',speed:0});assert(group.paused);assert.equal(group2.paused,false);
assert.throws(()=>c2.apply({state:'on',speed:Infinity}));assert(group2.paused);assert.equal(c2.status().state,'unknown');
assert.throws(()=>bindFanMotion({animationGroups:[{...group,targetedAnimations:[{target:{name:'Fan.Housing'}}]}],transformNodes:[rotor]},manifest));
console.log('instance isolation and fail-closed motion checks passed');