同步 sgs-frontend-mobile 源码
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-27 11:26:01 +08:00
parent 575dca430f
commit 9ea1bfab71
181 changed files with 24395 additions and 5212 deletions

View File

@@ -149,7 +149,6 @@ const lastResultState = (wrapper: ReturnType<typeof mount>) => (
categoryId: string
keyword: string
pending?: boolean
requestId?: number
}
)
@@ -235,6 +234,47 @@ afterEach(() => {
})
describe('PoiSearchPanel 搜索状态契约', () => {
it('首页折叠挂载只加载楼层,不提前读取全馆搜索数据', async () => {
const wrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: 'floor-1',
currentFloorLabel: '1F'
}
})
await flushMountedSearch()
expect(guideMocks.getFloors).toHaveBeenCalledTimes(1)
expect(guideMocks.createInitialPoiSearchState).not.toHaveBeenCalled()
expect(guideMocks.selectPoiSearchCategory).not.toHaveBeenCalled()
expect(guideMocks.searchPoiKeyword).not.toHaveBeenCalled()
expect(wrapper.findAll('.home-category-chip')).toHaveLength(10)
wrapper.unmount()
})
it('首页折叠态同步当前楼层时不创建默认搜索结果', async () => {
const wrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: '',
currentFloorLabel: ''
}
})
await flushMountedSearch()
await wrapper.setProps({
currentFloorId: 'floor-2',
currentFloorLabel: '2F'
})
await flushMountedSearch()
expect(guideMocks.createInitialPoiSearchState).not.toHaveBeenCalled()
expect(guideMocks.changePoiSearchFloor).not.toHaveBeenCalled()
expect(guideMocks.selectPoiSearchCategory).not.toHaveBeenCalled()
expect(guideMocks.searchPoiKeyword).not.toHaveBeenCalled()
wrapper.unmount()
})
it('固定展示 10 类快捷查找,并为收起和展开区域提供 aria-label', async () => {
const wrapper = mount(PoiSearchPanel, {
props: {
@@ -259,7 +299,7 @@ describe('PoiSearchPanel 搜索状态契约', () => {
wrapper.unmount()
})
it('无结果分类具有禁用态和 aria-disabled点击不会发起分类查询', async () => {
it('首页未初始化搜索状态时分类入口保持可用,并触发首次分类查询', async () => {
guideMocks.createInitialPoiSearchState.mockResolvedValue(createSearchState({
disabledCategoryIds: ['cinema']
}))
@@ -273,13 +313,13 @@ describe('PoiSearchPanel 搜索状态契约', () => {
await flushMountedSearch()
const cinema = wrapper.get('[data-testid="poi-category-cinema"]')
expect(cinema.classes()).toContain('disabled')
expect(cinema.attributes('aria-disabled')).toBe('true')
expect(cinema.classes()).not.toContain('disabled')
expect(cinema.attributes('aria-disabled')).toBe('false')
await cinema.trigger('tap')
await flushMountedSearch()
expect(guideMocks.selectPoiSearchCategory).not.toHaveBeenCalled()
expect(wrapper.find('[data-testid="poi-home-category-results"]').exists()).toBe(false)
expect(guideMocks.selectPoiSearchCategory).toHaveBeenCalledWith(null, 'cinema', 'floor-1')
expect(wrapper.find('[data-testid="poi-home-category-results"]').exists()).toBe(true)
wrapper.unmount()
})
@@ -297,6 +337,113 @@ describe('PoiSearchPanel 搜索状态契约', () => {
wrapper.unmount()
})
it('楼层展示文案不一致时仍按稳定 floorId 显示空间结果', async () => {
const storageSpace = createPoi(
'space-storage',
'藏品技术保护区',
'floor-1',
'1.0层',
'space_storage',
[2, 0, 2]
)
guideMocks.createInitialPoiSearchState.mockResolvedValue(createSearchState({
results: [storageSpace]
}))
const wrapper = mount(PoiSearchPanel, { props: { variant: 'page' } })
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual(['space-storage'])
expect(wrapper.get('.result-count').text()).toContain('1 处地点')
wrapper.unmount()
})
it('直接渲染当前楼层状态结果,不用瞬时楼层选项二次过滤后端别名', async () => {
const b2Floor = { id: 'floor-b2', label: 'B2', order: -2 }
const aliasedSpace = createPoi(
'space-b2-storage',
'B2 藏品库',
'legacy-b2-alias',
'B2',
'space_storage',
[2, -8, 2]
)
const b2State: GuidePoiSearchViewState = {
...createSearchState(),
floorId: b2Floor.id,
floorLabel: b2Floor.label,
results: [aliasedSpace],
visiblePoiIds: [aliasedSpace.id]
}
guideMocks.getFloors.mockResolvedValue([b2Floor])
guideMocks.createInitialPoiSearchState.mockResolvedValue(b2State)
const wrapper = mount(PoiSearchPanel, { props: { variant: 'page' } })
await flushMountedSearch()
expect(guideMocks.createInitialPoiSearchState).toHaveBeenCalledWith('floor-b2')
expect(renderedResultIds(wrapper)).toEqual(['space-b2-storage'])
expect(wrapper.get('.result-count').text()).toContain('1 处地点')
wrapper.unmount()
})
it('父级楼层快速往返时使旧楼层请求失效且不覆盖已提交状态', async () => {
const deferredFloor2 = createDeferred<GuidePoiSearchViewState>()
guideMocks.changePoiSearchFloor.mockReturnValueOnce(deferredFloor2.promise)
const wrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: 'floor-1',
currentFloorLabel: '1F'
}
})
await flushMountedSearch()
await wrapper.get('.search-box').trigger('tap')
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual(['hall-1', 'space-1'])
await wrapper.setProps({ currentFloorId: 'floor-2', currentFloorLabel: '2F' })
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual([])
await wrapper.setProps({ currentFloorId: 'floor-1', currentFloorLabel: '1F' })
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual(['hall-1', 'space-1'])
deferredFloor2.resolve(createSearchState({ floorId: 'floor-2' }))
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual(['hall-1', 'space-1'])
expect(wrapper.find('[data-testid="poi-result-hall-2"]').exists()).toBe(false)
wrapper.unmount()
})
it('首次默认查询在途时跟随父级新楼层重发并忽略旧响应', async () => {
const deferredFloor1 = createDeferred<GuidePoiSearchViewState>()
guideMocks.createInitialPoiSearchState
.mockReturnValueOnce(deferredFloor1.promise)
.mockResolvedValueOnce(createSearchState({ floorId: 'floor-2' }))
const wrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
currentFloorId: 'floor-1',
currentFloorLabel: '1F'
}
})
await flushMountedSearch()
await wrapper.get('.search-box').trigger('tap')
await flushMountedSearch()
await wrapper.setProps({ currentFloorId: 'floor-2', currentFloorLabel: '2F' })
await flushMountedSearch()
expect(guideMocks.createInitialPoiSearchState).toHaveBeenLastCalledWith('floor-2')
expect(renderedResultIds(wrapper)).toEqual(['hall-2'])
deferredFloor1.resolve(createSearchState({ floorId: 'floor-1' }))
await flushMountedSearch()
expect(renderedResultIds(wrapper)).toEqual(['hall-2'])
wrapper.unmount()
})
it('快捷分类调用 selectPoiSearchCategory列表 ID 与 results-change visiblePoiIds 完全一致', async () => {
const initialState = createSearchState()
guideMocks.createInitialPoiSearchState.mockResolvedValue(initialState)
@@ -312,8 +459,12 @@ describe('PoiSearchPanel 搜索状态契约', () => {
await wrapper.get('[data-testid="poi-category-restroom"]').trigger('tap')
await flushMountedSearch()
expect(guideMocks.selectPoiSearchCategory).toHaveBeenCalledWith(initialState, 'restroom', 'floor-1')
expect(guideMocks.selectPoiSearchCategory).toHaveBeenCalledWith(null, 'restroom', 'floor-1')
expect(renderedResultIds(wrapper)).toEqual(['restroom-1'])
expect(wrapper.find('.clear-button').exists()).toBe(false)
expect(wrapper.get('[data-testid="poi-category-cancel"]').exists()).toBe(true)
expect(wrapper.get('.result-name').text()).toBe('洗手间 A')
expect(wrapper.get('.result-meta').text()).toBe('1F · 洗手间')
expect(lastResultState(wrapper)).toMatchObject({
active: true,
floorId: 'floor-1',
@@ -324,36 +475,6 @@ 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>()
@@ -408,7 +529,11 @@ describe('PoiSearchPanel 搜索状态契约', () => {
})
await flushMountedSearch()
expect(guideMocks.searchPoiKeyword).toHaveBeenCalledWith(initialState, '恐龙', 'floor-1')
expect(guideMocks.searchPoiKeyword).toHaveBeenCalledWith(
expect.objectContaining({ mode: 'default', floorId: 'floor-1' }),
'恐龙',
'floor-1'
)
expect(renderedResultIds(wrapper)).toEqual(['dinosaur-1', 'dinosaur-shop-1'])
expect(lastResultState(wrapper)).toMatchObject({
active: true,
@@ -438,7 +563,11 @@ describe('PoiSearchPanel 搜索状态契约', () => {
})
await flushMountedSearch()
expect(guideMocks.searchPoiKeyword).toHaveBeenCalledWith(initialState, '洗手间', 'floor-1')
expect(guideMocks.searchPoiKeyword).toHaveBeenCalledWith(
expect.objectContaining({ mode: 'default', floorId: 'floor-1' }),
'洗手间',
'floor-1'
)
expect(guideMocks.selectPoiSearchCategory).not.toHaveBeenCalled()
expect(lastResultState(wrapper)).toMatchObject({
active: true,