tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

output-reveal.test.mjs (2763B)


      1 import test from 'node:test';
      2 import assert from 'node:assert/strict';
      3 import {revealDelta} from '../dist/output-reveal.js';
      4 test('only an offscreen result start needs revealing, not the whole large result',()=>{
      5  assert.equal(revealDelta(250,10000,140,0,844),0);
      6  assert.equal(revealDelta(900,10000,140,0,844),748);
      7  assert.equal(revealDelta(100,100,140,0,844),-52);
      8  assert.equal(revealDelta(810,100,140,0,844),658);
      9 });
     10 test('reveal respects visual viewport offsets and small keyboard-height viewports',()=>{
     11  assert.equal(revealDelta(300,100,100,120,360),0);
     12  assert.equal(revealDelta(460,100,100,120,360),228);
     13  assert.equal(revealDelta(400,100,140,0,100),0);
     14 });
     15 
     16 test('foreground reveal is once-only, cancelable, mobile-only and never steals focus',async()=>{
     17  const saved=Object.fromEntries(['window','matchMedia','requestAnimationFrame','innerHeight'].map(k=>[k,globalThis[k]]));
     18  const frames=[],scrolls=[];let mobile=true,inert=false;
     19  try{
     20   const win=new EventTarget();win.visualViewport={offsetTop:0,height:844};win.scrollBy=value=>scrolls.push(value);
     21   globalThis.window=win;globalThis.innerHeight=844;globalThis.matchMedia=()=>({matches:mobile});globalThis.requestAnimationFrame=fn=>frames.push(fn);
     22   const {outputReveal}=await import('../dist/output-reveal.js');
     23   const controller=outputReveal({getBoundingClientRect:()=>({height:140})});
     24   const target={getBoundingClientRect:()=>({top:900,height:2000}),getClientRects:()=>[{}],closest:()=>inert?{}:null,focus:()=>assert.fail('Must not focus the result')};
     25   const flush=()=>{while(frames.length)frames.shift()(0);};
     26   controller.reveal(target);flush();assert.equal(scrolls.length,0,'Background work never arms reveal');
     27   controller.arm();controller.reveal(target);controller.reveal(target);flush();assert.equal(scrolls.length,1,'Only first result/IO event reveals');
     28   assert.deepEqual(scrolls[0],{top:748,behavior:'instant'});
     29   controller.arm();controller.reveal(target);controller.cancel();flush();assert.equal(scrolls.length,1,'Stop invalidates queued reveal');
     30   for(const event of ['wheel','touchmove','pagehide']){controller.arm();win.dispatchEvent(new Event(event));controller.reveal(target);flush();assert.equal(scrolls.length,1,event);}
     31   controller.arm();win.dispatchEvent(Object.assign(new Event('keydown'),{key:'PageDown'}));controller.reveal(target);flush();assert.equal(scrolls.length,1);
     32   mobile=false;controller.arm();controller.reveal(target);flush();assert.equal(scrolls.length,1,'Desktop stays put');
     33   mobile=true;inert=true;controller.arm();controller.reveal(target);flush();assert.equal(scrolls.length,1,'Modal settings stays put');
     34  }finally{for(const [key,value]of Object.entries(saved))if(value===undefined)delete globalThis[key];else globalThis[key]=value;}
     35 });