/** Run in the Cocos Game View; uses local text fixtures and never requests remote content. */ export async function verifyNoticeTabsPreview(e,boardId) { const checks=[],assert=(value,message)=>{if(!value)throw Error(message);checks.push(message);}; const load=id=>new Promise((resolve,reject)=>e.assetManager.loadAny(id,(err,a)=>err?reject(err):resolve(a))); const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms)); const asset=await load(boardId),root=e.instantiate(asset);root.parent=e.director.getScene(); const host=new e.Node('NoticeFlowVerification');host.parent=e.director.getScene(); let panel; try { assert(root.children.length===1&&root.children[0].name==='group-12','standalone prefab contains only group-12'); const view=root.getChildByPath('group-12/NoticeTabs').getComponent('NoticeTabsView'); assert(view&&view.tabs.length===3,'three native tabs are serialized'); assert(view.getComponent(e.ToggleContainer)?.allowSwitchOff===false,'container enforces single selection'); const selected=[];let release=view.bindPages([true,true,true],index=>selected.push(index));await sleep(60); const state=index=>{ assert(view.tabs.every((tab,i)=>tab.isChecked===(i===index)),'exactly the selected tab is checked'); assert(view.backgrounds.every((s,i)=>s.spriteFrame.name===(i===index?'00216_1':'00216_2')),'backgrounds follow original selected frames'); assert(view.titles.every((s,i)=>s.spriteFrame.name==='00217_'+(i*2+(i===index?2:1))),'titles follow original selected frames'); }; state(0);assert(selected.join(',')==='0','opening shows first page once'); view.tabs[1].node.emit(e.Button.EventType.CLICK);state(1);assert(selected.at(-1)===1,'native click selects second content page'); view.tabs[2].node.emit(e.Button.EventType.CLICK);state(2);assert(selected.at(-1)===2,'native click selects third content page'); view.tabs[2].node.emit(e.Button.EventType.CLICK);state(2); release();const count=selected.length;view.tabs[0].node.emit(e.Button.EventType.CLICK);assert(selected.length===count,'released callback does not run'); release=view.bindPages([true,false,true],index=>selected.push(index));await sleep(60);state(0); assert(!view.tabs[1].node.active,'empty second page hides its entire tab'); const first=view.tabs[0].node,third=view.tabs[2].node; assert(Math.abs(first.position.y-third.position.y-first.getComponent(e.UITransform).height-view.getComponent(e.Layout).spacingY)<.1,'hidden middle tab leaves no layout gap'); view.tabs[2].node.emit(e.Button.EventType.CLICK);state(2);assert(selected.at(-1)===2,'hidden tab does not change page identity');release(); const startup=await load('1c10c2ee-adc2-496f-9005-d3e0e6ebbb56'),refs=startup.scene.getComponentInChildren('LobbyAssets'); assert(refs.noticeBoard.uuid===boardId,'startup references the standalone board'); assert(refs.ownedRoomList.data.getChildByName('group-98')&&refs.qrCode.data.getChildByName('group-42'),'independent room list and QR page remain wired'); assert(!refs.qrCode.data.getChildByName('group-12'),'QR prefab does not duplicate group-12'); const LobbyPanel=Array.from(System.entries()).map(([,module])=>module).find(module=>module.LobbyPanel)?.LobbyPanel; assert(LobbyPanel,'LobbyPanel module is available');panel=Object.create(LobbyPanel.prototype); panel.assets={noticeBoard:asset};panel.model={canAct:true};panel.disposed=false;panel.modal=null;panel.modalReleases=[]; panel.policy={notices:[{type:0,text:'第一页',image:'',url:''},{type:0,text:'',image:'',url:''},{type:0,text:'第三页',image:'',url:''}]}; panel.close=()=>{for(const off of panel.modalReleases.splice(0))off();panel.modal?.destroy();panel.modal=null;panel.modalKind='';}; panel.open=(prefab,kind)=>{panel.close();panel.modal=e.instantiate(prefab);panel.modal.parent=host;panel.modalKind=kind;return panel.modal;}; panel.openNotice();await sleep(60); const board=panel.modal,g=board.getChildByName('group-12'),actual=g.getChildByName('NoticeTabs').getComponent('NoticeTabsView'); const text=g.getChildByPath('NoticeViewport/NoticeContent/通知内容').getComponent(e.Label); assert(text.string==='第一页','actual notice entry renders page one'); actual.tabs[2].node.emit(e.Button.EventType.CLICK);assert(text.string==='第三页','actual tab event renders matching content'); assert(!actual.tabs[1].node.active,'actual entry uses source visibility rules'); g.getChildByName('通知关闭').emit(e.Button.EventType.CLICK);assert(panel.modal===null,'close button closes independent board'); panel.openNotice();await sleep(40); assert(panel.modal.getChildByPath('group-12/NoticeTabs').getComponent('NoticeTabsView').tabs[0].isChecked,'reopening resets selection'); // Route coordinate touches through Cocos hit testing, including the background behind controls. root.active=false; const canvas=e.director.getScene().getComponentInChildren(e.Canvas); const mount=async()=>{panel.openNotice();panel.modal.parent=canvas.node;panel.modal.setPosition(0,0,0);const widget=panel.modal.getComponent(e.Widget);widget.target=canvas.node;widget.updateAlignment();await sleep(70);}; let touchId=100; const tap=async(node,dx=0,dy=0)=>{ const position=node.worldPosition.clone();position.x+=dx;position.y+=dy; const screen=canvas.cameraComponent.worldToScreen(position),touch=new e.Touch(screen.x,screen.y,touchId++); for(const type of [e.Input.EventType.TOUCH_START,e.Input.EventType.TOUCH_END])e.input._dispatchEventTouch(new e.EventTouch([touch],false,type,[touch])); await sleep(25); }; await mount();let surface=panel.modal.getChildByName('group-12'); await tap(surface.getChildByName('通知背景'),-350,-200);assert(panel.modal!==null,'panel blank area does not close the board'); await tap(surface.getChildByName('通知标题内容'));assert(panel.modal!==null,'title does not close the board'); await tap(surface.getChildByPath('NoticeViewport/NoticeContent/通知内容'),30,-10);assert(panel.modal!==null,'content does not close the board'); await tap(surface.getChildByPath('NoticeTabs/NoticeTab3'));assert(panel.modal!==null&&surface.getChildByPath('NoticeTabs').getComponent('NoticeTabsView').tabs[2].isChecked,'coordinate tab touch selects without closing'); await tap(surface.getChildByName('通知关闭'));assert(panel.modal===null,'coordinate close-button touch closes the board'); await mount();surface=panel.modal.getChildByName('group-12'); await tap(surface.getChildByName('通知遮罩'),-700,0);assert(panel.modal===null,'coordinate backdrop touch closes the board'); panel.close();return {checks}; } finally {panel?.close();root.destroy();host.destroy();} }