33 lines
2.6 KiB
JavaScript
33 lines
2.6 KiB
JavaScript
|
|
const test=require('node:test'),assert=require('node:assert/strict'),vm=require('node:vm'),fs=require('node:fs');
|
||
|
|
const app=fs.readFileSync('web/app.js','utf8'),homes=fs.readFileSync('web/households.js','utf8');
|
||
|
|
const part=(s,a,b)=>s.slice(s.indexOf(a),s.indexOf(b,s.indexOf(a)+a.length));
|
||
|
|
test('API uses current household scope for each new request',async()=>{
|
||
|
|
const calls=[];const c=vm.createContext({sessionGeneration:0,householdScope:'house-a',fetch:async(p,o)=>{calls.push(o);return {ok:true,json:async()=>({})};}});
|
||
|
|
vm.runInContext(part(app,'async function api(','function toast('),c);
|
||
|
|
await c.api('/api/state');c.householdScope='house-b';await c.api('/api/users',{});
|
||
|
|
assert.equal(calls[0].headers['X-Household-Id'],'house-a');assert.equal(calls[1].headers['X-Household-Id'],'house-b');
|
||
|
|
});
|
||
|
|
test('switch destroys old private state before requesting another household',async()=>{
|
||
|
|
const events=[];const c=vm.createContext({state:{familyId:'a'},currentUser:{id:'root'},isPlatformAdmin:()=>true,
|
||
|
|
clearPrivateView(){events.push('clear');c.currentUser=null;c.state={};},auth:async()=>{events.push('auth');assert.equal(c.householdScope,'b');assert.equal(c.currentUser.id,'root');}});
|
||
|
|
vm.runInContext(part(homes,'async function switchHousehold(','function openHousehold('),c);await c.switchHousehold('b');
|
||
|
|
assert.deepEqual(events,['clear','auth']);
|
||
|
|
});
|
||
|
|
test('family administrator cannot invoke household switching',async()=>{
|
||
|
|
const c=vm.createContext({state:{familyId:'a'},isPlatformAdmin:()=>false,clearPrivateView:()=>{throw Error('should not switch');}});
|
||
|
|
vm.runInContext(part(homes,'async function switchHousehold(','function openHousehold('),c);await c.switchHousehold('b');
|
||
|
|
});
|
||
|
|
test('household switch invalidates outstanding API data',async()=>{
|
||
|
|
let finish;const c=vm.createContext({sessionGeneration:0,householdScope:'a',fetch:()=>new Promise(r=>finish=r)});
|
||
|
|
vm.runInContext(part(app,'async function api(','function toast('),c);
|
||
|
|
const pending=c.api('/api/users');c.sessionGeneration++;c.householdScope='b';finish({ok:true,json:async()=>({users:['private-a']})});
|
||
|
|
await assert.rejects(pending,e=>e.stale===true);
|
||
|
|
});
|
||
|
|
test('owner is visibly distinct from family and super administrators',()=>{
|
||
|
|
const c=vm.createContext({state:{households:[{ownerId:'owner'}]}});
|
||
|
|
vm.runInContext(part(app,'const roleName =','function applyPermissions(')+';globalThis.label=roleName;',c);
|
||
|
|
assert.equal(c.label({id:'owner',role:'family_admin'}),'一家之主');
|
||
|
|
assert.equal(c.label({id:'backup',role:'family_admin'}),'家庭管理员');
|
||
|
|
assert.equal(c.label({id:'root',role:'admin'}),'超级管理员');
|
||
|
|
});
|