訂判斷及所需輸入
假設畫面顯 R1、藏 note,匯出規則只准 id。錯點擊處理把所有來源屬性匯出,連 Private note 也有;更正沿獨立 exportColumns,下載只有 id、R1。
| 情況 | 輸入 JSON |
|---|---|
| 原例測試 | {"exportColumns":["id"]} |
跑所附比較
瀏覽器真正按 Export,讀下載 CSV 串流,再分開核畫面與檔案。紀錄是固定假設文字;不是通用 CSV 解析器或權限授予機制。
| 路徑 | 輸出 JSON |
|---|---|
| 錯誤路徑 | {"csv":"id,note\nR1,Private note","screenNoteVisible":false} |
| 所需路徑 | {"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);}
按邊界依據作判斷
另明訂 id、note 匯出就含 note,畫面藏也一樣;規則未知便停,不靠畫面欄猜。
- 核匯出專用規則
- 真正觸發下載
- 獨立核檔內欄位
匯出規則欠缺,出檔前先停。
| 條件 | 輸入 JSON | 預期輸出 JSON |
|---|---|---|
| 另明准匯出備註 | {"exportColumns":["id","note"]} | {"csv":"id,note\nR1,Private note","screenNoteVisible":false} |
| 匯出規則未知 | {"exportColumns":null} | {"held":true} |
原例畫面藏 note,可證明下載檔沒有它嗎?
查看參考答案
不能,要查真檔案。只有更正的 id-only 規則,才只得 id、R1,沒有 Private note。