This commit is contained in:
@@ -4,6 +4,10 @@ import { defineComponent } from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import GuideMapShell from '@/components/navigation/GuideMapShell.vue'
|
||||
import {
|
||||
clearGuidePerformanceRecords,
|
||||
getGuidePerformanceRecords
|
||||
} from '@/services/performance/guidePerformance'
|
||||
|
||||
const ThreeMapStub = defineComponent({
|
||||
name: 'ThreeMap',
|
||||
@@ -25,9 +29,20 @@ const ThreeMapStub = defineComponent({
|
||||
default: null
|
||||
}
|
||||
},
|
||||
emits: ['floor-change', 'target-focus'],
|
||||
emits: ['floor-change', 'target-focus', 'auto-switch', 'render-mode-fallback'],
|
||||
setup(_, { expose }) {
|
||||
expose({ switchFloor: vi.fn() })
|
||||
expose({
|
||||
switchFloor: vi.fn(),
|
||||
showMultiFloor: vi.fn(async () => true),
|
||||
getGuideViewportState: vi.fn(() => ({
|
||||
scene: 'floor',
|
||||
floorId: 'L1',
|
||||
centerX: 29.0598,
|
||||
centerZ: 23.9424,
|
||||
visibleWorldSpan: 270.39,
|
||||
revision: 1
|
||||
}))
|
||||
})
|
||||
return {}
|
||||
},
|
||||
template: '<div data-testid="three-map"></div>'
|
||||
@@ -57,6 +72,73 @@ const mountShell = (visiblePoiIds: string[] | null) => mount(GuideMapShell, {
|
||||
})
|
||||
|
||||
describe('GuideMapShell 点位过滤契约', () => {
|
||||
it('馆内渲染模式使用单个开关,二维外观不显示楼层列表', async () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [{ id: 'L1', label: '1F' }, { id: 'L2', label: '2F' }],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'overview',
|
||||
indoorInitialView: 'overview',
|
||||
indoorRenderMode: 'two-d',
|
||||
showIndoorRenderModeToggle: true,
|
||||
showFloor: true,
|
||||
showFloorHeader: true,
|
||||
showLayerModeToggle: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
|
||||
const toggle = wrapper.get('[data-testid="indoor-render-mode-toggle"]')
|
||||
expect(toggle.text()).toBe('2D')
|
||||
expect(wrapper.findAll('[data-testid="indoor-render-mode-toggle"]')).toHaveLength(1)
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(false)
|
||||
expect(wrapper.find('.floor-header').exists()).toBe(false)
|
||||
expect(wrapper.find('.layer-mode-toggle').exists()).toBe(false)
|
||||
|
||||
await toggle.trigger('tap')
|
||||
expect(wrapper.emitted('indoorRenderModeChange')).toEqual([['three-d']])
|
||||
expect(wrapper.emitted('sceneViewportChange')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('二维单层视图仍显示楼层栏,楼层栏只取决于业务场景', () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [{ id: 'L1', label: '1F' }, { id: 'L2', label: '2F' }],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'floor',
|
||||
indoorRenderMode: 'two-d',
|
||||
showFloor: true,
|
||||
showFloorHeader: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(true)
|
||||
expect(wrapper.find('.floor-header').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('外观路线和起点选择状态也不会显示室内楼层栏', () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [{ id: 'L1', label: '1F' }, { id: 'L2', label: '2F' }],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'overview',
|
||||
showFloor: true,
|
||||
showRoute: true,
|
||||
routeStartSelectionActive: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it.each([
|
||||
['不过滤时透传 null', null],
|
||||
['无结果时透传空列表', []],
|
||||
@@ -84,6 +166,32 @@ describe('GuideMapShell 点位过滤契约', () => {
|
||||
expect(wrapper.emitted('targetFocus')).toEqual([[focusResult]])
|
||||
})
|
||||
|
||||
it('忽略旧渲染版本的 WebP 回退事件', async () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [{ id: 'L1', label: '1F' }, { id: 'L2', label: '2F' }],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'floor',
|
||||
sceneRevision: 2
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
const renderer = wrapper.getComponent(ThreeMapStub)
|
||||
|
||||
renderer.vm.$emit('render-mode-fallback', {
|
||||
mode: 'two-d',
|
||||
view: 'floor',
|
||||
floorId: 'L2',
|
||||
reason: 'model-load-timeout',
|
||||
sceneRevision: 1
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.emitted('indoorRenderModeFallback')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('动态楼层业务视图不会覆盖首次外观模型初始化视图', () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
@@ -131,4 +239,137 @@ describe('GuideMapShell 点位过滤契约', () => {
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.emitted('indoorViewChange')).toEqual([['floor']])
|
||||
})
|
||||
|
||||
it('measures a manual floor switch until ThreeMap commits the target floor', async () => {
|
||||
clearGuidePerformanceRecords()
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [
|
||||
{ id: 'L1', label: '1F' },
|
||||
{ id: 'L2', label: '2F' }
|
||||
],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'floor'
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
const renderer = wrapper.getComponent(ThreeMapStub)
|
||||
|
||||
;(wrapper.vm as any).switchFloor('L2')
|
||||
renderer.vm.$emit('floor-change', 'L2')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(getGuidePerformanceRecords()).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
kind: 'interaction',
|
||||
name: 'floor-switch',
|
||||
outcome: 'success',
|
||||
detail: expect.objectContaining({ floorId: 'L2', source: 'manual' })
|
||||
})
|
||||
]))
|
||||
})
|
||||
|
||||
it('起点选择阶段处于外观视图时仍隐藏室内楼层栏', () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [
|
||||
{ id: 'L1', label: '1F' },
|
||||
{ id: 'L2', label: '2F' }
|
||||
],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'overview',
|
||||
showFloor: true,
|
||||
routeStartSelectionActive: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('ThreeMap 自动切换由父级提交后隐藏楼层栏', async () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [
|
||||
{ id: 'L1', label: '1F' },
|
||||
{ id: 'L2', label: '2F' }
|
||||
],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'floor',
|
||||
showFloor: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
const renderer = wrapper.getComponent(ThreeMapStub)
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(true)
|
||||
|
||||
renderer.vm.$emit('auto-switch', {
|
||||
from: 'floor',
|
||||
to: 'overview',
|
||||
trigger: 'zoom-out',
|
||||
distance: 320
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(true)
|
||||
expect(wrapper.emitted('autoSwitch')).toHaveLength(1)
|
||||
|
||||
await wrapper.setProps({ indoorView: 'overview' })
|
||||
expect(wrapper.find('.floor-switcher').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('多层视图只显示单层切换按钮,不显示单层楼层列表', () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [
|
||||
{ id: 'L1', label: '1F' },
|
||||
{ id: 'L2', label: '2F' }
|
||||
],
|
||||
activeFloor: 'L2',
|
||||
indoorView: 'multi',
|
||||
layerMode: 'multi',
|
||||
showFloor: true,
|
||||
showFloorHeader: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
|
||||
expect(wrapper.find('.floor-header-label').text()).toBe('单层')
|
||||
expect(wrapper.find('.floor-list').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('父组件楼层短暂为空时,仍用最后提交的楼层返回单层', async () => {
|
||||
const wrapper = mount(GuideMapShell, {
|
||||
props: {
|
||||
mapType: 'indoor',
|
||||
indoorModelSource: modelSource,
|
||||
floors: [
|
||||
{ id: 'L1', label: '1F' },
|
||||
{ id: 'L2', label: '2F' }
|
||||
],
|
||||
activeFloor: 'L1',
|
||||
indoorView: 'floor',
|
||||
layerMode: 'single',
|
||||
showFloor: true,
|
||||
showFloorHeader: true
|
||||
},
|
||||
global: { stubs: { ThreeMap: ThreeMapStub } }
|
||||
})
|
||||
const renderer = wrapper.getComponent(ThreeMapStub)
|
||||
|
||||
await (wrapper.vm as any).setLayerMode('multi')
|
||||
await wrapper.setProps({ indoorView: 'multi', layerMode: 'multi', activeFloor: '' })
|
||||
await (wrapper.vm as any).setLayerMode('single')
|
||||
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||
|
||||
expect((renderer.vm as any).switchFloor).toHaveBeenCalledWith('L1')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user