This commit is contained in:
196
tests/unit/SdkGuideRouteRepository.spec.ts
Normal file
196
tests/unit/SdkGuideRouteRepository.spec.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { SgsSdkApiProvider } from '@/data/providers/sgsSdkApiProvider'
|
||||
import { SdkGuideRouteRepository } from '@/repositories/SdkGuideRouteRepository'
|
||||
|
||||
const floorId = '2065808921272119298'
|
||||
|
||||
const createProvider = () => {
|
||||
const planRoute = vi.fn().mockResolvedValue({
|
||||
distance: 24,
|
||||
segments: [{
|
||||
floorId,
|
||||
floorName: '1.0层',
|
||||
transferType: 'WALK',
|
||||
pathPoints: [
|
||||
{ x: 2, y: 0, z: 3 },
|
||||
{ x: 8, y: 0, z: 9 }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
return {
|
||||
getManifest: vi.fn().mockResolvedValue({
|
||||
mapId: '1',
|
||||
capabilities: { routePlanning: true },
|
||||
floors: [{
|
||||
floorId,
|
||||
floorCode: 'L1',
|
||||
floorName: '1.0层'
|
||||
}]
|
||||
}),
|
||||
getMapDiagnostics: vi.fn().mockResolvedValue({
|
||||
floors: [{
|
||||
floorId,
|
||||
floorCode: 'L1',
|
||||
floorName: '1.0层',
|
||||
status: 'OK',
|
||||
routePlanningReady: true,
|
||||
navigablePlaceCount: 1
|
||||
}]
|
||||
}),
|
||||
getNavigablePlaces: vi.fn().mockResolvedValue([{
|
||||
id: 'route-node-service-desk',
|
||||
sourceId: 'poi-service-desk',
|
||||
anchorId: 'anchor-service-desk',
|
||||
name: '服务台 出入口',
|
||||
floorId,
|
||||
floorCode: 'L1',
|
||||
floorName: '1.0层',
|
||||
x: 2,
|
||||
y: 0,
|
||||
z: 3,
|
||||
nodeId: 'start-node'
|
||||
}]),
|
||||
planRoute
|
||||
} as unknown as SgsSdkApiProvider
|
||||
}
|
||||
|
||||
describe('SdkGuideRouteRepository', () => {
|
||||
it('使用 manifest 路线能力判断就绪,不调用全图 diagnostics 慢接口', async () => {
|
||||
const provider = createProvider()
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
const readiness = await repository.getRouteReadiness()
|
||||
|
||||
expect(readiness.ready).toBe(true)
|
||||
expect(provider.getManifest).toHaveBeenCalledTimes(1)
|
||||
expect(provider.getMapDiagnostics).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('允许未预绑定路网的地图对象作为终点,并向后端提交其定位坐标', async () => {
|
||||
const provider = createProvider()
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
const route = await repository.findRoute('anchor-service-desk', {
|
||||
poiId: 'space-stamp',
|
||||
name: '文创盖章打卡',
|
||||
floorId,
|
||||
floorLabel: '1F',
|
||||
categoryLabel: '购物空间',
|
||||
positionGltf: [61.8, 1.2, 45.3]
|
||||
})
|
||||
|
||||
expect(provider.planRoute).toHaveBeenCalledWith(expect.objectContaining({
|
||||
startNodeId: 'start-node',
|
||||
endFloorId: floorId,
|
||||
endX: 61.8,
|
||||
endY: 45.3,
|
||||
endNodeId: null,
|
||||
verticalTransferPolicy: 'PREFER_ELEVATOR_ESCALATOR'
|
||||
}))
|
||||
expect(route.end.name).toBe('文创盖章打卡')
|
||||
expect(route.distanceMeters).toBe(24)
|
||||
})
|
||||
|
||||
it('保留业务对象 ID,使地图标签可精确回连到对应接入点', async () => {
|
||||
const repository = new SdkGuideRouteRepository(createProvider())
|
||||
|
||||
const targets = await repository.listRouteTargets()
|
||||
|
||||
expect(targets).toEqual([expect.objectContaining({
|
||||
routeTargetId: 'anchor-service-desk',
|
||||
poiId: 'route-node-service-desk',
|
||||
sourceId: 'poi-service-desk',
|
||||
routeNodeId: 'start-node'
|
||||
})])
|
||||
})
|
||||
|
||||
it('路线起点选择只读取当前楼层目标,不扫描全馆楼层', async () => {
|
||||
const provider = createProvider()
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
const targets = await repository.listRouteTargetsForFloor(floorId)
|
||||
|
||||
expect(targets).toHaveLength(1)
|
||||
expect(provider.getNavigablePlaces).toHaveBeenCalledTimes(1)
|
||||
expect(provider.getNavigablePlaces).toHaveBeenCalledWith(floorId)
|
||||
expect(provider.getMapDiagnostics).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('为只有 nodeId 的路网节点生成稳定兜底身份', async () => {
|
||||
const provider = createProvider()
|
||||
provider.getNavigablePlaces = vi.fn().mockResolvedValue([{
|
||||
id: null,
|
||||
sourceId: 'space-42',
|
||||
name: '球幕影院节点',
|
||||
floorId,
|
||||
floorCode: 'L1',
|
||||
floorName: '1.0层',
|
||||
x: 1,
|
||||
y: 0,
|
||||
z: 2,
|
||||
nodeId: 'node-only'
|
||||
}])
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
const targets = await repository.listRouteTargets()
|
||||
|
||||
expect(targets).toEqual([expect.objectContaining({
|
||||
routeTargetId: 'node-node-only:node-only',
|
||||
poiId: 'node-node-only',
|
||||
sourceId: 'space-42',
|
||||
routeNodeId: 'node-only'
|
||||
})])
|
||||
})
|
||||
|
||||
it('允许地图对象坐标作为起点,由路线服务负责吸附到正式路网', async () => {
|
||||
const provider = createProvider()
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
await repository.findRoute({
|
||||
poiId: 'hall-unanchored',
|
||||
name: '球幕影院',
|
||||
floorId,
|
||||
floorLabel: '1F',
|
||||
positionGltf: [1.7, 3.3, -5.6]
|
||||
}, {
|
||||
poiId: 'space-stamp',
|
||||
name: '文创盖章打卡',
|
||||
floorId,
|
||||
floorLabel: '1F',
|
||||
positionGltf: [61.8, 1.2, 45.3]
|
||||
})
|
||||
|
||||
expect(provider.planRoute).toHaveBeenCalledWith(expect.objectContaining({
|
||||
startX: 1.7,
|
||||
startY: -5.6,
|
||||
startNodeId: null,
|
||||
endNodeId: null
|
||||
}))
|
||||
})
|
||||
|
||||
it('将路线接口异常转换为不暴露内部请求细节的用户错误', async () => {
|
||||
const provider = createProvider()
|
||||
provider.planRoute = vi.fn().mockRejectedValue(new Error(
|
||||
'SGS 数据接口请求失败: 500 /app-api/gis/sdk/routes/plan body="internal response"'
|
||||
))
|
||||
const repository = new SdkGuideRouteRepository(provider)
|
||||
|
||||
await expect(repository.findRoute({
|
||||
poiId: 'start-poi',
|
||||
name: '起点',
|
||||
floorId,
|
||||
floorLabel: '1F',
|
||||
positionGltf: [1, 0, 2]
|
||||
}, {
|
||||
poiId: 'end-poi',
|
||||
name: '终点',
|
||||
floorId,
|
||||
floorLabel: '1F',
|
||||
positionGltf: [3, 0, 4]
|
||||
})).rejects.toMatchObject({
|
||||
code: 'ROUTE_SERVICE_UNAVAILABLE',
|
||||
message: '路线服务暂时不可用,请稍后重试'
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user