|
- import {chromium,expect} from '@playwright/test';
- import assert from 'node:assert/strict';
- import fs from 'node:fs';
- import {login,call} from './role-permissions-live.mjs';
- const dir='reports/bridge-model-match-20260914',session=await login('root');
- const fixture=fs.readdirSync(dir).filter(f=>f.startsWith('fixtures-')).flatMap(f=>JSON.parse(fs.readFileSync(dir+'/'+f))).find(f=>f.code==='TASK-VIRTUAL-007');
- const result=await call('tran/v1/teaching/assignments/'+fixture.taskId,session.accessToken);assert.equal(result.status,200);
- const browser=await chromium.launch({channel:'msedge',headless:true,args:['--enable-unsafe-swiftshader']});
- const page=await browser.newPage({viewport:{width:1600,height:1000}}),checks=[],errors=[];
- await page.addInitScript(s=>sessionStorage.setItem('unreal-tran:web:access-token:v1',s.accessToken),session);
- page.on('pageerror',e=>errors.push(e.message));
- const diag=()=>page.evaluate(()=>globalThis.__trainingSceneDiagnostics());
- try{
- // LAN entry exercises the same Gateway-backed preview as localhost.
- await page.goto(`http://192.168.31.168:6180/teaching/virtual-training/preview/${fixture.taskId}`);
- await expect(page.locator('[data-role="loading"]')).toHaveClass(/is-hidden/,{timeout:120000});await page.waitForTimeout(1500);
- const teacher=page.locator('[aria-label="关闭数字教员"]');if(await teacher.isVisible())await teacher.click();
- const initial=await diag();
- const old=initial.bridgeWorkshop.targets.find(t=>t.id==='bridge-old-pump');
- for(const key of ['min','max'])assert.ok(old.worldBounds[key].every((v,i)=>Math.abs(v-initial.bridgeWorkshop.modelBinding.sourceBounds[key][i])<1e-6));
- for(let i=0;i<4;i++){
- const ops=result.data.definitionSnapshot.steps[i].action.mechanism.steps;
- for(let j=0;j<ops.length;j++){
- await page.waitForTimeout(550);
- const response=j===ops.length-1?page.waitForResponse(r=>r.url().includes('/preview/validate')):null;
- if(i===3){
- const d=await diag(),t=d.framing.targetOnScreen;
- assert.ok(t.insideCanvas);assert.deepEqual(t.coveredBy,[]);
- const rect=await page.locator('[data-role="canvas"]').boundingBox();
- await page.mouse.click(rect.x+t.localX,rect.y+t.localY);
- checks.push(`Canvas picking ${ops[j].targetId}`);
- }else await page.locator('[data-role="part-label"]').click();
- if(response)assert.equal((await response).status(),200);
- else await expect.poll(async()=>(await diag()).bridgeWorkshop.operationIndex).toBe(j+1);
- }
- await expect(page.locator('[data-action="next"]')).toBeEnabled();
- if(i<3)await page.locator('[data-action="next"]').click();
- }
- const positions=()=>diag().then(d=>d.bridgeWorkshop.targets.map(t=>[t.id,t.position,t.visible]));
- const before=await positions();
- await page.locator('[data-action="viewer-reset-view"]').click();await page.waitForTimeout(800);
- assert.deepEqual(await positions(),before,'camera reset must preserve dismantled state');
- await page.screenshot({path:`${dir}/TASK-VIRTUAL-007-context.png`});
- checks.push('camera reset preserves actual pump/bolt state');
- await page.reload();await expect(page.locator('[data-role="loading"]')).toHaveClass(/is-hidden/,{timeout:120000});await page.waitForTimeout(1000);
- const reloaded=await diag();assert.deepEqual(reloaded.bridgeWorkshop.modelBinding.sourceBounds,initial.bridgeWorkshop.modelBinding.sourceBounds);
- checks.push('reload preserves source placement');assert.deepEqual(errors,[]);
- fs.writeFileSync(`${dir}/picking.json`,JSON.stringify({pass:true,checks,errors},null,2));
- }catch(e){await page.screenshot({path:`${dir}/picking-failure.png`});fs.writeFileSync(`${dir}/picking-diagnostic.json`,JSON.stringify(await diag(),null,2));fs.writeFileSync(`${dir}/picking.json`,JSON.stringify({pass:false,error:e.message,checks,errors,feedback:await page.locator('.el-message').allTextContents()},null,2));throw e;}
- finally{await browser.close();}
|