No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

84 líneas
4.6 KiB

  1. import assert from 'node:assert/strict'
  2. import test from 'node:test'
  3. const webSource = new URL('../../unreal_tran_web/src/features/', import.meta.url)
  4. const fox = {
  5. sceneId: 'fox-scene-object', name: 'Fox', semantic: '实训装备',
  6. operable: true, interactionId: 'scene:fox', capabilities: ['select', 'inspect'],
  7. modelPartTargets: [{
  8. sceneId: 'fox-scene-object', interactionId: 'scene:fox/part/mesh',
  9. sourceInteractionId: 'model:fox-mesh', editorId: 'fox-mesh', name: 'Fox mesh',
  10. operable: true, visible: true, capabilities: ['select', 'inspect'],
  11. }],
  12. }
  13. const projectWith = objects => ({
  14. scenario: {
  15. publishedSceneId: 'content-scene-160',
  16. sceneResource: { sceneId: 'content-scene-160', snapshot: { objects } },
  17. },
  18. })
  19. for (const runtime of ['guide-legacy/demo-src', 'virtual-training-legacy/upstream']) {
  20. const {
  21. TRAINING_PROJECT_TARGETS, createTrainingProject, getTrainingProjectTargets,
  22. listTrainingSceneTargets, normalizeTrainingProject, validateTrainingProject,
  23. } = await import(new URL(`${runtime}/training-project-io.js`, webSource))
  24. test(`${runtime}: binding a published scene replaces all demo-machine targets`, () => {
  25. assert.deepEqual(getTrainingProjectTargets(projectWith([fox])).map(item => item.id), ['scene:fox', 'scene:fox/part/mesh'])
  26. assert.deepEqual(getTrainingProjectTargets(projectWith([])), [])
  27. assert.equal(getTrainingProjectTargets({}).length, TRAINING_PROJECT_TARGETS.length)
  28. const reservedId = TRAINING_PROJECT_TARGETS[0].id
  29. assert.deepEqual(getTrainingProjectTargets(projectWith([{ ...fox, interactionId: reservedId, modelPartTargets: [] }])).map(item => item.id), [reservedId])
  30. })
  31. test(`${runtime}: hidden and deleted roots exclude their parts and split children`, () => {
  32. for (const disabled of [{ visible: false }, { deleted: true }, { softDeleted: true }]) {
  33. const root = { ...fox, ...disabled, splitParts: [{ ...fox, sceneId: 'split', interactionId: 'scene:split' }] }
  34. assert.deepEqual(listTrainingSceneTargets({ objects: [root] }), [])
  35. const normalized = normalizeTrainingProject({ ...createTrainingProject(), ...projectWith([root]) })
  36. assert.deepEqual(getTrainingProjectTargets(normalized), [])
  37. assert.equal(normalized.scenario.sceneResource.snapshot.objects[0].visible, false)
  38. }
  39. })
  40. test(`${runtime}: part visibility and soft-delete overrides keep only the valid root`, () => {
  41. for (const disabled of [{ visible: false }, { deleted: true }, { softDeleted: true }]) {
  42. const root = { ...fox, modelPartTargets: [{ ...fox.modelPartTargets[0], ...disabled }] }
  43. assert.deepEqual(listTrainingSceneTargets({ objects: [root] }).map(item => item.id), ['scene:fox'])
  44. }
  45. const root = { ...fox, partOverrides: { 'scene:fox/part/mesh': { softDeleted: true } } }
  46. assert.deepEqual(listTrainingSceneTargets({ objects: [root] }).map(item => item.id), ['scene:fox'])
  47. })
  48. test(`${runtime}: formal semantic target ids follow backend operable/visible/deleted rules`, () => {
  49. const formal = {
  50. id: 'fox-formal', name: 'Fox',
  51. semantic: { operable: true, interactionId: 'scene:formal-fox', deviceId: 'FOX-001', capabilities: ['inspect'] },
  52. }
  53. const objects = [formal,
  54. { ...formal, id: 'hidden', visible: false },
  55. { ...formal, id: 'deleted', deleted: true },
  56. { id: 'not-operable', semantic: { interactionId: 'scene:locked', operable: false } },
  57. { id: 'missing-id', semantic: { operable: true } },
  58. ]
  59. const targets = listTrainingSceneTargets({ objects })
  60. assert.deepEqual(targets.map(item => item.id), ['scene:formal-fox'])
  61. assert.deepEqual(targets[0].modes, ['inspect'])
  62. assert.equal(targets[0].targetRef.deviceId, 'FOX-001')
  63. const normalized = normalizeTrainingProject({ ...createTrainingProject(), ...projectWith(objects) })
  64. assert.deepEqual(getTrainingProjectTargets(normalized).map(item => item.id), ['scene:formal-fox'])
  65. })
  66. test(`${runtime}: old demo steps stay invalid after binding, then real scene selections validate`, () => {
  67. const source = { ...createTrainingProject(), ...projectWith([fox]) }
  68. const invalid = validateTrainingProject(source)
  69. assert.ok(invalid.errors.some(item => item.path?.endsWith('.targetId')))
  70. source.steps = [{ ...source.steps[0], targetId: 'scene:fox', targetRef: { interactionId: 'scene:fox' }, mode: 'inspect' }]
  71. const normalized = normalizeTrainingProject(source)
  72. const result = validateTrainingProject(normalized)
  73. assert.equal(result.errors.some(item => item.path?.endsWith('.targetId')), false)
  74. assert.equal(normalized.steps[0].targetRef.sceneObjectId, 'fox-scene-object')
  75. })
  76. }