const {chromium}=require(process.env.PLAYWRIGHT_MODULE||'playwright');const fs=require('fs'); (async()=>{const browser=await chromium.launch({channel:'chrome',headless:true}),page=await browser.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message)); 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:'测试学员'}}))); 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}))})); 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=[]; await page.route('**/*',r=>['127.0.0.1','localhost'].includes(new URL(r.request().url()).hostname)?r.continue():r.abort()); await page.route('**/cloud-functions/**',async r=>{const p=r.request().postDataJSON()?.params||{};let result=[]; if(p.action==='e_order_detail')result=[order]; 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}; if(p.action==='e_record_detail')result=batches.flatMap(b=>b.words); 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()}; if(p.action==='app_lesson_courses')result={items:[{bindingId:'binding',kcid:161,Title:'初中词库'}]}; if(p.action==='app_live_versions')result={version:'fixture',scopeVersions:{},syncStatus:{state:'current'}}; 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};} await r.fulfill({json:{retcode:0,result,...(p.action==='e_record_detail'?{addon:[order]}:{})}});}); const out='docs/qa/lesson-study-batches-2026-10-13'; 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');} 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'); 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');} await page.setViewportSize({width:375,height:812}); 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');} 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)});