|
- import { chromium, expect } from '@playwright/test';
- import fs from 'node:fs';
- import assert from 'node:assert/strict';
- import crypto from 'node:crypto';
- import { login, call } from './role-permissions-live.mjs';
- import { scripts, scriptDefinition } from '../../unreal_tran_web/src/features/virtual-training-scripts/definition.js';
- import { verifyVisualEffects } from './bridge-three-dimensional-assertions.mjs';
-
- const dir='reports/bridge-three-dimensional-20260913';fs.mkdirSync(dir,{recursive:true});
- const session=await login('root'), fixtures=[], checks=[], errors=[];
- const api=async(path,data,method)=>{const r=await call(path,session.accessToken,data,method);assert.equal(r.status,200,`${path}: ${r.message}`);return r.data;};
- const fixtureFile=`${dir}/fixtures-${Date.now()}.json`;
- const saveFixtures=()=>fs.writeFileSync(fixtureFile,JSON.stringify(fixtures,null,2));
- const browser=await chromium.launch({channel:'msedge',headless:true,args:['--enable-unsafe-swiftshader']});
- const page=await browser.newPage({viewport:{width:1600,height:1000}});
- await page.addInitScript(s=>sessionStorage.setItem('unreal-tran:web:access-token:v1',s.accessToken),session);
- page.on('pageerror',e=>errors.push(e.message));
- const waitReady=async()=>{await expect(page.locator('[data-role="loading"]')).toHaveClass(/is-hidden/,{timeout:120000});await page.waitForFunction(()=>globalThis.__trainingSceneDiagnostics()?.bridgeWorkshop?.targets.length>0);await page.waitForTimeout(1800);};
- try {
- for(const script of scripts.filter(s=>s.version==='3' && (!process.env.BRIDGE_CODE || process.env.BRIDGE_CODE===s.code))) {
- const content=await api('tran/v1/content/projects',{type:'TRAINING',name:`三维验收·${script.title}`,description:'Temporary 3D acceptance fixture',categoryCode:'MAINTENANCE',trainingMode:'VIRTUAL',content:scriptDefinition(script),dependencies:[],assets:[]});
- const fixture={code:script.code,projectId:content.project.id};fixtures.push(fixture);saveFixtures();
- const project=(await api(`tran/v1/content/projects/${fixture.projectId}/publish`,{version:content.project.version})).project;
- let task=await api('tran/v1/teaching/assignments',{code:`CHECK-3D-${Date.now()}-${script.code}`,name:`三维验收·${script.title}`,description:'Temporary acceptance fixture',channel:'VIRTUAL',assignmentKind:'TRAINING',executionMode:'PRACTICE',audienceType:'COMMON',collaborationMode:'INDIVIDUAL',digitalHumanAllowed:false,contentProjectId:project.id,contentVersionId:project.publishedVersionId,members:[]});
- fixture.taskId=task.id;saveFixtures();
- task=await api(`tran/v1/teaching/assignments/${task.id}/publish`,{version:task.version});
- await page.goto(`http://127.0.0.1:6180/teaching/virtual-training/preview/${task.id}`);await waitReady();
- await expect(page.locator('.bridge-procedure')).toHaveCount(0);
- const bar=page.locator('[data-role="model-commandbar"]');
- for(const action of ['toggle-structure-tree','focus-selected-part','viewer-reset-view','toggle-part-labels','toggle-issue-highlight','toggle-hide-others','toggle-explosion'])await expect(bar.locator(`[data-action="${action}"]`)).toBeVisible();
- await page.screenshot({path:`${dir}/${script.code}-start.png`});
- fs.writeFileSync(`${dir}/${script.code}-diagnostic.json`,JSON.stringify(await page.evaluate(()=>globalThis.__trainingSceneDiagnostics()),null,2));
- for(let index=0;index<script.definition.steps.length;index++) {
- const step=script.definition.steps[index];
- await expect(page.locator('[data-role="step-count"]')).toHaveText(`${index+1} / ${script.steps.length}`);
- if(step.mode==='measure'){
- await page.locator('[data-open-preparation]').click();
- await page.locator('[data-measurement]').fill('按原稿连接管路,矛盾描述交教员核对。');
- await page.locator('[data-close-preparation]').click();
- }
- for(let k=0;k<step.action.mechanism.steps.length;k++) {
- const op=step.action.mechanism.steps[k];
- await expect.poll(async()=>page.evaluate(()=>globalThis.__trainingSceneDiagnostics().bridgeWorkshop.operationIndex)).toBe(k);
- if(k===step.action.mechanism.steps.length-1){
- const response=page.waitForResponse(r=>r.url().includes(`/assignments/${task.id}/preview/validate`));
- await page.locator('[data-role="part-label"]').click();
- assert.equal((await response).status(),200);
- }else{
- await page.locator('[data-role="part-label"]').click();
- await expect.poll(async()=>page.evaluate(()=>globalThis.__trainingSceneDiagnostics().bridgeWorkshop.operationIndex)).toBe(k+1);
- }
- await verifyVisualEffects(page,op);
- console.log(script.code,index+1,k+1,op.targetId);
- }
- await expect(page.locator('[data-action="next"]')).toBeEnabled();
- if([1,3,4,7,10,15].includes(index))await page.screenshot({path:`${dir}/${script.code}-step-${index+1}.png`});
- if(index<script.steps.length-1)await page.locator('[data-action="next"]').click();
- }
- assert.equal((await api(`tran/v1/teaching/runs?assignmentId=${task.id}&size=100`)).total,0);
- checks.push(`${script.code}: ${script.steps.length} steps, ${script.definition.steps.flatMap(s=>s.action.mechanism.steps).length} 3D operations; preview server validation passed`);
- fixture.passed=true;saveFixtures();
- }
- assert.deepEqual(errors,[]);
- fs.writeFileSync(`${dir}/acceptance.json`,JSON.stringify({pass:true,checks,errors},null,2));
- } catch(error){
- console.log('Feedback',await page.locator('.el-message').allTextContents());
- await page.screenshot({path:`${dir}/failure.png`}).catch(()=>{});
- fs.writeFileSync(`${dir}/acceptance.json`,JSON.stringify({pass:false,error:error.message,checks,errors},null,2));throw error;
- }finally{await browser.close();saveFixtures();}
|