browser-check.cjs 5.1 KB

12345678910111213141516171819202122
  1. const {chromium}=require(process.env.PLAYWRIGHT_MODULE||'playwright');const fs=require('fs');
  2. (async()=>{const browser=await chromium.launch({channel:'chrome',headless:true}),page=await browser.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message));
  3. await page.addInitScript(()=>localStorage.setItem('xiaoshu.angular.session',JSON.stringify({token:'r:fixture',user:{userId:30,groupId:3,honeyName:'测试老师'},student:{userId:20,groupId:1,honeyName:'测试学员'}})));
  4. const batches=[9,5,3].map((count,index)=>({batchId:'round-'+index,version:1,status:index<2?'confirmed':'draft',bindingId:'binding',courseName:'初中词库',words:Array.from({length:count},(_,i)=>({GeneralID:index*100+i+1,Title:'word'+index+'-'+i,nodeId:172+index,nodeName:['七年级','八年级','九年级'][index],check:index<2?1:0}))}));
  5. const order={GeneralID:901,szyh:20,pl:30,dszt:10,HoneyName:'测试学员',bindingId:'binding',kcid:161,allowedActions:['continue','complete'],updatedAt:new Date().toISOString()};let failSave=true,saves=0;const keys=[];
  6. await page.route('**/*',r=>['127.0.0.1','localhost'].includes(new URL(r.request().url()).hostname)?r.continue():r.abort());
  7. await page.route('**/cloud-functions/**',async r=>{const p=r.request().postDataJSON()?.params||{};let result=[];
  8. if(p.action==='e_order_detail')result=[order];
  9. if(p.action==='app_lesson_study')result={record:{learned:batches.filter(b=>b.status==='confirmed').reduce((n,b)=>n+b.words.length,0)},batches,pending:batches.filter(b=>b.status==='draft').length};
  10. if(p.action==='e_record_detail')result=batches.flatMap(b=>b.words);
  11. if(p.action==='app_lesson_report')result={order,feedback:{contentSummary:'三个单元的词汇学习',trainingSummary:'累计17词'},records:[{learned:17,ygg:17,con:'本节累计学习17个单词'}],antiForget:{total:10,completed:0},refreshedAt:new Date().toISOString()};
  12. if(p.action==='app_lesson_courses')result={items:[{bindingId:'binding',kcid:161,Title:'初中词库'}]};
  13. if(p.action==='app_live_versions')result={version:'fixture',scopeVersions:{},syncStatus:{state:'current'}};
  14. if(p.action==='stu_record_update_v2'){keys.push(p.requestKey);if(failSave){failSave=false;return r.fulfill({status:503,json:{retcode:-1,retmsg:'隔离断网测试'}});}const b=batches.find(b=>b.batchId===p.batchId);b.words=JSON.parse(p.addon).xxqs.map(w=>({...b.words.find(old=>String(old.GeneralID)===String(w.GeneralID)),...w}));b.status='confirmed';b.version++;saves++;result={GeneralID:9901,batchVersion:b.version,learned:17};}
  15. await r.fulfill({json:{retcode:0,result,...(p.action==='e_record_detail'?{addon:[order]}:{})}});});
  16. const out='docs/qa/lesson-study-batches-2026-10-13';
  17. for(const width of [375,812]){await page.setViewportSize({width,height:812});await page.goto('http://127.0.0.1:4200/pages/stu/pl_end?orderId=901&bindingId=binding&batchId=round-2');await page.getByRole('button',{name:'保存并继续选词'}).waitFor();if(await page.getByRole('button',{name:'全部掌握',exact:true}).count())await page.getByRole('button',{name:'全部掌握',exact:true}).click();await page.screenshot({path:out+'/round-'+width+'.png',fullPage:true});if(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth))throw Error('round overflow');}
  18. await page.getByRole('button',{name:'保存并继续选词'}).click();await page.getByText('请求暂未完成,请检查网络后重试;已填写内容会保留。',{exact:true}).waitFor();if(!page.url().includes('/pl_end'))throw Error('failed save left page');await page.getByRole('button',{name:'保存并继续选词'}).click();await page.getByRole('heading',{name:'本节学习成果 · 17 个词'}).waitFor();if(saves!==1||keys.length!==2||keys[0]!==keys[1])throw Error('retry mismatch');
  19. for(const width of [375,812]){await page.setViewportSize({width,height:812});await page.screenshot({path:out+'/summary-'+width+'.png',fullPage:true});if(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth))throw Error('summary overflow');}
  20. await page.setViewportSize({width:375,height:812});
  21. for(const [route,name] of [['/pages/his/his_words?id=9901','history'],['/pages/shop/baobiao?id=901','report']]){await page.goto('http://127.0.0.1:4200'+route);const sources=page.getByLabel('课堂词表来源');await sources.waitFor();const label=await sources.innerText();for(const part of ['七年级 9','八年级 5','九年级 3','17'])if(!label.includes(part))throw Error('missing source '+part);await page.screenshot({path:out+'/'+name+'-375.png',fullPage:true});if(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth))throw Error(name+' overflow');}
  22. if(errors.length)throw Error(errors.join('\n'));const diagnostics=await page.evaluate(()=>JSON.parse(sessionStorage.getItem('xiaoshu.safe-diagnostics.v1')||'[]'));if(diagnostics.some(d=>d.kind==='runtime'))throw Error('Angular error');fs.writeFileSync(out+'/browser-result.json',JSON.stringify({viewports:[375,812],confirmedWords:17,historyAndReportSources:[9,5,3],saves,retrySameKey:true,pageErrors:errors},null,2));await browser.close();console.log('Browser batch confirmation, offline retry, summary and responsive checks passed');})().catch(e=>{console.error(e);process.exit(1)});