Set the decision and its input
The supplied viewing area is390×300. A fixed frame with overflow clip hides Calculate below that area. The corrected scrollable frame lets focus reach Calculate and return to the input. Both actions are needed; nominal document height does not establish reachability inside the frame.
| Case | Input JSON |
|---|---|
| Base test | {"height":300} |
Run the supplied comparison
Browser control rectangles are inspected after actual focus actions. The reduced viewport is supplied test geometry, not evidence that a real device keyboard was opened.
| Path | Output JSON |
|---|---|
| Faulty path | {"buttonReachable":false,"fieldRecoverable":true} |
| Required path | {"buttonReachable":true,"fieldRecoverable":true} |
import assert from 'node:assert/strict';
const smallWhole=(x,max)=>Number.isSafeInteger(x)&&x>=0&&x<=max;
import {createRequire} from 'node:module';
const htmlEscape=s=>String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
async function withPage(action,options={}){
const require=createRequire(import.meta.url);const {chromium}=require('playwright');
const browser=await chromium.launch({headless:true});
try{const context=await browser.newContext(options);const page=await context.newPage();
const requests=[];await page.route('**/*',route=>{requests.push(route.request().url());return route.abort();});
return await action(page,context,requests);
}finally{await browser.close();}
}
const run=async function run(i,corrected=true){
if(!smallWhole(i.height,800)||i.height<200)return {held:true};
return withPage(async page=>{await page.setContent('<style>body{margin:0;overflow:hidden}.frame{position:fixed;inset:0;overflow:'+(corrected?'auto':'clip')+'}.space{height:650px}</style><form class="frame"><label>Memo<input id="field"></label><div class="space"></div><button type="button" id="calculate">Calculate</button></form>');
await page.focus('#calculate');const buttonReachable=await page.evaluate(()=>{const r=document.querySelector('#calculate').getBoundingClientRect();return r.top>=0&&r.bottom<=innerHeight;});
await page.focus('#field');const fieldRecoverable=await page.evaluate(()=>{const r=document.querySelector('#field').getBoundingClientRect();return r.top>=0&&r.bottom<=innerHeight;});return {buttonReachable,fieldRecoverable};
},{viewport:{width:390,height:i.height}});
};
const cases=[{"input":{"height":300},"corrected":false,"expected":{"buttonReachable":false,"fieldRecoverable":true}},{"input":{"height":300},"corrected":true,"expected":{"buttonReachable":true,"fieldRecoverable":true}},{"input":{"height":240},"corrected":true,"expected":{"buttonReachable":true,"fieldRecoverable":true}},{"input":{"height":null},"corrected":true,"expected":{"held":true}}];
for(const test of cases){const actual=await run(test.input,test.corrected);assert.deepEqual(actual,test.expected);console.log(actual);}
Choose from the boundary evidence
A240-pixel-high boundary retains the same path. Missing visible height is held rather than guessed.
- Use the supplied visible area
- Focus the required action
- Return to the input
Obtain missing viewport observations before claiming mobile access.
| Condition | Input JSON | Expected output JSON |
|---|---|---|
| smaller supplied viewport | {"height":240} | {"buttonReachable":true,"fieldRecoverable":true} |
| visible viewport unknown | {"height":null} | {"held":true} |
What must the repaired base observation show?
Show the worked answer
Calculate becomes visible after focus, and the field is recoverable afterward. A clipped offscreen action does not satisfy the task.