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

137 lines
3.9 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { GuideRouteReadiness, GuideRouteResult, GuideRouteTarget } from '@/domain/museum'
import type { GuideRouteRepository } from '@/repositories/GuideRouteRepository'
import { GuideRouteUseCase } from '@/usecases/guideRouteUseCase'
import {
clearGuidePerformanceRecords,
getGuidePerformanceRecords
} from '@/services/performance/guidePerformance'
const startTarget: GuideRouteTarget = {
routeTargetId: 'start-anchor',
poiId: 'start-poi',
name: '起点',
floorId: 'L1',
floorLabel: '1F',
positionGltf: [1, 0, 1],
routeNodeId: 'start-node'
}
const startEndpoint = {
poiId: startTarget.poiId,
name: startTarget.name,
floorId: startTarget.floorId,
floorLabel: startTarget.floorLabel,
routeNodeId: startTarget.routeNodeId,
position: [1, 0, 1] as [number, number, number]
}
const endTarget: GuideRouteTarget = {
routeTargetId: 'end-anchor',
poiId: 'end-poi',
name: '终点',
floorId: 'L2',
floorLabel: '2F',
positionGltf: [2, 0, 2],
routeNodeId: 'end-node'
}
const endEndpoint = {
poiId: endTarget.poiId,
name: endTarget.name,
floorId: endTarget.floorId,
floorLabel: endTarget.floorLabel,
routeNodeId: endTarget.routeNodeId,
position: [2, 0, 2] as [number, number, number]
}
const route: GuideRouteResult = {
id: 'route-1',
start: startEndpoint,
end: endEndpoint,
distanceMeters: 18.6,
floorSegments: [],
nodeIds: [],
points: [],
connectorPoints: [],
transitions: []
}
const ready: GuideRouteReadiness = {
ready: true,
message: '',
requiredData: []
}
describe('GuideRouteUseCase performance', () => {
beforeEach(() => {
clearGuidePerformanceRecords()
})
it('records a successful cross-floor route calculation without location names', async () => {
const repository = {
getRouteReadiness: vi.fn().mockResolvedValue(ready),
listRouteTargets: vi.fn().mockResolvedValue([startTarget, endTarget]),
findRoute: vi.fn().mockResolvedValue(route)
} satisfies GuideRouteRepository
const useCase = new GuideRouteUseCase(repository)
await expect(useCase.planRoute({
startPoiId: startTarget.poiId,
startTarget,
endTarget
})).resolves.toMatchObject({ route, error: '' })
expect(getGuidePerformanceRecords()).toEqual(expect.arrayContaining([
expect.objectContaining({
kind: 'interaction',
name: 'route-plan',
outcome: 'success',
detail: {
startFloorId: 'L1',
endFloorId: 'L2',
coordinateFallback: false,
distanceMeters: 19,
floorSegmentCount: 0
}
})
]))
})
it('hides repository URLs and response bodies from route error messages', async () => {
const repository = {
getRouteReadiness: vi.fn().mockResolvedValue(ready),
listRouteTargets: vi.fn().mockResolvedValue([startTarget, endTarget]),
findRoute: vi.fn().mockRejectedValue(new Error(
'SGS 数据接口请求失败: 500 /app-api/gis/sdk/routes/plan body="internal response"'
))
} satisfies GuideRouteRepository
const useCase = new GuideRouteUseCase(repository)
await expect(useCase.planRoute({
startPoiId: startTarget.poiId,
startTarget,
endTarget
})).resolves.toEqual({
route: null,
error: '路线服务暂时不可用,请稍后重试'
})
})
it('hides repository errors while reading route readiness', async () => {
const repository = {
getRouteReadiness: vi.fn().mockRejectedValue(new Error(
'SGS 数据接口请求失败: 500 /app-api/gis/sdk/maps/1/manifest body="internal response"'
)),
listRouteTargets: vi.fn().mockResolvedValue([]),
findRoute: vi.fn()
} satisfies GuideRouteRepository
const useCase = new GuideRouteUseCase(repository)
await expect(useCase.getRouteReadiness()).resolves.toMatchObject({
ready: false,
message: '路线服务暂时不可用,请稍后重试'
})
})
})