修复首页快捷入口与三维点位同步
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
cxk
2026-07-21 00:40:06 +08:00
parent 1f89e8b3e0
commit b90c58451c
7 changed files with 257 additions and 16 deletions

View File

@@ -18,6 +18,7 @@ const testState = vi.hoisted(() => ({
searchRestoreCount: 0,
searchCollapseAfterDetailCount: 0,
searchResetCount: 0,
floorSwitchRequests: [] as string[],
onShowHandler: null as null | (() => Promise<void> | void),
halls: [] as Array<{ id: string; poiId?: string; location?: { poiId?: string }; name: string }>,
hallResolutionPromises: [] as Array<Promise<Array<{
@@ -102,7 +103,7 @@ const GuideMapShellStub = defineComponent({
visiblePoiIds: { type: Array, default: null },
targetFocusRequest: { type: Object, default: null }
},
emits: ['floor-change', 'poi-click', 'selection-clear', 'indoor-view-change'],
emits: ['floor-change', 'floor-request', 'floor-switch-failed', 'initial-model-ready', 'poi-click', 'selection-clear', 'indoor-view-change'],
setup() {
onMounted(() => {
testState.mapMountCount += 1
@@ -113,6 +114,10 @@ const GuideMapShellStub = defineComponent({
return {}
},
methods: {
switchFloor(floorId: string) {
testState.floorSwitchRequests.push(floorId)
return Promise.resolve()
},
resetToViewBaseline(options: {
view: 'overview' | 'floor'
floorId?: string
@@ -217,6 +222,7 @@ beforeEach(() => {
testState.searchRestoreCount = 0
testState.searchCollapseAfterDetailCount = 0
testState.searchResetCount = 0
testState.floorSwitchRequests = []
testState.onShowHandler = null
testState.halls = []
testState.hallResolutionPromises = []
@@ -355,7 +361,7 @@ describe('首页搜索与地图闭环', () => {
expect(wrapper.findAll('.guide-quick-action')[0]?.text()).toBe('导览')
})
it('向搜索面板传入当前楼层,并将分类结果 ID 精确传给地图', async () => {
it('等待渲染器提交目标楼层后,才将快捷分类结果 ID 传给地图', async () => {
const wrapper = await mountIndex()
const search = wrapper.getComponent(PoiSearchPanelStub)
const map = wrapper.getComponent(GuideMapShellStub)
@@ -370,6 +376,13 @@ describe('首页搜索与地图闭环', () => {
})
await wrapper.vm.$nextTick()
expect(testState.floorSwitchRequests).toEqual(['L2'])
expect(map.props('activeFloor')).toBe('L1')
expect(map.props('visiblePoiIds')).toEqual([])
map.vm.$emit('floor-change', 'L2')
await wrapper.vm.$nextTick()
expect(map.props('activeFloor')).toBe('L2')
expect(map.props('indoorView')).toBe('floor')
expect(map.props('visiblePoiIds')).toEqual(categoryContext.visiblePoiIds)
@@ -388,6 +401,78 @@ describe('首页搜索与地图闭环', () => {
expect(map.props('visiblePoiIds')).toEqual([])
})
it('三维模型重新以总览就绪后,不将旧单层状态误作楼层提交', async () => {
const wrapper = await mountIndex()
const search = wrapper.getComponent(PoiSearchPanelStub)
const map = wrapper.getComponent(GuideMapShellStub)
map.vm.$emit('floor-change', 'L1')
await wrapper.vm.$nextTick()
expect(map.props('indoorView')).toBe('floor')
map.vm.$emit('initial-model-ready', { view: 'overview', floorId: 'L1' })
await wrapper.vm.$nextTick()
expect(map.props('indoorView')).toBe('overview')
search.vm.$emit('category-mode-change', true)
search.vm.$emit('results-change', {
...categoryContext,
floorId: 'L1',
floorLabel: '1F',
active: true,
requestId: 20
})
await wrapper.vm.$nextTick()
expect(testState.floorSwitchRequests).toEqual(['L1'])
expect(map.props('visiblePoiIds')).toEqual([])
map.vm.$emit('floor-change', 'L1')
await wrapper.vm.$nextTick()
expect(map.props('visiblePoiIds')).toEqual(categoryContext.visiblePoiIds)
})
it('忽略过期搜索结果,不允许旧楼层覆盖当前待提交地图状态', async () => {
const wrapper = await mountIndex()
const search = wrapper.getComponent(PoiSearchPanelStub)
const map = wrapper.getComponent(GuideMapShellStub)
search.vm.$emit('category-mode-change', true)
search.vm.$emit('results-change', { ...categoryContext, active: true, requestId: 8 })
search.vm.$emit('results-change', {
...categoryContext,
floorId: 'L1',
floorLabel: '1F',
visiblePoiIds: ['stale-l1'],
active: true,
requestId: 7
})
await wrapper.vm.$nextTick()
expect(testState.floorSwitchRequests).toEqual(['L2'])
map.vm.$emit('floor-change', 'L2')
await wrapper.vm.$nextTick()
expect(map.props('visiblePoiIds')).toEqual(categoryContext.visiblePoiIds)
})
it('楼层切换失败时清空快捷分类标记,重试提交后恢复与列表一致的 ID', async () => {
const wrapper = await mountIndex()
const search = wrapper.getComponent(PoiSearchPanelStub)
const map = wrapper.getComponent(GuideMapShellStub)
search.vm.$emit('category-mode-change', true)
search.vm.$emit('results-change', { ...categoryContext, active: true, requestId: 12 })
await wrapper.vm.$nextTick()
map.vm.$emit('floor-switch-failed', { floorId: 'L2', floorLabel: '2F' })
await wrapper.vm.$nextTick()
expect(map.props('activeFloor')).toBe('L1')
expect(map.props('visiblePoiIds')).toEqual([])
map.vm.$emit('floor-change', 'L2')
await wrapper.vm.$nextTick()
expect(map.props('visiblePoiIds')).toEqual(categoryContext.visiblePoiIds)
})
it('楼层数据按高到低返回时,首次进入仍将 1F 作为自动缩放的默认目标', async () => {
const originalFloors = [...floors]
floors.splice(0, floors.length,
@@ -417,6 +502,8 @@ describe('首页搜索与地图闭环', () => {
...categoryContext,
active: true
})
map.vm.$emit('floor-change', 'L2')
await wrapper.vm.$nextTick()
search.vm.$emit('result-tap', poi, categoryContext)
await flushPromises()
@@ -486,6 +573,8 @@ describe('首页搜索与地图闭环', () => {
search.vm.$emit('category-mode-change', true)
search.vm.$emit('results-change', { ...categoryContext, active: true })
map.vm.$emit('floor-change', 'L2')
await wrapper.vm.$nextTick()
search.vm.$emit('result-tap', poi, categoryContext)
await flushPromises()

View File

@@ -149,6 +149,7 @@ const lastResultState = (wrapper: ReturnType<typeof mount>) => (
categoryId: string
keyword: string
pending?: boolean
requestId?: number
}
)
@@ -323,6 +324,36 @@ describe('PoiSearchPanel 搜索状态契约', () => {
wrapper.unmount()
})
it('首页分类结果在组件重挂载后仍发送递增的跨组件版本号', async () => {
const firstWrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: 'floor-1',
currentFloorLabel: '1F'
}
})
await flushMountedSearch()
await firstWrapper.get('[data-testid="poi-category-restroom"]').trigger('tap')
await flushMountedSearch()
const firstRequestId = lastResultState(firstWrapper).requestId
firstWrapper.unmount()
const secondWrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: 'floor-1',
currentFloorLabel: '1F'
}
})
await flushMountedSearch()
await secondWrapper.get('[data-testid="poi-category-restroom"]').trigger('tap')
await flushMountedSearch()
expect(firstRequestId).toEqual(expect.any(Number))
expect(lastResultState(secondWrapper).requestId).toBeGreaterThan(firstRequestId as number)
secondWrapper.unmount()
})
it('首页快捷分类请求期间清空列表并下发 pending 空地图 ID', async () => {
const initialState = createSearchState()
const deferredCategory = createDeferred<GuidePoiSearchViewState>()