import { fireEvent, render, screen } from '@testing-library/react'; import { decodeMapLibraryDragPayload, MAP_LIBRARY_DRAG_MIME } from './editor/assetCatalog'; import { MapAssetLibrary } from './MapAssetLibrary'; const renderLibrary = ( onAdd: (type: string, placementMode: string) => void = () => {}, onSelectTerrain: (preset: string) => void = () => {}, ) => render( , ); describe('MapAssetLibrary', () => { it('只负责地图包、物理原语和预设地形的放置入口', () => { expect(decodeMapLibraryDragPayload('not-json')).toBeNull(); expect(decodeMapLibraryDragPayload('{"kind":"terrain","preset":"unknown"}')).toBeNull(); renderLibrary(); const library = screen.getByLabelText('地图资产库'); expect(library).toHaveTextContent('场景资产库'); expect(library).toHaveTextContent('物理几何原语'); expect(library).toHaveTextContent('预设地形'); expect(library).not.toHaveTextContent('已放置地图'); }); it('地图包使用与资产卡片一致的添加和拖放入口', () => { const values = new Map(); const onAddProjectMap = vi.fn(); const dataTransfer = { effectAllowed: 'none', setData: (type: string, value: string) => values.set(type, value), } as unknown as DataTransfer; render( {}} onAddProjectMap={onAddProjectMap} onSelectTerrain={() => {}} />, ); const source = document.querySelector('[data-project-map="maps/warehouse/map.json"]')!; fireEvent.dragStart(source, { dataTransfer }); fireEvent.click(screen.getByRole('button', { name: '放置工程地图 仓库' })); expect(decodeMapLibraryDragPayload(values.get(MAP_LIBRARY_DRAG_MIME) ?? '')).toEqual({ kind: 'project', descriptorPath: 'maps/warehouse/map.json', }); expect(onAddProjectMap).toHaveBeenCalledWith('maps/warehouse/map.json'); }); it('按所选放置方式添加物理几何原语', () => { const onAdd = vi.fn(); renderLibrary(onAdd); fireEvent.change(screen.getByLabelText('新增资产放置方式'), { target: { value: 'gravity' }, }); fireEvent.click(screen.getByRole('button', { name: '添加基础方盒' })); expect(onAdd).toHaveBeenCalledWith('box', 'gravity'); }); it('可与视口工具条共享受控放置方式', () => { const onPlacementModeChange = vi.fn(); render( {}} onSelectTerrain={() => {}} />, ); expect(screen.getByLabelText('新增资产放置方式')).toHaveValue('locked'); fireEvent.change(screen.getByLabelText('新增资产放置方式'), { target: { value: 'gravity' }, }); expect(onPlacementModeChange).toHaveBeenCalledWith('gravity'); }); it('拖动物理原语时写入类型和放置方式', () => { const values = new Map(); const dataTransfer = { effectAllowed: 'none', setData: (type: string, value: string) => values.set(type, value), } as unknown as DataTransfer; renderLibrary(); fireEvent.change(screen.getByLabelText('新增资产放置方式'), { target: { value: 'locked' }, }); fireEvent.dragStart(document.querySelector('[data-map-asset="ramp"]')!, { dataTransfer }); expect(decodeMapLibraryDragPayload(values.get(MAP_LIBRARY_DRAG_MIME) ?? '')).toEqual({ kind: 'certified', type: 'ramp', placementMode: 'locked', }); }); it('以示意图卡片添加或拖动预设地形', () => { const onSelectTerrain = vi.fn(); const values = new Map(); const dataTransfer = { effectAllowed: 'none', setData: (type: string, value: string) => values.set(type, value), } as unknown as DataTransfer; renderLibrary(undefined, onSelectTerrain); expect(screen.getAllByText('8.00 × 8.00 m')).toHaveLength(9); fireEvent.click(screen.getByRole('button', { name: '添加随机粗糙地形' })); fireEvent.dragStart(document.querySelector('[data-system-terrain="wave"]')!, { dataTransfer }); expect(onSelectTerrain).toHaveBeenCalledWith('rough'); expect(decodeMapLibraryDragPayload(values.get(MAP_LIBRARY_DRAG_MIME) ?? '')).toEqual({ kind: 'terrain', preset: 'wave', }); }); });