import { describe, expect, it, vi } from 'vitest' import * as THREE from 'three' import { isolateMeshMaterialsForFocus, restoreIsolatedFocusMaterials } from '@/components/map/focusMaterialIsolation' describe('选中模型材质隔离', () => { it('仅修改选中 Mesh 的克隆材质并在清理时恢复共享引用', () => { const sharedMaterial = new THREE.MeshStandardMaterial({ color: '#ffffff' }) const selectedMesh = new THREE.Mesh(new THREE.BoxGeometry(), sharedMaterial) const siblingMesh = new THREE.Mesh(new THREE.BoxGeometry(), sharedMaterial) const state = isolateMeshMaterialsForFocus(selectedMesh) const selectedMaterial = selectedMesh.material as THREE.MeshStandardMaterial const disposeSpy = vi.spyOn(selectedMaterial, 'dispose') expect(selectedMaterial).not.toBe(sharedMaterial) expect(siblingMesh.material).toBe(sharedMaterial) selectedMaterial.color.set('#e0df00') selectedMaterial.emissive.set('#e0df00') expect(sharedMaterial.color.getHexString()).toBe('ffffff') expect(sharedMaterial.emissive.getHexString()).toBe('000000') expect(siblingMesh.material).toBe(sharedMaterial) restoreIsolatedFocusMaterials(state) expect(selectedMesh.material).toBe(sharedMaterial) expect(disposeSpy).toHaveBeenCalledOnce() selectedMesh.geometry.dispose() siblingMesh.geometry.dispose() sharedMaterial.dispose() }) it('材质数组逐项克隆并完整恢复原数组引用', () => { const materials = [ new THREE.MeshBasicMaterial({ color: '#ffffff' }), new THREE.MeshBasicMaterial({ color: '#000000' }) ] const mesh = new THREE.Mesh(new THREE.BoxGeometry(), materials) const state = isolateMeshMaterialsForFocus(mesh) const clonedMaterials = mesh.material as THREE.Material[] const disposeSpies = clonedMaterials.map((material) => vi.spyOn(material, 'dispose')) expect(clonedMaterials).not.toBe(materials) expect(clonedMaterials[0]).not.toBe(materials[0]) expect(clonedMaterials[1]).not.toBe(materials[1]) restoreIsolatedFocusMaterials(state) expect(mesh.material).toBe(materials) disposeSpies.forEach((spy) => expect(spy).toHaveBeenCalledOnce()) mesh.geometry.dispose() materials.forEach((material) => material.dispose()) }) })