aboutsummaryrefslogtreecommitdiff
path: root/ride/fit_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'ride/fit_test.go')
-rw-r--r--ride/fit_test.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/ride/fit_test.go b/ride/fit_test.go
new file mode 100644
index 0000000..9e9e0a3
--- /dev/null
+++ b/ride/fit_test.go
@@ -0,0 +1,74 @@
+package ride_test
+
+import (
+ "bytes"
+ "encoding/binary"
+ "testing"
+ "time"
+
+ "github.com/martinlehoux/biking_home/ride"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/tormoder/fit"
+)
+
+func encodeFIT(t *testing.T, fileType fit.FileType, records []*fit.RecordMsg) []byte {
+ t.Helper()
+ file, err := fit.NewFile(fileType, fit.NewHeader(fit.V20, true))
+ require.NoError(t, err)
+ file.FileId.Manufacturer = fit.ManufacturerGarmin
+ file.FileId.Type = fileType
+ file.FileId.TimeCreated = time.Date(2026, 8, 1, 7, 30, 0, 0, time.UTC)
+ switch fileType {
+ case fit.FileTypeCourse:
+ course, err := file.Course()
+ require.NoError(t, err)
+ course.Records = records
+ case fit.FileTypeActivity:
+ activity, err := file.Activity()
+ require.NoError(t, err)
+ activity.Records = records
+ }
+ var buf bytes.Buffer
+ require.NoError(t, fit.Encode(&buf, file, binary.LittleEndian))
+ return buf.Bytes()
+}
+
+func fitRecord(lat, lon, elevationM float64, ts time.Time) *fit.RecordMsg {
+ rec := fit.NewRecordMsg()
+ rec.Timestamp = ts
+ rec.PositionLat = fit.NewLatitudeDegrees(lat)
+ rec.PositionLong = fit.NewLongitudeDegrees(lon)
+ rec.Altitude = uint16((elevationM + 500) * 5)
+ rec.HeartRate = 0xFF
+ rec.Cadence = 0xFF
+ rec.Power = 0xFFFF
+ return rec
+}
+
+func TestFITRideParserParsesCourseFile(t *testing.T) {
+ base := time.Date(2026, 8, 1, 7, 30, 0, 0, time.UTC)
+ data := encodeFIT(t, fit.FileTypeCourse, []*fit.RecordMsg{
+ fitRecord(43.0, 5.0, 100, base),
+ fitRecord(43.0, 5.0, 101, base.Add(5*time.Second)), // stationary: skipped
+ fitRecord(43.001, 5.001, 200, base.Add(10*time.Second)),
+ })
+
+ parsed, err := (ride.FITRideParser{}).Parse(bytes.NewReader(data))
+ require.NoError(t, err)
+ require.Equal(t, 2, parsed.Len())
+ assert.Equal(t, 0.0, parsed.Distances[0])
+ assert.Greater(t, parsed.Distances[1], 0.0)
+ assert.Equal(t, []float64{100, 200}, parsed.Elevations)
+ assert.Equal(t, []time.Time{base, base.Add(10 * time.Second)}, parsed.Timestamps())
+ _, hasHR := parsed.HeartRates()
+ assert.False(t, hasHR, "course records carry no telemetry")
+}
+
+func TestFITRideParserRejectsFileWithoutTrack(t *testing.T) {
+ data := encodeFIT(t, fit.FileTypeSettings, nil)
+
+ _, err := (ride.FITRideParser{}).Parse(bytes.NewReader(data))
+ require.Error(t, err)
+ assert.Equal(t, "fit file type is Settings, not Activity or Course", err.Error())
+}