| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- import {chromium} from 'file:///C:/Users/JSHY/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright/index.mjs';
- import fs from 'node:fs/promises';
- import assert from 'node:assert/strict';
- const base='http://127.0.0.1:4183';
- const out='docs/development-board-20261108';
- await fs.mkdir(out,{recursive:true});
- const browser=await chromium.launch({executablePath:'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe',headless:true});
- const report={ok:false,checkedAt:new Date().toISOString(),base,layouts:[],checks:[],pageErrors:[],failedResponses:[],
- realHardware:false,responseOverrides:0,paidCalls:0,productionWrites:0};
- let current;
- const wait=async p=>{
- await p.locator('industry-development .dr-intro').waitFor();
- await p.waitForFunction(async()=>{const p=document.querySelector('kf-app')?.renderRoot.querySelector('view-industry');if(!p||p._loading||!p._data)return false;await p.updateComplete;return !p._error;});
- };
- const dimensions=async(p,width,section)=>{
- const metrics=await p.evaluate(()=>({innerWidth,clientWidth:document.documentElement.clientWidth,scrollWidth:document.documentElement.scrollWidth}));
- assert.equal(metrics.innerWidth,width);assert.ok(metrics.scrollWidth<=metrics.clientWidth,JSON.stringify(metrics));
- const bad=await p.locator('industry-development').evaluate(root=>[...root.renderRoot.querySelectorAll('*')].filter(e=>{
- if(e.closest('dialog:not([open])'))return false;
- const r=e.getBoundingClientRect();return r.width>0&&r.height>0&&(r.left< -1||r.right>document.documentElement.clientWidth+1);
- }).map(e=>({tag:e.tagName,cls:e.className,text:e.textContent.slice(0,60)})).slice(0,10));
- assert.deepEqual(bad,[],section+' '+width);report.layouts.push({width,section,...metrics,outOfBounds:bad.length});
- };
- const check=name=>{report.checks.push(name);console.log('PASS '+name);};
- try{
- for(const [width,height,mobile] of [[1440,900,false],[1024,768,false],[768,1024,false],[430,932,true],[390,844,true],[360,800,true],[320,568,true],[844,390,true]]){
- const context=await browser.newContext({viewport:{width,height},isMobile:mobile,hasTouch:mobile,permissions:['clipboard-read','clipboard-write'],deviceScaleFactor:1});
- const p=await context.newPage();current=p;
- p.on('pageerror',e=>report.pageErrors.push(e.message));
- p.on('response',r=>{if(r.status()>=400)report.failedResponses.push({url:r.url(),status:r.status()});});
- await p.goto(base+'/industry?tab=development');await wait(p);
- assert.equal(await p.locator('[data-development-direction]').count(),4);
- assert.equal(await p.locator('industry-development blockquote').count(),2);
- if([1440,390,320].includes(width))await p.screenshot({path:out+'/directions-'+width+'.png'});
- for(const tab of ['directions','categories','processes','materials','standards']){
- await p.locator('[data-development-tab='+tab+']').click();
- await dimensions(p,width,tab);
- const counts={categories:16,processes:3,materials:14,standards:10};
- if(tab==='categories')assert.equal(await p.locator('.dr-axis .dr-category').count(),12);
- if(['processes','materials','standards'].includes(tab))assert.equal(await p.locator('.dr-tab-content [data-reference]').count(),counts[tab]);
- if([1440,390].includes(width)&&['categories','materials','standards'].includes(tab))await p.screenshot({path:out+'/'+tab+'-'+width+'.png'});
- }
- await p.locator('[data-development-tab=materials]').click();
- await p.locator('[data-material-group="营养强化"]').click();assert.equal(await p.locator('.dr-material-grid>.dr-card').count(),2);
- await p.locator('[data-reference="fortifier-维生素B1"]').click();
- await p.locator('.dr-detail[open]').waitFor();assert.match(await p.locator('.dr-detail').innerText(),/没有核实目标食品类别/);
- await dimensions(p,width,'source-dialog');
- await p.locator('[data-close-reference]').click();
- await p.locator('[data-material-group="全部"]').click();
- await p.getByPlaceholder('搜索原料或作用').fill('硫胺素');assert.equal(await p.locator('.dr-material-grid>.dr-card').count(),1);
- await p.getByPlaceholder('搜索原料或作用').fill('无此原料');assert.equal(await p.locator('.dr-material-grid>.dr-card').count(),0);
- assert.match(await p.locator('.dr-empty').innerText(),/没有匹配/);
- await p.locator('[data-development-tab=directions]').click();
- for(const id of ['spice','texture','nutrition','seasoning']){
- await p.locator('[data-development-direction='+id+']').click();
- assert.equal(await p.locator('industry-development blockquote').count(),id==='nutrition'?0:2);
- await dimensions(p,width,'direction-'+id);
- }
- await p.locator('[data-development-copy]').click();
- const text=await p.evaluate(()=>navigator.clipboard.readText());
- assert.ok(text.includes('KfMaterial/')&&text.includes('KfSource/')&&text.includes('3279276824734890')&&text.includes('待验证设想'));
- await p.locator('.dr-coverage>summary').click();
- assert.match(await p.locator('.dr-coverage').innerText(),/快照/);
- await dimensions(p,width,'coverage');
- if(mobile){
- const controls=p.locator('industry-development button:visible');
- for(let i=0;i<await controls.count();i++){
- const r=await controls.nth(i).boundingBox();assert.ok(r.height>=43.5,'touch target height');
- }
- }
- check('five sections, four directions, references, filter, search, copy and layout '+width);
- if(width===1440){
- await p.locator('industry-development a').filter({hasText:'查看原评'}).first().click();
- await p.waitForURL(/\/library\/reviews\//);
- await p.locator('view-library').waitFor();check('review navigation validates the bound VOC generation');
- }
- await context.close();
- }
- assert.deepEqual(report.pageErrors,[]);assert.deepEqual(report.failedResponses,[]);
- report.ok=true;
- }catch(e){report.error=e.stack;console.error(e);if(current)await current.screenshot({path:out+'/failure.png'}).catch(()=>{});process.exitCode=1;}
- finally{await browser.close();await fs.writeFile(out+'/browser-acceptance.json',JSON.stringify(report,null,2)+'\n');}
|