t32-view-layer-flow.mjs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import assert from 'node:assert/strict'
  2. import { register } from 'node:module'
  3. import { readFile } from 'node:fs/promises'
  4. register('./t32-adapter-io-loader.mjs',import.meta.url)
  5. const { JulianDate }=await import('cesium')
  6. const {syncPipeLayer,setPipeViewMode,clearPipeLayer}=await import('../../../src/modules/cockpit/services/cesiumPipeLayer.js')
  7. let modelLoaded
  8. const modelCreated=new Promise(resolve=>modelLoaded=resolve)
  9. globalThis.t32Models=[]
  10. globalThis.t32Models.push=function(model){Array.prototype.push.call(this,model);modelLoaded()}
  11. globalThis.t32TerrainFails=false
  12. const nativeFetch=globalThis.fetch
  13. globalThis.window={location:{href:'http://test.invalid/cockpit/',origin:'http://test.invalid'}}
  14. const sources=[]
  15. const viewer={terrainProvider:{},isDestroyed:()=>false,scene:{requestRender(){},primitives:{add(){},remove(m){m.destroy()}}},dataSources:{getByName:n=>sources.filter(s=>s.name===n),add:async s=>{sources.push(s);return s}}}
  16. try{
  17. globalThis.fetch=async url=>String(url).startsWith('blob:')?nativeFetch(url):new Response(await readFile(new URL('../../../public/cockpit/models/pipes/spline.gltf',import.meta.url),'utf8'))
  18. const pipe={code:'async',industry:'DRAINAGE',networkLevel:1,diameter:400,positions:[[110.39,28.44],[110.3901,28.44]]}
  19. let finish
  20. const loaded=new Promise(resolve=>finish=resolve)
  21. const states=[]
  22. setPipeViewMode(viewer,'pipeline')
  23. const syncing=syncPipeLayer(viewer,{pipes:[pipe],components:[]},{onModelChange:s=>{states.push(s);if(s.pending===1)finish()}})
  24. setPipeViewMode(viewer,'ground')
  25. await syncing;await loaded;await modelCreated;await new Promise(setImmediate)
  26. const graphics=()=>sources[0].entities.getById('pipe:async').polyline
  27. const near=()=>graphics().distanceDisplayCondition.getValue(JulianDate.now()).near
  28. assert.equal(near(),0)
  29. globalThis.t32Models[0].readyEvent.raiseEvent()
  30. assert.equal(near(),0,'late readiness must use latest ground mode')
  31. assert.equal(states.at(-1).visualDefaultCount,0)
  32. setPipeViewMode(viewer,'pipeline');assert.equal(near(),600)
  33. const previous=graphics()
  34. await syncPipeLayer(viewer,{pipes:[{...pipe,name:'metadata changed'}],components:[]})
  35. assert.notEqual(graphics(),previous)
  36. assert.equal(near(),600,'replacement graphics retains underground-only distance rule')
  37. setPipeViewMode(viewer,'ground');assert.equal(near(),0)
  38. assert.equal(globalThis.t32Models.length,1)
  39. globalThis.t32Models[0].errorEvent.raiseEvent(new Error('late asset error'))
  40. assert.equal(near(),0)
  41. setPipeViewMode(viewer,'pipeline');assert.equal(near(),0,'failed model never suppresses near guide')
  42. await clearPipeLayer(viewer)
  43. assert.equal(sources[0].entities.values.length,0)
  44. console.log('PASS real layer: async mode change, readiness, metadata replacement, failure and clear')
  45. }finally{globalThis.fetch=nativeFetch}