584 lines
21 KiB
TypeScript
584 lines
21 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
resolvePoiCategory,
|
|
type PoiCategoryId
|
|
} from '@/domain/poiCategories'
|
|
import type { SgsSdkApiProvider, SgsSdkManifestPayload } from '@/data/providers/sgsSdkApiProvider'
|
|
import type { StaticNavAssetsProvider } from '@/data/providers/staticNavAssetsProvider'
|
|
import {
|
|
canonicalizeVisitorSearchPois,
|
|
SgsSdkGuideRepository,
|
|
StaticGuideRepository
|
|
} from '@/repositories/GuideRepository'
|
|
import {
|
|
SgsSdkGuideModelRepository,
|
|
StaticGuideModelRepository
|
|
} from '@/repositories/GuideModelRepository'
|
|
|
|
const manifest: SgsSdkManifestPayload = {
|
|
mapId: 'museum',
|
|
floors: [{
|
|
floorId: 'L1',
|
|
floorCode: 'L1',
|
|
floorName: '1F',
|
|
sortOrder: 1
|
|
}]
|
|
}
|
|
|
|
const position = (x: number): [number, number, number] => [x, 12, x]
|
|
|
|
const allQuickCategoryIds: readonly PoiCategoryId[] = [
|
|
'exhibition-hall',
|
|
'cinema',
|
|
'ticket-office',
|
|
'dining',
|
|
'shopping',
|
|
'service-center',
|
|
'restroom',
|
|
'nursing-room',
|
|
'elevator',
|
|
'escalator'
|
|
]
|
|
|
|
const floorSpaces = [
|
|
{ id: 'space-hall', name: '地球展厅', type: 'exhibition_hall', floorId: 'L1', center: { x: 1, y: 12, z: 1 } },
|
|
{ id: 'space-cinema', name: '穹幕影院', type: 'theater', floorId: 'L1', center: { x: 2, y: 12, z: 2 } },
|
|
{ id: 'space-dining', name: '餐饮区', type: 'restaurant', floorId: 'L1', center: { x: 3, y: 12, z: 3 } },
|
|
{ id: 'space-shopping', name: '文创商店', type: 'commercial', floorId: 'L1', center: { x: 4, y: 12, z: 4 } },
|
|
{ id: 'space-private-tea', name: '茶水间', type: 'service_space', floorId: 'L1', center: { x: 5, y: 12, z: 5 } },
|
|
{ id: 'space-private-vip', name: '贵宾接待区', type: 'service_space', floorId: 'L1', center: { x: 6, y: 12, z: 6 } },
|
|
{
|
|
id: 'space-public-rest',
|
|
name: '游客休息区',
|
|
type: 'service_space',
|
|
floorId: 'L1',
|
|
center: { x: 7, y: 12, z: 7 },
|
|
visitorVisible: true
|
|
}
|
|
]
|
|
|
|
const floorPois = [
|
|
{ id: 'ticket', name: '售票处', type: 'ticket_office', floorId: 'L1', position: { x: 10, y: 12, z: 10 } },
|
|
{ id: 'service', name: '咨询服务台', type: 'service_desk', floorId: 'L1', position: { x: 11, y: 12, z: 11 } },
|
|
{
|
|
id: 'restroom',
|
|
name: '女卫 01',
|
|
type: 'toilet',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'shared-service-zone',
|
|
position: { x: 12, y: 12, z: 12 }
|
|
},
|
|
{ id: 'nursing', name: '母婴室', type: 'mother_baby_room', floorId: 'L1', position: { x: 13, y: 12, z: 13 } },
|
|
{
|
|
id: 'elevator',
|
|
name: '无障碍电梯',
|
|
type: 'elevator',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'shared-service-zone',
|
|
position: { x: 14, y: 12, z: 14 }
|
|
},
|
|
{ id: 'escalator', name: '自动扶梯', type: 'escalator', floorId: 'L1', position: { x: 15, y: 12, z: 15 } },
|
|
{
|
|
id: 'poi-dining',
|
|
name: '餐饮区',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'space-dining',
|
|
spatialAreaName: '餐饮区',
|
|
position: { x: 3, y: 12, z: 3 }
|
|
},
|
|
{ id: 'door', name: '北入口', type: 'entrance_exit', floorId: 'L1', position: { x: 16, y: 12, z: 16 } },
|
|
{ id: 'anchor', name: '入口锚点', type: 'entrance_anchor', floorId: 'L1', position: { x: 17, y: 12, z: 17 } },
|
|
{ id: 'route-node', name: '路线节点', type: 'route_node', floorId: 'L1', position: { x: 18, y: 12, z: 18 } },
|
|
{ id: 'guide-stop', name: '讲解点', type: 'operation_experience', floorId: 'L1', position: { x: 19, y: 12, z: 19 } }
|
|
]
|
|
|
|
const businessPois = [
|
|
{
|
|
id: 'business-dining',
|
|
name: '餐饮区',
|
|
type: 'restaurant',
|
|
poiGroup: 'BUSINESS',
|
|
businessType: 'restaurant',
|
|
spatialAreaId: 'space-dining',
|
|
spatialAreaName: '餐饮区',
|
|
floorId: 'L1',
|
|
position: { x: 3, y: 12, z: 3 }
|
|
},
|
|
{
|
|
id: 'business-shopping',
|
|
name: '文创商店',
|
|
type: 'shop',
|
|
poiGroup: 'BUSINESS',
|
|
businessType: 'shop',
|
|
spatialAreaId: 'space-shopping',
|
|
spatialAreaName: '文创商店',
|
|
floorId: 'L1',
|
|
position: { x: 4, y: 12, z: 4 }
|
|
}
|
|
]
|
|
|
|
const createSgsProvider = (overrides: Partial<SgsSdkApiProvider> = {}) => ({
|
|
getManifest: vi.fn().mockResolvedValue(manifest),
|
|
getFloorPois: vi.fn().mockResolvedValue(floorPois),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue(businessPois),
|
|
getFloorSpaces: vi.fn().mockResolvedValue(floorSpaces),
|
|
getNavigablePlaces: vi.fn().mockResolvedValue([
|
|
{ id: 'nav-door', name: '入口', type: 'navigable_place', floorId: 'L1', position: { x: 20, y: 12, z: 20 } }
|
|
]),
|
|
...overrides
|
|
}) as unknown as SgsSdkApiProvider
|
|
|
|
describe('GuideRepository visitor search contracts', () => {
|
|
it('uses spaces for default browse, exposes all ten quick categories, and never returns anchors', async () => {
|
|
const provider = createSgsProvider()
|
|
const repository = new SgsSdkGuideRepository(provider)
|
|
|
|
const [defaultResults, availability, privateKeyword, publicKeyword] = await Promise.all([
|
|
repository.listDestinationPois('L1'),
|
|
repository.getQuickFindCategoryAvailability('L1'),
|
|
repository.searchPois('茶水间', 'L1'),
|
|
repository.searchPois('游客休息区', 'L1')
|
|
])
|
|
|
|
expect(defaultResults.map((poi) => poi.id)).toEqual(expect.arrayContaining([
|
|
'hall-space-hall',
|
|
'hall-space-cinema',
|
|
'space-space-dining',
|
|
'space-space-shopping',
|
|
'space-space-public-rest'
|
|
]))
|
|
for (const privatePoiId of ['space-space-private-tea', 'space-space-private-vip']) {
|
|
expect(defaultResults.map((poi) => poi.id)).not.toContain(privatePoiId)
|
|
}
|
|
expect(privateKeyword).toEqual([])
|
|
expect(publicKeyword.map((poi) => poi.id)).toEqual(['space-space-public-rest'])
|
|
expect(defaultResults.map((poi) => poi.id)).not.toEqual(expect.arrayContaining([
|
|
'restroom',
|
|
'elevator',
|
|
'ticket',
|
|
'door',
|
|
'anchor',
|
|
'route-node',
|
|
'guide-stop'
|
|
]))
|
|
expect(availability).toEqual(allQuickCategoryIds.map((id) => ({
|
|
id,
|
|
count: 1,
|
|
disabled: false
|
|
})))
|
|
|
|
await Promise.all(allQuickCategoryIds.map(async (categoryId) => {
|
|
const results = await repository.listQuickFindPois(categoryId, 'L1')
|
|
expect(results).toHaveLength(1)
|
|
expect(results[0].floorId).toBe('L1')
|
|
expect(results[0].positionGltf).toBeDefined()
|
|
expect(resolvePoiCategory(results[0])?.id).toBe(categoryId)
|
|
}))
|
|
|
|
const renderPois = await new SgsSdkGuideModelRepository(provider, repository).loadFloorPois('L1')
|
|
const renderPoiIds = new Set(renderPois.map((poi) => poi.id))
|
|
// Facilities in one spatial area are distinct visitor places and must both
|
|
// survive model marker deduplication.
|
|
expect(renderPoiIds.has('restroom')).toBe(true)
|
|
expect(renderPoiIds.has('elevator')).toBe(true)
|
|
expect(renderPoiIds.has('space-space-public-rest')).toBe(true)
|
|
for (const hiddenPoiId of ['door', 'anchor', 'route-node', 'guide-stop']) {
|
|
expect(renderPoiIds.has(hiddenPoiId)).toBe(false)
|
|
}
|
|
for (const privatePoiId of ['space-space-private-tea', 'space-space-private-vip']) {
|
|
expect(renderPoiIds.has(privatePoiId)).toBe(false)
|
|
}
|
|
const quickResultIds = (await Promise.all(allQuickCategoryIds.map((categoryId) => (
|
|
repository.listQuickFindPois(categoryId, 'L1')
|
|
)))).flat().map((poi) => poi.id)
|
|
expect([...defaultResults, ...quickResultIds.map((id) => ({ id }))]
|
|
.every((poi) => renderPoiIds.has(poi.id))).toBe(true)
|
|
})
|
|
|
|
it('normalizes restaurant/shop sources, deduplicates a real place, and excludes non-visitor search records', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider())
|
|
|
|
const [dining, shopping, keywordDining, keywordRestroom, hiddenKeyword] = await Promise.all([
|
|
repository.listQuickFindPois('dining', 'L1'),
|
|
repository.listQuickFindPois('shopping', 'L1'),
|
|
repository.searchPois('餐饮', 'L1'),
|
|
repository.searchPois('洗手间', 'L1'),
|
|
repository.searchPois('入口', 'L1')
|
|
])
|
|
|
|
expect(dining.map((poi) => poi.id)).toEqual(['space-space-dining'])
|
|
expect(shopping.map((poi) => poi.id)).toEqual(['space-space-shopping'])
|
|
expect(keywordDining.map((poi) => poi.id)).toEqual(['space-space-dining'])
|
|
expect(keywordRestroom.map((poi) => poi.id)).toEqual(['restroom'])
|
|
expect(hiddenKeyword).toEqual([])
|
|
})
|
|
|
|
it('does not resolve private direct IDs outside the visitor search pool', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider({
|
|
queryPois: vi.fn().mockResolvedValue([{
|
|
id: 'private-direct-space',
|
|
name: '茶水间',
|
|
type: 'service_space',
|
|
floorId: 'L1',
|
|
visitorVisible: false,
|
|
position: { x: 30, y: 12, z: 30 }
|
|
}])
|
|
}))
|
|
|
|
await expect(repository.getPoiById('private-direct-space')).resolves.toBeNull()
|
|
})
|
|
|
|
it('keeps private and structural space duplicates out of search lists and map markers', async () => {
|
|
const provider = createSgsProvider({
|
|
getFloorPois: vi.fn().mockResolvedValue([
|
|
{
|
|
id: 'poi-private-dining',
|
|
name: '西侧餐饮区',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'space-private-dining',
|
|
position: { x: 30, y: 12, z: 30 }
|
|
},
|
|
{
|
|
id: 'poi-service-space',
|
|
name: '服务空间',
|
|
type: 'service_space',
|
|
floorId: 'L1',
|
|
position: { x: 31, y: 12, z: 31 }
|
|
}
|
|
]),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue([]),
|
|
getFloorSpaces: vi.fn().mockResolvedValue([
|
|
{
|
|
id: 'space-private-dining',
|
|
name: '西侧餐饮区',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
visitorVisible: false,
|
|
center: { x: 30, y: 12, z: 30 }
|
|
},
|
|
{
|
|
id: 'space-private-cinema',
|
|
name: '私享影院',
|
|
type: 'theater',
|
|
floorId: 'L1',
|
|
visitorVisible: false,
|
|
center: { x: 32, y: 12, z: 32 }
|
|
},
|
|
{
|
|
id: 'space-route-node',
|
|
name: '导航区域',
|
|
type: 'navigable_place',
|
|
floorId: 'L1',
|
|
center: { x: 33, y: 12, z: 33 }
|
|
}
|
|
]),
|
|
getNavigablePlaces: vi.fn().mockResolvedValue([])
|
|
})
|
|
const repository = new SgsSdkGuideRepository(provider)
|
|
const modelRepository = new SgsSdkGuideModelRepository(provider, repository)
|
|
|
|
const [defaultResults, dining, cinema, privateKeyword, serviceKeyword, structuralKeyword, renderPois] = await Promise.all([
|
|
repository.listDestinationPois('L1'),
|
|
repository.listQuickFindPois('dining', 'L1'),
|
|
repository.listQuickFindPois('cinema', 'L1'),
|
|
repository.searchPois('西侧餐饮区', 'L1'),
|
|
repository.searchPois('服务空间', 'L1'),
|
|
repository.searchPois('导航区域', 'L1'),
|
|
modelRepository.loadFloorPois('L1')
|
|
])
|
|
|
|
expect(defaultResults).toEqual([])
|
|
expect(dining).toEqual([])
|
|
expect(cinema).toEqual([])
|
|
expect(privateKeyword).toEqual([])
|
|
expect(serviceKeyword).toEqual([])
|
|
expect(structuralKeyword).toEqual([])
|
|
expect(renderPois).toEqual([])
|
|
})
|
|
|
|
it('merges source-place duplicates before returning canonical visitor IDs', () => {
|
|
const basePoi = {
|
|
floorId: 'L1',
|
|
floorLabel: '1F',
|
|
primaryCategory: { id: 'space_restaurant', label: '餐饮', iconType: 'restaurant' },
|
|
categories: [{ id: 'space_restaurant', label: '餐饮', iconType: 'restaurant' }],
|
|
positionGltf: [40, 12, 40] as [number, number, number],
|
|
accessible: false,
|
|
kind: 'facility' as const,
|
|
sourcePlaceId: 'place-cafe'
|
|
}
|
|
|
|
const results = canonicalizeVisitorSearchPois([
|
|
{ ...basePoi, id: 'poi-cafe-a', name: '中庭咖啡' },
|
|
{
|
|
...basePoi,
|
|
id: 'poi-cafe-b',
|
|
name: '中庭咖啡取餐台',
|
|
positionGltf: [41, 12, 41]
|
|
}
|
|
])
|
|
|
|
expect(results.map((poi) => poi.id)).toEqual(['poi-cafe-a'])
|
|
})
|
|
|
|
it('deduplicates co-located sources when they do not provide a shared spatial area ID', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider({
|
|
getFloorPois: vi.fn().mockResolvedValue([{
|
|
id: 'poi-cafe',
|
|
name: '中庭咖啡厅',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
position: { x: 40, y: 12, z: 40 }
|
|
}]),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue([{
|
|
id: 'business-cafe',
|
|
name: '中庭咖啡厅',
|
|
type: 'restaurant',
|
|
poiGroup: 'BUSINESS',
|
|
businessType: 'restaurant',
|
|
floorId: 'L1',
|
|
position: { x: 40, y: 12, z: 40 }
|
|
}]),
|
|
getFloorSpaces: vi.fn().mockResolvedValue([{
|
|
id: 'space-cafe',
|
|
name: '中庭咖啡厅',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
center: { x: 40, y: 12, z: 40 }
|
|
}])
|
|
}))
|
|
|
|
const [quickFind, keyword] = await Promise.all([
|
|
repository.listQuickFindPois('dining', 'L1'),
|
|
repository.searchPois('咖啡', 'L1')
|
|
])
|
|
|
|
expect(quickFind).toHaveLength(1)
|
|
expect(keyword).toHaveLength(1)
|
|
expect(quickFind[0]).toMatchObject({ kind: 'space', name: '中庭咖啡厅' })
|
|
expect(keyword.map((poi) => poi.id)).toEqual(quickFind.map((poi) => poi.id))
|
|
})
|
|
|
|
it('deduplicates source representations linked to one space before positional fallback', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider({
|
|
getFloorPois: vi.fn().mockResolvedValue([{
|
|
id: 'poi-cafe-counter',
|
|
name: '咖啡取餐台',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'space-cafe',
|
|
position: { x: 45, y: 12, z: 45 }
|
|
}]),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue([{
|
|
id: 'business-cafe',
|
|
name: '中庭咖啡厅',
|
|
type: 'restaurant',
|
|
poiGroup: 'BUSINESS',
|
|
businessType: 'restaurant',
|
|
floorId: 'L1',
|
|
spatialAreaId: 'space-cafe',
|
|
position: { x: 46, y: 12, z: 46 }
|
|
}]),
|
|
getFloorSpaces: vi.fn().mockResolvedValue([{
|
|
id: 'space-cafe',
|
|
name: '中庭咖啡厅',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
center: { x: 47, y: 12, z: 47 }
|
|
}])
|
|
}))
|
|
|
|
const [quickFind, keyword] = await Promise.all([
|
|
repository.listQuickFindPois('dining', 'L1'),
|
|
repository.searchPois('咖啡', 'L1')
|
|
])
|
|
|
|
expect(quickFind).toEqual([
|
|
expect.objectContaining({ id: 'space-space-cafe', kind: 'space' })
|
|
])
|
|
expect(keyword.map((poi) => poi.id)).toEqual(quickFind.map((poi) => poi.id))
|
|
})
|
|
|
|
it('keeps an unlinked commercial POI out of default destinations but exposes it through shopping', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider({
|
|
getFloorPois: vi.fn().mockResolvedValue([]),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue([{
|
|
id: 'business-commercial',
|
|
name: '纪念品商店',
|
|
type: 'commercial',
|
|
poiGroup: 'BUSINESS',
|
|
businessType: 'commercial',
|
|
floorId: 'L1',
|
|
position: { x: 30, y: 12, z: 30 }
|
|
}]),
|
|
getFloorSpaces: vi.fn().mockResolvedValue([])
|
|
}))
|
|
|
|
await expect(repository.listDestinationPois('L1')).resolves.toEqual([])
|
|
await expect(repository.listQuickFindPois('shopping', 'L1')).resolves.toMatchObject([
|
|
{ id: 'business-commercial', kind: 'facility' }
|
|
])
|
|
})
|
|
|
|
it('keeps an unlinked restaurant POI out of default destinations but exposes it through dining and keyword search', async () => {
|
|
const repository = new SgsSdkGuideRepository(createSgsProvider({
|
|
getFloorPois: vi.fn().mockResolvedValue([{
|
|
id: 'poi-restaurant',
|
|
name: '咖啡餐饮点',
|
|
type: 'restaurant',
|
|
floorId: 'L1',
|
|
position: { x: 31, y: 12, z: 31 }
|
|
}]),
|
|
getFloorBusinessPois: vi.fn().mockResolvedValue([]),
|
|
getFloorSpaces: vi.fn().mockResolvedValue([])
|
|
}))
|
|
|
|
await expect(repository.listDestinationPois('L1')).resolves.toEqual([])
|
|
await expect(repository.listQuickFindPois('dining', 'L1')).resolves.toMatchObject([
|
|
{ id: 'poi-restaurant', kind: 'facility' }
|
|
])
|
|
await expect(repository.searchPois('咖啡', 'L1')).resolves.toMatchObject([
|
|
{ id: 'poi-restaurant' }
|
|
])
|
|
})
|
|
|
|
it('falls back to static hall destinations when no independent space source exists', async () => {
|
|
const provider = {
|
|
baseUrl: '',
|
|
loadPoiIndex: vi.fn().mockResolvedValue([
|
|
{
|
|
id: 'static-hall',
|
|
name: '地球展厅',
|
|
floorId: 'L1',
|
|
primaryCategory: 'touring_poi',
|
|
primaryCategoryZh: '展厅',
|
|
iconType: 'exhibition_hall',
|
|
positionGltf: position(1)
|
|
},
|
|
{
|
|
id: 'static-restroom',
|
|
name: '男卫生间',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '服务设施',
|
|
iconType: 'toilet',
|
|
positionGltf: position(2)
|
|
},
|
|
{
|
|
id: 'static-service-desk',
|
|
name: '服务台',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(3)
|
|
},
|
|
{
|
|
id: 'static-tea-room',
|
|
name: '茶水间',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(4)
|
|
},
|
|
{
|
|
id: 'static-vip-reception',
|
|
name: '贵宾接待区',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(5)
|
|
},
|
|
{
|
|
id: 'static-vip-restroom',
|
|
name: '贵宾卫生间',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(6)
|
|
}
|
|
])
|
|
} as unknown as StaticNavAssetsProvider
|
|
const repository = new StaticGuideRepository(provider)
|
|
|
|
await expect(repository.listDestinationPois('L1')).resolves.toMatchObject([
|
|
{ id: 'static-hall', kind: 'hall' }
|
|
])
|
|
await expect(repository.listQuickFindPois('restroom', 'L1')).resolves.toMatchObject([
|
|
{ id: 'static-restroom' }
|
|
])
|
|
await expect(repository.searchPois('洗手间', 'L1')).resolves.toMatchObject([
|
|
{ id: 'static-restroom' }
|
|
])
|
|
await expect(repository.searchPois('茶水间', 'L1')).resolves.toEqual([])
|
|
await expect(repository.searchPois('贵宾', 'L1')).resolves.toEqual([])
|
|
await expect(repository.getPoiById('static-tea-room')).resolves.toBeNull()
|
|
await expect(repository.getPoiById('static-vip-restroom')).resolves.toBeNull()
|
|
await expect(repository.searchPois('服务', 'L1')).resolves.toEqual([
|
|
expect.objectContaining({ id: 'static-service-desk' })
|
|
])
|
|
await expect(repository.listQuickFindPois('service-center', 'L1')).resolves.toMatchObject([
|
|
{ id: 'static-service-desk' }
|
|
])
|
|
await expect(repository.getQuickFindCategoryAvailability('L1')).resolves.toEqual(expect.arrayContaining([
|
|
{ id: 'service-center', count: 1, disabled: false },
|
|
{ id: 'restroom', count: 1, disabled: false }
|
|
]))
|
|
})
|
|
|
|
it('keeps static guide records out of the model render pool', async () => {
|
|
const provider = {
|
|
loadFloorIndex: vi.fn().mockResolvedValue({
|
|
floors: [{ floorId: 'L1', poiDataAsset: 'poi_by_floor/L1.json' }]
|
|
}),
|
|
loadFloorPois: vi.fn().mockResolvedValue([
|
|
{
|
|
id: 'static-hall',
|
|
name: '地球展厅',
|
|
floorId: 'L1',
|
|
primaryCategory: 'touring_poi',
|
|
primaryCategoryZh: '展厅',
|
|
iconType: 'exhibition_hall',
|
|
positionGltf: position(1)
|
|
},
|
|
{
|
|
id: 'static-guide-point',
|
|
name: '讲解点',
|
|
floorId: 'L1',
|
|
primaryCategory: 'operation_experience',
|
|
primaryCategoryZh: '讲解点',
|
|
iconType: 'guide',
|
|
positionGltf: position(2)
|
|
},
|
|
{
|
|
id: 'static-private-tea',
|
|
name: '茶水间',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(3)
|
|
},
|
|
{
|
|
id: 'static-vip-restroom',
|
|
name: '贵宾卫生间',
|
|
floorId: 'L1',
|
|
primaryCategory: 'basic_service_facility',
|
|
primaryCategoryZh: '基础服务设施',
|
|
iconType: 'restroom',
|
|
positionGltf: position(4)
|
|
}
|
|
])
|
|
} as unknown as StaticNavAssetsProvider
|
|
|
|
const renderPois = await new StaticGuideModelRepository(provider).loadFloorPois('L1')
|
|
|
|
expect(renderPois.map((poi) => poi.id)).toEqual(['static-hall'])
|
|
})
|
|
})
|