mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 13:36:48 +00:00
66 lines
3.0 KiB
TypeScript
66 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { analyzeRouteGeometry, focusRouteProfileAtDistance, parseRenderableRouteGeometry } from './routeGeometry'
|
|
|
|
describe('analyzeRouteGeometry', () => {
|
|
it('shares a validated rendering parser that retains valid elevation values', () => {
|
|
expect(parseRenderableRouteGeometry('[[48,11,512.125],[48.01,11.02,520.75]]'))
|
|
.toEqual([[48, 11, 512.125], [48.01, 11.02, 520.75]])
|
|
})
|
|
|
|
it('derives distance, elevation extrema, gain, loss and cumulative-distance samples together', () => {
|
|
const analysis = analyzeRouteGeometry(JSON.stringify([
|
|
[0, 0, 100],
|
|
[0, 0.01, 130],
|
|
[0, 0.03, 110],
|
|
]))
|
|
|
|
expect(analysis).not.toBeNull()
|
|
expect(analysis!.routeCoordinates).toEqual([[0, 0], [0, 0.01], [0, 0.03]])
|
|
expect(analysis!.distanceKm).toBeCloseTo(3.3358, 3)
|
|
expect(analysis!.minEle).toBe(100)
|
|
expect(analysis!.maxEle).toBe(130)
|
|
expect(analysis!.gain).toBe(30)
|
|
expect(analysis!.loss).toBe(20)
|
|
expect(analysis!.distanceIndexedProfileSamples).toHaveLength(3)
|
|
expect(analysis!.distanceIndexedProfileSamples[1]).toMatchObject({ lat: 0, lng: 0.01 })
|
|
expect(analysis!.distanceIndexedProfileSamples[1].distanceMeters).toBeCloseTo(1111.95, 1)
|
|
expect(analysis!.distanceIndexedProfileSamples[2].distanceMeters).toBeCloseTo(3335.85, 1)
|
|
})
|
|
|
|
it('maps route endpoints and interpolates focus between prepared samples', () => {
|
|
const samples = [
|
|
{ distanceMeters: 0, elevationMeters: 100, lat: 10, lng: 20 },
|
|
{ distanceMeters: 100, elevationMeters: 200, lat: 12, lng: 24 },
|
|
{ distanceMeters: 300, elevationMeters: 300, lat: 14, lng: 28 },
|
|
]
|
|
expect(focusRouteProfileAtDistance(samples, -20)).toMatchObject({ distanceMeters: 0, elevationMeters: 100, lat: 10, lng: 20, sampleIndex: 0 })
|
|
expect(focusRouteProfileAtDistance(samples, 150)).toMatchObject({ distanceMeters: 150, elevationMeters: 225, lat: 12.5, lng: 25, sampleIndex: 1 })
|
|
expect(focusRouteProfileAtDistance(samples, 500)).toMatchObject({ distanceMeters: 300, elevationMeters: 300, lat: 14, lng: 28, sampleIndex: 2 })
|
|
})
|
|
|
|
it('does not create geographic focus for samples without coordinates', () => {
|
|
expect(focusRouteProfileAtDistance([
|
|
{ distanceMeters: 0, elevationMeters: 100 },
|
|
{ distanceMeters: 10, elevationMeters: 110 },
|
|
], 5)).toBeNull()
|
|
})
|
|
|
|
it('keeps distance but omits all elevation outputs when any point lacks elevation', () => {
|
|
const analysis = analyzeRouteGeometry(JSON.stringify([
|
|
[48, 11, 500],
|
|
[48.01, 11.01],
|
|
]))
|
|
|
|
expect(analysis?.distanceKm).toBeGreaterThan(0)
|
|
expect(analysis?.minEle).toBeNull()
|
|
expect(analysis?.maxEle).toBeNull()
|
|
expect(analysis?.gain).toBeNull()
|
|
expect(analysis?.loss).toBeNull()
|
|
expect(analysis?.distanceIndexedProfileSamples).toEqual([])
|
|
})
|
|
|
|
it.each([undefined, null, '', 'not json', '[]', '[[0,0]]', '[[0,"bad"],[1,1]]'])('returns null for unusable geometry %s', geometry => {
|
|
expect(analyzeRouteGeometry(geometry)).toBeNull()
|
|
})
|
|
})
|