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()) }