evaluation-layout-probe.mjs (4317B)
1 // Uses the actual selected runtime and page actions; no mocked evaluator. 2 const el=id=>document.getElementById(id),assert=(ok,message)=>{if(!ok)throw Error(message);}; 3 const frame=()=>new Promise(r=>requestAnimationFrame(()=>requestAnimationFrame(r))); 4 const delay=ms=>new Promise(r=>setTimeout(r,ms)); 5 const change=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('change'));}; 6 const input=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('input'));}; 7 async function wait(status){const end=Date.now()+45000;while(el('status').textContent!==status){if(Date.now()>end)throw Error('Waiting for '+status+': '+el('status').textContent);await delay(20);}await frame();} 8 export async function evaluationLayout(){ 9 const dock=document.querySelector('.expression-dock'),panel=document.querySelector('.output-panel'); 10 assert(dock.contains(el('run'))&&dock.contains(el('stop-run')),'Actions belong to expression dock'); 11 assert(dock.nextElementSibling===panel&&panel.parentElement.classList.contains('editor-main'),'Result immediately follows expression in the same column'); 12 assert(!document.querySelector('.editor-toolbar').contains(el('run')),'Evaluate is not a distant sticky action'); 13 change('output-target','result');change('mode','pure');change('output-type','number');input('expression-editor','identity 42'); 14 const mobile=matchMedia('(max-width:740px)').matches; 15 // Start with a result well below the viewport. No user scroll event is emitted. 16 window.scrollTo({top:0,behavior:'instant'});await frame(); 17 const before=scrollY;el('run').click(); 18 assert(!el('stop').hidden&&!el('stop-run').disabled,'Both Stop controls available while running'); 19 await wait('Finished'); 20 assert(el('result').textContent==='42','Actual result appears'); 21 if(mobile){const r=el('result').getBoundingClientRect(),bar=document.querySelector('.editor-toolbar').getBoundingClientRect();assert(r.top>=bar.bottom&&r.top+40<=innerHeight,'Offscreen result start is revealed below sticky toolbar');} 22 else assert(scrollY===before,'Desktop does not auto-scroll'); 23 assert(el('stop').hidden,'Sticky Stop disappears when idle'); 24 // When the result is already visible, repeating an evaluation must stay put. 25 if(!mobile){el('run').scrollIntoView({block:'center',behavior:'instant'});await frame();} 26 const visibleBefore=scrollY;el('run').click();await wait('Finished');assert(Math.abs(scrollY-visibleBefore)<=1,'Visible result does not jump'); 27 window.scrollTo({top:0,behavior:'instant'});await frame();el('run').click();window.dispatchEvent(new Event('wheel'));await wait('Finished');assert(scrollY===0,'Deliberate browsing cancels pending reveal'); 28 // Stored definitions share the nearby action without displaying irrelevant input. 29 change('output-target','definition');change('export','leaf');change('output-type','tricu'); 30 assert(el('expression-inputs').hidden&&el('guided-inputs').hidden&&el('run').textContent==='Show definition','Stored target hides expression input'); 31 el('run').click();await wait('Ready');assert(el('result').textContent==='t','Stored definition action still works'); 32 change('output-target','result');assert(!el('expression-inputs').hidden,'Expression returns for evaluation'); 33 input('expression-editor','unknownNameForLayout');el('run').click();await wait('Stopped'); 34 assert(el('result').classList.contains('error'),'Explicit evaluation diagnostics use the same result surface'); 35 // First IO event reveals once; later input/output/completion never follows it. 36 change('mode','io');change('output-type','tricu');input('expression-editor','t "tricuIO" (t 1 (t 11 (line : t "tricuIO" (t 1 (t 0 t)))))'); 37 el('run').click();await wait('Waiting for input'); 38 assert(document.activeElement!==el('line-input'),'IO does not force focus or open the keyboard'); 39 window.scrollTo({top:0,behavior:'instant'});await frame();input('line-input','hello');el('input-form').requestSubmit();await wait('Finished');assert(scrollY===0,'IO completion does not scroll again'); 40 // Idle compilation has no reveal authority. 41 change('mode','pure');window.scrollTo({top:0,behavior:'instant'});await frame();input('source-editor','answer = t');await wait('Compiled');assert(scrollY===0,'Idle compilation leaves the viewport alone'); 42 change('program-picker','demo:language-reference');await wait('Ready'); 43 }