import fs from 'node:fs'; import assert from 'node:assert/strict'; import {chromium,expect} from '@playwright/test'; import {login,call} from './role-permissions-live.mjs'; const dir='reports/bridge-tools-authoring-20260924';fs.mkdirSync(dir,{recursive:true}); const fixture=JSON.parse(fs.readFileSync('reports/bridge-content-authoring-20260924/fixture.json','utf8')); const session=await login('root'),checks=[],errors=[]; const browser=await chromium.launch({channel:'msedge',headless:true,args:['--enable-unsafe-swiftshader']}); const page=await browser.newPage({viewport:{width:1440,height:1000}}); await page.addInitScript(s=>{sessionStorage.setItem('unreal-tran:web:access-token:v1',s.accessToken);sessionStorage.setItem('unreal-tran:web:refresh-token:v1',s.refreshToken);localStorage.setItem('unreal-tran:web:preferences:v1',JSON.stringify({themeMode:'light'}));},session); page.on('pageerror',e=>errors.push(e.message)); const api=async ep=>{const r=await call('tran/v1/'+ep,session.accessToken);assert.equal(r.status,200);return r.data;}; const ready=()=>expect(page.getByRole('button',{name:'播放动作',exact:true})).toBeEnabled({timeout:120000}); try{ const before=new Map();for(const item of fixture.items)before.set(item.taskId,(await api('teaching/assignments/'+item.taskId)).definitionSnapshot); for(const item of fixture.items){ if(process.env.PREVIEW_ONLY==='1'&&!['88','89'].includes(item.taskId))continue; await page.goto('http://127.0.0.1:6180/content/models/'+item.modelProjectId+'/production');await ready(); const model=await api('content/projects/'+item.modelProjectId),actions=model.currentVersion.content.productionActions; const chosen=actions.findIndex(a=>/bolt-1$/.test(a.targetId)); await page.locator('.production-action-item').nth(Math.max(0,chosen)).click(); await expect(page.getByText('学员操作',{exact:true})).toBeVisible(); if(chosen>=0){ await expect(page.getByText('所需工具',{exact:true})).toBeVisible(); await expect(page.getByText('工具作用部件',{exact:true})).toBeVisible(); await page.getByRole('button',{name:'播放动作',exact:true}).click();await page.waitForTimeout(600); await page.screenshot({path:dir+'/'+item.taskCode+'-tool-preview.png'});await ready(); } if(process.env.PREVIEW_ONLY==='1'){checks.push({task:item.taskCode,preview:true});continue;} // Publish only the authoring chain. The existing task points at its old fixed // snapshot; the assertion below protects all four active simulations. await page.getByRole('button',{name:'发布并进入场景',exact:true}).click();await expect(page).toHaveURL(new RegExp('/scenes/'+item.sceneProjectId+'/production'));await ready(); await page.getByRole('button',{name:'发布并进入编排',exact:true}).click();await expect(page).toHaveURL(new RegExp('/training-projects/'+item.trainingProjectId+'/production'));await ready(); await page.getByRole('button',{name:'发布训练内容',exact:true}).click();await expect(page.getByText('训练内容已发布;现有仿真仍保持固定版本')).toBeVisible(); const training=await api('content/projects/'+item.trainingProjectId); const bindings=training.currentVersion.content.steps.flatMap(s=>s.modelActions||[]); assert.equal(bindings.length,item.actions);assert.ok(bindings.every(a=>a.toolAction&&a.toolAction.trigger)); if(chosen>=0)assert.ok(bindings.some(a=>a.toolAction.trigger==='tool-drop')); await page.screenshot({path:dir+'/'+item.taskCode+'-training.png'}); checks.push({task:item.taskCode,bindings:bindings.length,modelProject:item.modelProjectId,sceneProject:item.sceneProjectId,trainingProject:item.trainingProjectId,version:training.project.publishedVersionId}); console.log(item.taskCode+' authoring tools published'); } for(const item of fixture.items)assert.deepEqual((await api('teaching/assignments/'+item.taskId)).definitionSnapshot,before.get(item.taskId),'fixed simulation unchanged'); assert.deepEqual(errors,[]);fs.writeFileSync(dir+(process.env.PREVIEW_ONLY==='1'?'/preview-result.json':'/result.json'),JSON.stringify({pass:true,checks,errors,existingTasksUnchanged:true},null,2)); }catch(error){await page.screenshot({path:dir+'/failure.png'}).catch(()=>{});fs.writeFileSync(dir+'/result.json',JSON.stringify({pass:false,error:error.message,checks,errors},null,2));throw error;}finally{await browser.close();}