package ride_test import ( "testing" "github.com/martinlehoux/biking_home/ride" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestDetectElevationOutliers_TunnelSpike(t *testing.T) { // Simulate ride 754 tunnel: steady then spike 46m over 7m (grade 657%), then normal. distances := []float64{0, 10, 20, 27, 34} // 7m gap at idx 3 elevations := []float64{100, 101, 102, 148, 149} outliers := ride.DetectElevationOutliers(distances, elevations, 0.5) require.Len(t, outliers, 1) assert.Equal(t, 2, outliers[0].StartIdx) // expanded by 1 assert.Equal(t, 4, outliers[0].EndIdx) assert.Greater(t, outliers[0].MaxGrade, 5.0) } func TestDetectElevationOutliers_IgnoresSmallJitter(t *testing.T) { distances := []float64{0, 0.5, 1.0, 1.5} elevations := []float64{100, 100.3, 100.6, 100.9} // 0.3m over 0.5m =60% but abs de <1.5 outliers := ride.DetectElevationOutliers(distances, elevations, 0.5) assert.Empty(t, outliers) } func TestDetectElevationOutliers_IgnoresGentleSlope(t *testing.T) { distances := []float64{0, 10, 20, 30} elevations := []float64{100, 102, 104, 106} // 20% grade outliers := ride.DetectElevationOutliers(distances, elevations, 0.5) assert.Empty(t, outliers) } func TestLinearFix_Interpolates(t *testing.T) { distances := []float64{0, 10, 20, 30, 40} elevations := []float64{100, 110, 999, 130, 140} zones := []ride.FixZone{{StartIdx: 1, EndIdx: 3, StartKm: 0.01, EndKm: 0.03}} n := ride.LinearFix(distances, elevations, zones) assert.Equal(t, 1, n) assert.InDelta(t, 120, elevations[2], 0.01) } func TestResolveIndex_ByKm(t *testing.T) { distances := []float64{0, 1000, 2000, 3000} idx, err := ride.ResolveIndex(distances, "1.5km") require.NoError(t, err) // nearest to 1500 is idx 1 or 2 (both 500 away, picks first) assert.Contains(t, []int{1, 2}, idx) } func TestResolveIndex_ByIndex(t *testing.T) { distances := []float64{0, 1000, 2000} idx, err := ride.ResolveIndex(distances, "2") require.NoError(t, err) assert.Equal(t, 2, idx) }