Set the decision and its input
The synthetic screen hides note while showing R1. Its export rule permits id only. A faulty click handler exports every source property, including Private note. The corrected handler uses the independently supplied exportColumns and downloads id/R1 only.
| Case | Input JSON |
|---|---|
| Base test | {"exportColumns":["id"]} |
Run the supplied comparison
The browser actually clicks Export and reads the downloaded CSV stream. Screen visibility and file content are inspected separately. The record is fixed synthetic text; this is not a general CSV parser or permission authority.
| Path | Output JSON |
|---|---|
| Faulty path | {"csv":"id,note\nR1,Private note","screenNoteVisible":false} |
| Required path | {"csv":"id\nR1","screenNoteVisible":false} |
import assert from 'node:assert/strict';
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(i.exportColumns===null)return {held:true};
return withPage(async page=>{await page.setContent('<table><tr><td>R1</td><td style="display:none">Private note</td></tr></table><button id="export">Export</button>');
await page.evaluate(({corrected,exportColumns})=>{document.querySelector('#export').addEventListener('click',()=>{
const record={id:'R1',note:'Private note'},columns=corrected?exportColumns:Object.keys(record);
const csv=columns.join(',')+'\n'+columns.map(k=>record[k]).join(',');const a=document.createElement('a');a.href=URL.createObjectURL(new Blob([csv],{type:'text/csv'}));a.download='synthetic-export.csv';a.click();setTimeout(()=>URL.revokeObjectURL(a.href),1000);
});},{corrected,exportColumns:i.exportColumns});
const downloaded=page.waitForEvent('download');await page.click('#export');const download=await downloaded;const stream=await download.createReadStream();const chunks=[];for await(const chunk of stream)chunks.push(chunk);
return {csv:Buffer.concat(chunks).toString('utf8'),screenNoteVisible:await page.locator('td').nth(1).isVisible()};
});
};
const cases=[{"input":{"exportColumns":["id"]},"corrected":false,"expected":{"csv":"id,note\nR1,Private note","screenNoteVisible":false}},{"input":{"exportColumns":["id"]},"corrected":true,"expected":{"csv":"id\nR1","screenNoteVisible":false}},{"input":{"exportColumns":["id","note"]},"corrected":true,"expected":{"csv":"id,note\nR1,Private note","screenNoteVisible":false}},{"input":{"exportColumns":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
A separate explicit id/note export rule includes note despite screen hiding. Unknown export policy is held, not inferred from UI columns.
- Read the export-specific policy
- Trigger the actual download
- Inspect its fields independently
Hold an absent export policy before releasing a file.
| Condition | Input JSON | Expected output JSON |
|---|---|---|
| separately authorised note export | {"exportColumns":["id","note"]} | {"csv":"id,note\nR1,Private note","screenNoteVisible":false} |
| export policy unknown | {"exportColumns":null} | {"held":true} |
Does hiding note prove the base downloaded file omits it?
Show the worked answer
No. Inspect the real file. Only the corrected id-only policy produces id followed by R1 without Private note.