aboutsummaryrefslogtreecommitdiff
path: root/internal/ridetest/ride_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/ridetest/ride_test.go')
-rw-r--r--internal/ridetest/ride_test.go146
1 files changed, 146 insertions, 0 deletions
diff --git a/internal/ridetest/ride_test.go b/internal/ridetest/ride_test.go
new file mode 100644
index 0000000..69c084d
--- /dev/null
+++ b/internal/ridetest/ride_test.go
@@ -0,0 +1,146 @@
+package ridetest
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestRideSingleSection(t *testing.T) {
+ r, err := Ride("1km at 10%")
+ require.NoError(t, err)
+
+ assert.Len(t, r.Distances(), 11)
+ assert.Equal(t, 0.0, r.Distances()[0])
+ assert.Equal(t, 1000.0, r.Distances()[10])
+ assert.Equal(t, 0.0, r.Elevations()[0])
+ assert.Equal(t, 100.0, r.Elevations()[10])
+}
+
+func TestRideSectionsWithDescentAndFlat(t *testing.T) {
+ r, err := Ride("0.5km at 10% | 0.5km at -10%")
+ require.NoError(t, err)
+
+ assert.Len(t, r.Distances(), 11)
+ assert.Equal(t, 1000.0, r.Distances()[10])
+ assert.Equal(t, 50.0, r.Elevations()[5]) // top of the first section
+ assert.Equal(t, 0.0, r.Elevations()[10]) // back to start elevation
+}
+
+func TestRideSamplingOption(t *testing.T) {
+ r, err := Ride("1km at 10%", Sampling(50))
+ require.NoError(t, err)
+
+ assert.Len(t, r.Distances(), 21)
+ assert.Equal(t, 1000.0, r.Distances()[20])
+ assert.Equal(t, 5.0, r.Elevations()[1])
+}
+
+func TestRideStartCoordHeading(t *testing.T) {
+ r, err := Ride("2km at 0%", StartCoord(43.10, 5.10), Sampling(1000))
+ require.NoError(t, err)
+
+ // Coordinates advance northeast by 0.01° per km; float64 literals like
+ // 43.11 drift in the last bits, so compare with a small tolerance.
+ require.Len(t, r.Coords(), 3)
+ assert.InDelta(t, 43.10, r.Coords()[0].Lat, 1e-9)
+ assert.InDelta(t, 5.10, r.Coords()[0].Lon, 1e-9)
+ assert.InDelta(t, 43.11, r.Coords()[1].Lat, 1e-9)
+ assert.InDelta(t, 5.11, r.Coords()[1].Lon, 1e-9)
+ assert.InDelta(t, 43.12, r.Coords()[2].Lat, 1e-9)
+ assert.InDelta(t, 5.12, r.Coords()[2].Lon, 1e-9)
+}
+
+func TestRideStartTime(t *testing.T) {
+ start := time.Date(2026, 8, 1, 10, 0, 0, 0, time.UTC)
+ r, err := Ride("1km at 0%", StartTime(start), Sampling(500))
+ require.NoError(t, err)
+
+ assert.Len(t, r.Timestamps(), 3)
+ assert.Equal(t, start, r.Timestamps()[0])
+ assert.Equal(t, start.Add(time.Second), r.Timestamps()[1])
+ assert.Equal(t, start.Add(2*time.Second), r.Timestamps()[2])
+}
+
+func TestRideStartElevation(t *testing.T) {
+ r, err := Ride("1km at 0%", StartElevation(100))
+ require.NoError(t, err)
+
+ assert.Equal(t, 100.0, r.Elevations()[0])
+ assert.Equal(t, 100.0, r.Elevations()[10])
+}
+
+func TestRideMetricsCompleteColumns(t *testing.T) {
+ r, err := Ride("0.5km at 0% hr=150 cad=80 w=200 | 0.5km at 0% hr=140 cad=70 w=150")
+ require.NoError(t, err)
+
+ heartRates, ok := r.HeartRates()
+ require.True(t, ok)
+ assert.Equal(t, 150.0, heartRates[0])
+ assert.Equal(t, 150.0, heartRates[5])
+ assert.Equal(t, 140.0, heartRates[6])
+ assert.Equal(t, 140.0, heartRates[10])
+
+ cadences, ok := r.Cadences()
+ require.True(t, ok)
+ assert.Equal(t, 80.0, cadences[0])
+ assert.Equal(t, 70.0, cadences[10])
+
+ powers, ok := r.Powers()
+ require.True(t, ok)
+ assert.Equal(t, 200.0, powers[0])
+ assert.Equal(t, 150.0, powers[10])
+}
+
+func TestRideMetricsWithoutOptions(t *testing.T) {
+ r, err := Ride("1km at 0%")
+ require.NoError(t, err)
+
+ _, ok := r.HeartRates()
+ assert.False(t, ok)
+ _, ok = r.Cadences()
+ assert.False(t, ok)
+ _, ok = r.Powers()
+ assert.False(t, ok)
+}
+
+func TestRideMetricsPartialColumnFails(t *testing.T) {
+ _, err := Ride("0.5km at 0% hr=150 | 0.5km at 0%")
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "hr=")
+}
+
+func TestRideParseErrors(t *testing.T) {
+ cases := []string{
+ "",
+ " ",
+ "|",
+ "1km at 0% |",
+ "at 7%",
+ "1km 7%",
+ "0km at 7%",
+ "-1km at 7%",
+ "1km at abc%",
+ "xyz at 7%",
+ "1km away 7%",
+ "1km at 7% foo=1",
+ "1km at 7% hr=abc",
+ }
+ for _, dsl := range cases {
+ _, err := Ride(dsl)
+ require.Error(t, err, "dsl %q", dsl)
+ }
+}
+
+func TestRideRejectsNonPositiveSampling(t *testing.T) {
+ _, err := Ride("1km at 0%", Sampling(0))
+ require.Error(t, err)
+ _, err = Ride("1km at 0%", Sampling(-10))
+ require.Error(t, err)
+}
+
+func TestMustRidePanicsOnMalformedDSL(t *testing.T) {
+ assert.Panics(t, func() { MustRide("nope") })
+}