Files
frontend-miniapp/tests/unit/GuideRepository.spec.ts
lyf 9ea1bfab71
Some checks failed
CI / verify (push) Has been cancelled
同步 sgs-frontend-mobile 源码
2026-07-27 11:26:01 +08:00

753 lines
25 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, describe, expect, it, vi } from 'vitest'
import type {
SgsSdkApiProvider,
SgsSdkManifestPayload
} from '@/data/providers/sgsSdkApiProvider'
import { SgsSdkGuideRepository } from '@/repositories/GuideRepository'
import { SgsSdkGuideModelRepository } from '@/repositories/GuideModelRepository'
import {
isExhibitionHallSpace,
toMuseumPoiFromSgs,
toMuseumSpacePointFromSgs
} from '@/data/adapters/sgsSdkGuideAdapter'
import {
getPoiCategoryById,
matchesPoiCategory,
resolvePoiCategory
} from '@/domain/poiCategories'
import { toFacilityDetailViewModel } from '@/view-models/guideViewModels'
const manifest: SgsSdkManifestPayload = {
mapId: 'museum',
mapName: '深圳自然博物馆',
floors: [
{
floorId: '101',
floorCode: 'L1',
floorName: '1F',
sortOrder: 1
}
]
}
const floorPoi = {
id: 'poi-toilet',
name: '一层卫生间',
type: 'toilet',
typeName: '卫生间',
floorId: '101',
position: {
x: 4,
y: 12,
z: 8
}
}
const theaterSpace = {
id: 'space-theater',
name: '球幕影院',
type: 'theater',
floorId: '101',
boundaryWkt: 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'
}
const createProvider = (overrides: Partial<SgsSdkApiProvider> = {}) => ({
getManifest: vi.fn().mockResolvedValue(manifest),
getFloorPois: vi.fn().mockResolvedValue([floorPoi]),
getFloorBusinessPois: vi.fn().mockResolvedValue([]),
getFloorSpaces: vi.fn().mockResolvedValue([theaterSpace]),
getNavigablePlaces: vi.fn().mockResolvedValue([]),
...overrides
}) as unknown as SgsSdkApiProvider
afterEach(() => {
vi.restoreAllMocks()
})
describe('SgsSdkGuideRepository 点位搜索', () => {
it('源数据仅有 floorCode 时回填 manifest 的稳定 floorId', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'poi-floor-code-only',
floorId: undefined,
floorCode: 'L1'
}, manifest.floors)
expect(poi.floorId).toBe('101')
expect(poi.floorLabel).toBe('1F')
})
it('SDK null 坐标不会被误转换为模型原点', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'poi-with-null-position',
position: {
x: null,
y: null,
z: null
}
}, manifest.floors)
expect(poi.positionGltf).toBeUndefined()
})
it('普通 POI 坐标与大屏端一致优先使用 meshCenter', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
meshCenter: { x: 11, y: 12, z: 13 },
position: { x: 21, y: 22, z: 23 },
labelPosition: { x: 31, y: 32, z: 33 },
x: 41,
y: 42,
z: 43
}, manifest.floors)
expect(poi.positionGltf).toEqual([11, 12, 13])
})
it('普通 POI 坐标按 position、labelPosition、旧坐标依次回退', () => {
const basePoi = {
...floorPoi,
position: { x: null, y: null, z: null },
labelPosition: { x: 31, y: 32, z: 33 },
x: 41,
y: 42,
z: 43
}
expect(toMuseumPoiFromSgs(basePoi, manifest.floors).positionGltf).toEqual([31, 32, 33])
expect(toMuseumPoiFromSgs({
...basePoi,
labelPosition: { x: null, y: null, z: null }
}, manifest.floors).positionGltf).toEqual([41, 42, 43])
})
it('设备终端解析对象 extParams 的全部精确模型节点', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'guide-screen-pair',
name: '一楼导览屏',
type: 'device_terminal',
extParams: {
sourceNodeNames: ['L1_导览屏_01', 'L1_导览屏_02']
}
}, manifest.floors)
expect(poi.primaryCategory.iconType).toBe('device_terminal')
expect(poi.sourceObjectName).toBe('L1_导览屏_01')
expect(poi.mergedSourceObjectNames).toEqual(['L1_导览屏_02'])
})
it('设备终端解析字符串 extParams并保持显式节点字段优先级', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'elevator-with-node-chain',
name: 'L1_H电梯',
type: 'device_terminal',
anchorNodeName: 'L1_H_电梯16',
sourceNodeName: 'L1_H_电梯15',
extParams: JSON.stringify({
sourceNodeNames: ['L1_H_电梯14', 'L1_H_电梯16']
})
}, manifest.floors)
expect(poi.sourceObjectName).toBe('L1_H_电梯16')
expect(poi.mergedSourceObjectNames).toEqual(['L1_H_电梯15', 'L1_H_电梯14'])
})
it('设备终端解析 extParams 中的单个 sourceNodeName', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'vending-machine',
name: '自助售卖机',
type: 'device_terminal',
extParams: {
sourceNodeName: 'L1_自助售卖机'
}
}, manifest.floors)
expect(poi.sourceObjectName).toBe('L1_自助售卖机')
expect(poi.mergedSourceObjectNames).toEqual([])
})
it('缺少节点元数据的设备终端仅用精确后台名称作为模型节点', () => {
const poi = toMuseumPoiFromSgs({
...floorPoi,
id: 'security-device',
name: 'L1_安检机_01',
type: 'device_terminal'
}, manifest.floors)
expect(poi.sourceObjectName).toBe('L1_安检机_01')
expect(poi.mergedSourceObjectNames).toEqual([])
})
it('空间是否为展厅仅由后端分类决定', () => {
expect(isExhibitionHallSpace({
id: 'hall',
name: '人类厅',
type: 'exhibition_hall',
floorId: '101'
})).toBe(true)
expect(isExhibitionHallSpace({
...theaterSpace,
name: '动感多维影院'
})).toBe(false)
expect(isExhibitionHallSpace({
id: 'education-space',
name: '青少年探索中心',
type: 'education_activity',
floorId: '101'
})).toBe(false)
})
it('空间节点名为占位符时按楼层和空间名称匹配模型', () => {
const poi = toMuseumSpacePointFromSgs({
id: 'tea-room',
name: '茶水间',
type: 'service_space',
floorId: '101',
sourceNodeName: 'L1_???',
position: { x: 1, y: 12, z: 2 }
}, manifest.floors, '101')
expect(poi?.sourceObjectName).toBe('L1_茶水间')
})
it('合并普通点位与空间点位,并保留影院真实分类和楼层高度', async () => {
const repository = new SgsSdkGuideRepository(createProvider())
const results = await repository.searchPois()
const theaterResults = results.filter((poi) => poi.name === '球幕影院')
expect(theaterResults).toHaveLength(1)
expect(theaterResults[0]).toMatchObject({
id: 'space-space-theater',
floorId: '101',
floorLabel: '1F',
primaryCategory: {
id: 'space_theater'
},
positionGltf: [5, 12, 5]
})
expect(resolvePoiCategory(theaterResults[0])?.id).toBe('cinema')
expect(matchesPoiCategory(
theaterResults[0],
getPoiCategoryById('cinema')!
)).toBe(true)
expect(matchesPoiCategory(
theaterResults[0],
getPoiCategoryById('exhibition-hall')!
)).toBe(false)
expect(toFacilityDetailViewModel(theaterResults[0]).category).toBe('影院')
expect(results.some((poi) => poi.id === 'poi-toilet')).toBe(true)
})
it('搜索可定位 ID 与同楼层地图 marker ID 保持一致', async () => {
const provider = createProvider()
const guideRepository = new SgsSdkGuideRepository(provider)
const modelRepository = new SgsSdkGuideModelRepository(provider, guideRepository)
const [searchResults, renderPois] = await Promise.all([
guideRepository.searchPois(),
modelRepository.loadFloorPois('101')
])
const renderPoiIds = new Set(renderPois.map((poi) => poi.id))
const locatableSearchIds = searchResults
.filter((poi) => poi.floorId === '101' && poi.positionGltf)
.map((poi) => poi.id)
expect(locatableSearchIds.length).toBeGreaterThan(0)
expect(locatableSearchIds.every((poiId) => renderPoiIds.has(poiId))).toBe(true)
expect(renderPois.find((poi) => poi.id === 'space-space-theater')).toMatchObject({
primaryCategory: 'space_theater',
iconType: 'theater'
})
})
it('地图标签只读取当前楼层 SDK 数据,不触发全馆搜索聚合', async () => {
const provider = createProvider()
const guideSearchRepository = {
listPois: vi.fn().mockResolvedValue([]),
listSpacePoints: vi.fn().mockResolvedValue([])
}
const modelRepository = new SgsSdkGuideModelRepository(
provider,
guideSearchRepository as never
)
const renderPois = await modelRepository.loadFloorPois('101')
expect(renderPois).not.toHaveLength(0)
expect(provider.getFloorPois).toHaveBeenCalledTimes(1)
expect(provider.getFloorBusinessPois).toHaveBeenCalledTimes(1)
expect(provider.getFloorSpaces).toHaveBeenCalledTimes(1)
expect(provider.getNavigablePlaces).toHaveBeenCalledTimes(1)
expect(guideSearchRepository.listPois).not.toHaveBeenCalled()
expect(guideSearchRepository.listSpacePoints).not.toHaveBeenCalled()
})
it('地图渲染链路透传设备终端的全部模型节点', async () => {
const provider = createProvider({
getFloorPois: vi.fn().mockResolvedValue([{
...floorPoi,
id: 'guide-screen-pair',
name: '一楼导览屏',
type: 'device_terminal',
extParams: JSON.stringify({
sourceNodeNames: ['L1_导览屏_01', 'L1_导览屏_02']
})
}])
})
const repository = new SgsSdkGuideModelRepository(provider)
const renderPoi = (await repository.loadFloorPois('101'))
.find((poi) => poi.id === 'guide-screen-pair')
expect(renderPoi).toMatchObject({
iconType: 'device_terminal',
sourceObjectName: 'L1_导览屏_01',
mergedSourceObjectNames: ['L1_导览屏_02']
})
})
it('首屏标签优先读取楼层 Bundle并在首帧后预取搜索补充数据', async () => {
const getFloorBundle = vi.fn().mockResolvedValue({
pois: [floorPoi],
spaces: [theaterSpace]
})
const getFloorBusinessPois = vi.fn().mockResolvedValue([])
const getNavigablePlaces = vi.fn().mockResolvedValue([])
const provider = createProvider({
getFloorBundle,
getFloorBusinessPois,
getNavigablePlaces
})
const repository = new SgsSdkGuideModelRepository(provider)
const renderPois = await repository.loadFloorPoisFast('101')
expect(renderPois).toEqual(expect.arrayContaining([
expect.objectContaining({ id: 'poi-toilet' }),
expect.objectContaining({ id: 'space-space-theater' })
]))
expect(getFloorBundle).toHaveBeenCalledWith('101')
expect(provider.getFloorPois).not.toHaveBeenCalled()
await new Promise((resolve) => setTimeout(resolve, 0))
expect(getFloorBusinessPois).toHaveBeenCalledWith('101')
expect(getNavigablePlaces).toHaveBeenCalledWith('101')
})
it('外观首屏不会预取室内搜索补充数据', async () => {
const getFloorBusinessPois = vi.fn().mockResolvedValue([])
const getNavigablePlaces = vi.fn().mockResolvedValue([])
const provider = createProvider({
getManifest: vi.fn().mockResolvedValue({
...manifest,
floors: [{
floorId: 'outdoor',
floorCode: 'EXTERIOR',
floorName: '室外'
}]
}),
getFloorBundle: vi.fn().mockResolvedValue({ pois: [], spaces: [] }),
getFloorBusinessPois,
getNavigablePlaces
})
const repository = new SgsSdkGuideModelRepository(provider)
await expect(repository.loadFloorPoisFast('outdoor')).resolves.toEqual([])
await new Promise((resolve) => setTimeout(resolve, 0))
expect(getFloorBusinessPois).not.toHaveBeenCalled()
expect(getNavigablePlaces).not.toHaveBeenCalled()
})
it('核心点位来源短暂失败时仍返回可直接定位的稳定空间 ID', async () => {
const getFloorPois = vi.fn()
.mockResolvedValueOnce([floorPoi])
.mockRejectedValueOnce(new Error('pois offline'))
.mockResolvedValue([floorPoi])
const getFloorSpaces = vi.fn()
.mockResolvedValueOnce([theaterSpace])
.mockRejectedValueOnce(new Error('spaces offline'))
.mockResolvedValue([theaterSpace])
const provider = createProvider({ getFloorPois, getFloorSpaces })
const guideRepository = new SgsSdkGuideRepository(provider)
const modelRepository = new SgsSdkGuideModelRepository(provider, guideRepository)
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
await guideRepository.listSpacePoints()
const fallbackResults = await guideRepository.searchPois()
const fallbackTheater = fallbackResults.find((poi) => poi.name === '球幕影院')
expect(fallbackTheater?.id).toBe('space-space-theater')
const recoveredTheater = (await guideRepository.searchPois())
.find((poi) => poi.name === '球幕影院')
expect(recoveredTheater?.id).toBe(fallbackTheater?.id)
await expect(guideRepository.getPoiById('space-space-theater'))
.resolves.toMatchObject({ id: 'space-space-theater' })
const renderPois = await modelRepository.loadFloorPois('101')
expect(renderPois.some((poi) => poi.id === fallbackTheater?.id)).toBe(true)
})
it('精确空间 ID 与普通点位 ID 同号时不会定位到错误点位', async () => {
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
const provider = createProvider({
getFloorPois: vi.fn().mockResolvedValue([{
...floorPoi,
id: '42',
name: '普通卫生间'
}]),
getFloorSpaces: vi.fn().mockResolvedValue([{
id: '42',
name: '公共空间',
type: 'public_area',
floorId: '101',
boundaryWkt: 'POLYGON((0 0, 8 0, 8 8, 0 8, 0 0))'
}])
})
const repository = new SgsSdkGuideRepository(provider)
await expect(repository.getPoiById('space-42')).resolves.toMatchObject({
id: 'space-42',
name: '公共空间'
})
await expect(repository.getPoiById('42')).resolves.toMatchObject({
id: '42',
name: '普通卫生间'
})
})
it('相同模型对象名不会删除不同稳定 ID 和坐标的普通点位', async () => {
const provider = createProvider({
getFloorSpaces: vi.fn().mockResolvedValue([]),
getFloorPois: vi.fn().mockResolvedValue([
{
...floorPoi,
id: '5625',
name: '男卫生间001',
sourceNodeName: 'L2_男卫生间001',
position: { x: 1, y: 12, z: 1 }
},
{
...floorPoi,
id: '5629',
name: '卫生间01',
sourceNodeName: 'L2_男卫生间001',
position: { x: 9, y: 12, z: 9 }
}
])
})
const guideRepository = new SgsSdkGuideRepository(provider)
const modelRepository = new SgsSdkGuideModelRepository(provider, guideRepository)
const renderPois = await modelRepository.loadFloorPois('101')
expect(renderPois.filter((poi) => poi.id === '5625' || poi.id === '5629'))
.toHaveLength(2)
})
it('外观地图使用室外楼层预计算的空间标签位置', async () => {
const exteriorFloor = {
floorId: 'outdoor',
floorCode: 'EXTERIOR',
floorName: '外观/室外层',
sortOrder: 10
}
const exteriorRoadSpace = {
id: 'space-honghua-road',
name: '红花路',
type: 'road_area',
floorId: exteriorFloor.floorId,
sourceNodeName: '室外_红花路',
labelPosition: {
x: -1.206116,
y: 2.505,
z: -84.258389
},
meshCenter: {
x: -1.206116,
y: 0.005,
z: -84.258389
}
}
const getFloorSpaces = vi.fn().mockImplementation(async (floorId: string) => (
floorId === exteriorFloor.floorId ? [exteriorRoadSpace] : [theaterSpace]
))
const getFloorBundle = vi.fn().mockResolvedValue({
model: {
modelUrl: '/models/overview.glb'
}
})
const provider = createProvider({
getManifest: vi.fn().mockResolvedValue({
...manifest,
floors: [exteriorFloor, ...manifest.floors]
}),
getFloorPois: vi.fn().mockResolvedValue([]),
getFloorSpaces,
getFloorBundle
})
const repository = new SgsSdkGuideModelRepository(provider, new SgsSdkGuideRepository(provider))
const packageData = await repository.loadPackage()
const renderPois = await repository.loadFloorPois(exteriorFloor.floorId)
expect(packageData.overviewFloorId).toBe(exteriorFloor.floorId)
expect(getFloorSpaces).toHaveBeenCalledWith(exteriorFloor.floorId)
expect(renderPois).toContainEqual(expect.objectContaining({
id: 'space-space-honghua-road',
name: '红花路',
floorId: exteriorFloor.floorId,
sourceObjectName: '室外_红花路',
positionGltf: [-1.206116, 2.505, -84.258389]
}))
})
it('Manifest 提供模型地址时不再为每个楼层读取 Bundle', async () => {
const exteriorFloor = {
floorId: 'outdoor',
floorCode: 'EXTERIOR',
floorName: '外观/室外层',
sortOrder: 10,
modelUrl: '/models/overview-lightweight.glb',
fallbackModelUrl: '/models/overview.glb'
}
const indoorFloor = {
...manifest.floors[0],
modelUrl: '/models/l1-lightweight.glb',
fallbackModelUrl: '/models/l1.glb'
}
const getFloorBundle = vi.fn()
const provider = createProvider({
getManifest: vi.fn().mockResolvedValue({
...manifest,
floors: [exteriorFloor, indoorFloor]
}),
getFloorBundle
})
const repository = new SgsSdkGuideModelRepository(provider, new SgsSdkGuideRepository(provider))
await expect(repository.loadPackage()).resolves.toMatchObject({
overviewModelUrl: '/models/overview-lightweight.glb',
floors: [expect.objectContaining({
floorId: '101',
modelUrl: '/models/l1-lightweight.glb',
modelUrls: ['/models/l1-lightweight.glb', '/models/l1.glb']
})]
})
expect(getFloorBundle).not.toHaveBeenCalled()
})
it('部分来源失败时继续返回可用点位,并在后续搜索重试失败来源', async () => {
const getFloorSpaces = vi.fn()
.mockRejectedValueOnce(new Error('spaces offline'))
.mockRejectedValueOnce(new Error('spaces offline'))
.mockResolvedValue([theaterSpace])
const provider = createProvider({ getFloorSpaces })
const repository = new SgsSdkGuideRepository(provider)
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
const firstResults = await repository.searchPois()
expect(firstResults.map((poi) => poi.id)).toEqual(['poi-toilet'])
const secondResults = await repository.searchPois()
expect(secondResults.some((poi) => poi.id === 'space-space-theater')).toBe(true)
expect(getFloorSpaces).toHaveBeenCalledTimes(4)
})
it('补充来源失败不会阻止核心点位结果缓存', async () => {
const getFloorPois = vi.fn().mockResolvedValue([floorPoi])
const getFloorSpaces = vi.fn().mockResolvedValue([theaterSpace])
const getFloorBusinessPois = vi.fn().mockRejectedValue(new Error('business offline'))
const provider = createProvider({
getFloorPois,
getFloorSpaces,
getFloorBusinessPois
})
const repository = new SgsSdkGuideRepository(provider)
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
await repository.listPois()
await repository.listPois()
expect(getFloorPois).toHaveBeenCalledTimes(1)
expect(getFloorSpaces).toHaveBeenCalledTimes(1)
expect(getFloorBusinessPois).toHaveBeenCalledTimes(1)
})
it('楼层高度来源短暂失败时不缓存缺失的空间点位', async () => {
const getFloorPois = vi.fn()
.mockRejectedValueOnce(new Error('pois offline'))
.mockRejectedValueOnce(new Error('pois offline'))
.mockResolvedValue([floorPoi])
const provider = createProvider({ getFloorPois })
const repository = new SgsSdkGuideRepository(provider)
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
await expect(repository.searchPois()).rejects.toThrow('点位数据加载失败,请检查网络后重试')
const recoveredResults = await repository.searchPois()
expect(recoveredResults.find((poi) => poi.id === 'space-space-theater')?.positionGltf)
.toEqual([5, 12, 5])
expect(getFloorPois).toHaveBeenCalledTimes(4)
})
it('所有核心楼层与空间请求失败时返回明确的可重试错误', async () => {
const provider = createProvider({
getFloorPois: vi.fn().mockRejectedValue(new Error('pois offline')),
getFloorSpaces: vi.fn().mockRejectedValue(new Error('spaces offline'))
})
const repository = new SgsSdkGuideRepository(provider)
vi.spyOn(console, 'warn').mockImplementation(() => undefined)
await expect(repository.searchPois()).rejects.toThrow('点位数据加载失败,请检查网络后重试')
})
it('将同楼层编号售票机渲染为一个逻辑对象并保留全部物理锚点', async () => {
const numberedTicketMachines = [
{ id: '5682', name: 'L1_售票机_01', x: 10 },
{ id: '5683', name: 'L1_售票机_02', x: 20 },
{ id: '5684', name: 'L1_售票机_03', x: 30 },
{ id: '5685', name: 'L1_售票机_04', x: 40 }
].map(({ id, name, x }) => ({
id,
name,
type: 'ticket_office',
floorId: '101',
position: { x, y: 12, z: x }
}))
const provider = createProvider({
getFloorPois: vi.fn().mockResolvedValue([
...numberedTicketMachines,
{
id: '5591',
name: '售票机',
type: 'ticket_office',
floorId: '101',
position: { x: 50, y: 12, z: 50 }
},
{
id: '352502409978861752',
name: '展厅售票点',
type: 'ticket_office',
floorId: '101',
position: { x: 60, y: 12, z: 60 }
}
]),
getFloorSpaces: vi.fn().mockResolvedValue([])
})
const repository = new SgsSdkGuideModelRepository(provider)
const renderPois = await repository.loadFloorPois('101')
const numberedSeries = renderPois.find((poi) => poi.id === '5682')
expect(numberedSeries).toMatchObject({
name: '售票机',
positionGltf: [10, 12, 10],
displayPolicy: {
labelVisible: true,
minLabelTier: 'tight'
},
mergedDisplayPositions: [
[20, 12, 20],
[30, 12, 30],
[40, 12, 40]
],
mergedMarkerPositions: [
[20, 12, 20],
[30, 12, 30],
[40, 12, 40]
]
})
expect(renderPois.map((poi) => poi.id)).toEqual(expect.arrayContaining([
'5682',
'5591',
'352502409978861752'
]))
expect(renderPois.find((poi) => poi.id === '5591')?.displayPolicy).toMatchObject({
labelVisible: true,
minLabelTier: 'tight'
})
expect(renderPois.find((poi) => poi.id === '352502409978861752')?.displayPolicy).toMatchObject({
labelVisible: true,
minLabelTier: 'tight'
})
expect(renderPois).toHaveLength(3)
})
it('仅把 FLOOR_EXIT 导航点转换为楼层出入口标签', async () => {
const provider = createProvider({
getFloorPois: vi.fn().mockResolvedValue([]),
getFloorSpaces: vi.fn().mockResolvedValue([]),
getNavigablePlaces: vi.fn().mockResolvedValue([
{
id: '2077983437229297849',
name: '展览入口',
category: 'door',
anchorType: 'FLOOR_EXIT',
floorId: '101',
position: { x: -28.536788, y: 1, z: -4.662431 }
},
{
id: '2077983437229297850',
name: '观众次入口',
category: 'door',
anchorType: 'FLOOR_EXIT',
floorId: '101',
position: { x: -106.745851, y: 1, z: 76.900369 }
},
{
id: '2077983437229297851',
name: '影剧院入口',
category: 'door',
anchorType: 'FLOOR_EXIT',
floorId: '101',
position: { x: -8.49571, y: 1, z: 11.77092 }
},
{
id: 'space-entrance',
name: '普通空间入口',
category: 'door',
anchorType: 'SPACE_ENTRANCE',
floorId: '101',
position: { x: 1, y: 1, z: 1 }
},
{
id: 'poi-entrance',
name: '普通点位入口',
category: 'door',
anchorType: 'POI_ENTRANCE',
floorId: '101',
position: { x: 2, y: 1, z: 2 }
}
])
})
const repository = new SgsSdkGuideModelRepository(provider)
const renderPois = await repository.loadFloorPois('101')
const floorExits = renderPois.filter((poi) => poi.id.startsWith('floor-exit-'))
expect(floorExits.map((poi) => poi.name)).toEqual([
'展览入口',
'观众次入口',
'影剧院入口'
])
expect(floorExits[0]).toMatchObject({
positionGltf: [-28.536788, 1, -4.662431],
primaryCategory: 'navigation_anchor',
iconType: 'entrance_exit',
displayPolicy: {
labelVisible: true,
minLabelTier: 'tight'
}
})
expect(renderPois.some((poi) => poi.id.includes('space-entrance'))).toBe(false)
expect(renderPois.some((poi) => poi.id.includes('poi-entrance'))).toBe(false)
})
})