// @vitest-environment happy-dom import { defineComponent } from 'vue' import { mount } from '@vue/test-utils' import { describe, expect, it, vi } from 'vitest' import GuideMapShell from '@/components/navigation/GuideMapShell.vue' const ThreeMapStub = defineComponent({ name: 'ThreeMap', props: { initialFloorId: { type: String, default: '' }, initialView: { type: String, default: '' }, visiblePoiIds: { type: Array, default: null }, targetFocus: { type: Object, default: null } }, emits: ['floor-change', 'target-focus'], setup(_, { expose }) { expose({ switchFloor: vi.fn() }) return {} }, template: '
' }) const modelSource = { loadPackage: async () => ({ overviewModelUrl: '', floors: [] }), loadFloorPois: async () => [] } const mountShell = (visiblePoiIds: string[] | null) => mount(GuideMapShell, { props: { mapType: 'indoor', indoorModelSource: modelSource, floors: [ { id: 'L1', label: '1F' }, { id: 'L2', label: '2F' } ], activeFloor: 'L1', visiblePoiIds }, global: { stubs: { ThreeMap: ThreeMapStub } } }) describe('GuideMapShell 点位过滤契约', () => { it.each([ ['不过滤时透传 null', null], ['无结果时透传空列表', []], ['有结果时透传精确 ID', ['poi-a', 'poi-b']] ])('%s', (_label, visiblePoiIds) => { const wrapper = mountShell(visiblePoiIds as string[] | null) expect(wrapper.getComponent(ThreeMapStub).props('visiblePoiIds')).toEqual(visiblePoiIds) }) it('原样转发跨楼层与目标聚焦结果', async () => { const wrapper = mountShell(['poi-l2']) const renderer = wrapper.getComponent(ThreeMapStub) const focusResult = { requestId: 3, poiId: 'poi-l2', floorId: 'L2', status: 'focused' as const } renderer.vm.$emit('floor-change', 'L2') renderer.vm.$emit('target-focus', focusResult) await wrapper.vm.$nextTick() expect(wrapper.emitted('floorChange')).toEqual([['L2']]) expect(wrapper.emitted('targetFocus')).toEqual([[focusResult]]) }) it('动态楼层业务视图不会覆盖首次外观模型初始化视图', () => { const wrapper = mount(GuideMapShell, { props: { mapType: 'indoor', indoorModelSource: modelSource, floors: [ { id: 'L1', label: '1F' }, { id: 'L2', label: '2F' } ], activeFloor: 'L2', indoorView: 'floor', indoorInitialView: 'overview' }, global: { stubs: { ThreeMap: ThreeMapStub } } }) const renderer = wrapper.getComponent(ThreeMapStub) expect(renderer.props('initialFloorId')).toBe('L2') expect(renderer.props('initialView')).toBe('overview') }) it('外观状态点击当前业务楼层仍请求渲染器,且等待 floor-change 才提交业务视图', async () => { const wrapper = mount(GuideMapShell, { props: { mapType: 'indoor', indoorModelSource: modelSource, floors: [{ id: 'L2', label: '2F' }], activeFloor: 'L2', indoorView: 'overview', indoorInitialView: 'overview' }, global: { stubs: { ThreeMap: ThreeMapStub } } }) const renderer = wrapper.getComponent(ThreeMapStub) await (wrapper.vm as any).switchFloor('L2') expect((renderer.vm as any).switchFloor).toHaveBeenCalledWith('L2') expect(wrapper.emitted('indoorViewChange')).toBeUndefined() renderer.vm.$emit('floor-change', 'L2') await wrapper.vm.$nextTick() expect(wrapper.emitted('indoorViewChange')).toEqual([['floor']]) }) })