aboutsummaryrefslogtreecommitdiff
path: root/web/ride-filters_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'web/ride-filters_test.go')
-rw-r--r--web/ride-filters_test.go59
1 files changed, 38 insertions, 21 deletions
diff --git a/web/ride-filters_test.go b/web/ride-filters_test.go
index bf1cc6f..fd3ee13 100644
--- a/web/ride-filters_test.go
+++ b/web/ride-filters_test.go
@@ -23,7 +23,8 @@ func TestParseRideFilters(t *testing.T) {
rideFilterDateToParam: {"2026-08-31"},
rideFilterCotacolMinParam: {"50"},
rideFilterCotacolMaxParam: {"500"},
- rideFilterRouteParam: {rideRouteFilterAvailable},
+ rideFilterBikeTypeParam: {string(ride.BikeTypeRoad)},
+ rideFilterRideTypeParam: {string(ride.RideTypeTraining)},
}
filters := parseRideFilters(query)
@@ -36,7 +37,8 @@ func TestParseRideFilters(t *testing.T) {
assert.Equal(t, "2026-09-01T00:00:00Z", filters.DateToExclusive.Format(time.RFC3339))
assert.Equal(t, 50, *filters.CotacolMinPoints)
assert.Equal(t, 500, *filters.CotacolMaxPoints)
- assert.Equal(t, rideRouteFilterAvailable, filters.Route)
+ assert.Equal(t, ride.BikeTypeRoad, *filters.BikeType)
+ assert.Equal(t, ride.RideTypeTraining, *filters.RideType)
assert.True(t, filters.Active())
}
@@ -50,7 +52,8 @@ func TestParseRideFiltersIgnoresInvalidValues(t *testing.T) {
rideFilterDateToParam: {"2026-08-01"},
rideFilterCotacolMinParam: {"25"},
rideFilterCotacolMaxParam: {"25"},
- rideFilterRouteParam: {"unknown"},
+ rideFilterBikeTypeParam: {"unknown"},
+ rideFilterRideTypeParam: {"unknown"},
}
filters := parseRideFilters(query)
@@ -64,7 +67,8 @@ func TestParseRideFiltersIgnoresInvalidValues(t *testing.T) {
assert.Nil(t, filters.DateToExclusive)
assert.Nil(t, filters.CotacolMinPoints)
assert.Nil(t, filters.CotacolMaxPoints)
- assert.Empty(t, filters.Route)
+ assert.Nil(t, filters.BikeType)
+ assert.Nil(t, filters.RideType)
}
func TestParseRideFiltersTreatsFullRangesAsInactive(t *testing.T) {
@@ -88,11 +92,11 @@ func TestParseRideFiltersTreatsFullRangesAsInactive(t *testing.T) {
func TestFilterRidesUsesInclusiveBoundsAndMovingTime(t *testing.T) {
items := []ride.StoredRide{
- {Name: "lower boundary", DistanceM: 20_000, ExternalMovingTimeS: 1_800, StartDate: time.Date(2026, 8, 1, 12, 0, 0, 0, time.UTC), GPXPath: "lower.gpx"},
- {Name: "upper boundary", DistanceM: 100_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "upper.gpx"},
- {Name: "outside distance", DistanceM: 110_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "outside-distance.gpx"},
- {Name: "outside moving time", DistanceM: 100_000, ExternalMovingTimeS: 10_801, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "outside-duration.gpx"},
- {Name: "outside date", DistanceM: 100_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 9, 1, 12, 0, 0, 0, time.UTC), GPXPath: "outside-date.gpx"},
+ {Name: "lower boundary", DistanceM: 20_000, ExternalMovingTimeS: 1_800, StartDate: time.Date(2026, 8, 1, 12, 0, 0, 0, time.UTC), GPXPath: "lower.gpx", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining},
+ {Name: "upper boundary", DistanceM: 100_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "upper.gpx", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining},
+ {Name: "outside distance", DistanceM: 110_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "outside-distance.gpx", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining},
+ {Name: "outside moving time", DistanceM: 100_000, ExternalMovingTimeS: 10_801, StartDate: time.Date(2026, 8, 31, 12, 0, 0, 0, time.UTC), GPXPath: "outside-duration.gpx", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining},
+ {Name: "outside date", DistanceM: 100_000, ExternalMovingTimeS: 10_800, StartDate: time.Date(2026, 9, 1, 12, 0, 0, 0, time.UTC), GPXPath: "outside-date.gpx", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining},
}
filters := parseRideFilters(url.Values{
rideFilterDistanceMinParam: {"20"},
@@ -110,19 +114,21 @@ func TestFilterRidesUsesInclusiveBoundsAndMovingTime(t *testing.T) {
assert.Equal(t, "upper boundary", filtered[1].Name)
}
-func TestFilterRidesByRouteAvailability(t *testing.T) {
+func TestFilterRidesByBikeAndRideType(t *testing.T) {
items := []ride.StoredRide{
- {Name: "recorded", GPXPath: "recorded.gpx"},
- {Name: "metadata only"},
+ {Name: "road training", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeTraining, GPXPath: "a.gpx"},
+ {Name: "mtb race", BikeType: ride.BikeTypeMTB, RideType: ride.RideTypeRace, GPXPath: "b.gpx"},
+ {Name: "road race", BikeType: ride.BikeTypeRoad, RideType: ride.RideTypeRace, GPXPath: "c.gpx"},
}
- available := filterRides(items, parseRideFilters(url.Values{rideFilterRouteParam: {rideRouteFilterAvailable}}))
- missing := filterRides(items, parseRideFilters(url.Values{rideFilterRouteParam: {rideRouteFilterMissing}}))
+ road := filterRides(items, parseRideFilters(url.Values{rideFilterBikeTypeParam: {string(ride.BikeTypeRoad)}}))
+ race := filterRides(items, parseRideFilters(url.Values{rideFilterRideTypeParam: {string(ride.RideTypeRace)}}))
+ roadRace := filterRides(items, parseRideFilters(url.Values{rideFilterBikeTypeParam: {string(ride.BikeTypeRoad)}, rideFilterRideTypeParam: {string(ride.RideTypeRace)}}))
- require.Len(t, available, 1)
- assert.Equal(t, "recorded", available[0].Name)
- require.Len(t, missing, 1)
- assert.Equal(t, "metadata only", missing[0].Name)
+ require.Len(t, road, 2)
+ require.Len(t, race, 2)
+ require.Len(t, roadRace, 1)
+ assert.Equal(t, "road race", roadRace[0].Name)
}
func TestFilterRidesByCotacolExcludesUnavailableScores(t *testing.T) {
@@ -132,6 +138,8 @@ func TestFilterRidesByCotacolExcludesUnavailableScores(t *testing.T) {
GPXPath: testGPXPath(t, "current-cotacol.gpx"),
Name: "Current score",
Type: "Ride",
+ BikeType: ride.BikeTypeRoad,
+ RideType: ride.RideTypeTraining,
StartDate: time.Date(2026, 8, 1, 7, 0, 0, 0, time.UTC),
DistanceM: 20_000,
}
@@ -140,6 +148,8 @@ func TestFilterRidesByCotacolExcludesUnavailableScores(t *testing.T) {
GPXPath: testGPXPath(t, "stale-cotacol.gpx"),
Name: "Stale score",
Type: "Ride",
+ BikeType: ride.BikeTypeRoad,
+ RideType: ride.RideTypeTraining,
StartDate: time.Date(2026, 8, 2, 7, 0, 0, 0, time.UTC),
DistanceM: 20_000,
}
@@ -147,6 +157,8 @@ func TestFilterRidesByCotacolExcludesUnavailableScores(t *testing.T) {
ExternalID: "strava:7ba7b810-9dad-41d1-80b4-00c04fd430c8",
Name: "No score",
Type: "VirtualRide",
+ BikeType: ride.BikeTypeRoad,
+ RideType: ride.RideTypeTraining,
StartDate: time.Date(2026, 8, 3, 7, 0, 0, 0, time.UTC),
DistanceM: 20_000,
}
@@ -190,7 +202,8 @@ func TestHandlerRendersRideFilterControls(t *testing.T) {
assert.Contains(t, body, `name="duration_min"`)
assert.Contains(t, body, `name="date_from"`)
assert.Contains(t, body, `name="cotacol_min"`)
- assert.Contains(t, body, `name="route"`)
+ assert.Contains(t, body, `name="bike_type"`)
+ assert.Contains(t, body, `name="ride_type"`)
assert.Contains(t, body, `<script type="module" src="/static/ride-filters.js"></script>`)
}
@@ -198,12 +211,12 @@ func TestRideSortHeadersPreserveFilters(t *testing.T) {
filters := parseRideFilters(url.Values{
rideFilterDistanceMinParam: {"50"},
rideFilterDistanceMaxParam: {"150"},
- rideFilterRouteParam: {rideRouteFilterAvailable},
+ rideFilterBikeTypeParam: {string(ride.BikeTypeRoad)},
})
headers := rideSortHeadersWithFilters(RideSort{Column: rideSortDistance, Descending: true}, filters)
- assert.Equal(t, "/?dir=asc&distance_max=150&distance_min=50&route=available&sort=name", headers[0].URL)
+ assert.Equal(t, "/?bike_type=road&dir=asc&distance_max=150&distance_min=50&sort=name", headers[0].URL)
}
func TestHandlerFiltersRidesBeforeRenderingSortedResults(t *testing.T) {
@@ -214,6 +227,8 @@ func TestHandlerFiltersRidesBeforeRenderingSortedResults(t *testing.T) {
GPXPath: testGPXPath(t, path),
Name: name,
Type: "Ride",
+ BikeType: ride.BikeTypeRoad,
+ RideType: ride.RideTypeTraining,
StartDate: time.Date(2026, 8, 1, 7, 0, 0, 0, time.UTC),
DistanceM: distance,
}))
@@ -239,6 +254,8 @@ func TestHandlerRendersFilteredEmptyState(t *testing.T) {
GPXPath: testGPXPath(t, "empty-filter.gpx"),
Name: "Short Ride",
Type: "Ride",
+ BikeType: ride.BikeTypeRoad,
+ RideType: ride.RideTypeTraining,
StartDate: time.Date(2026, 8, 1, 7, 0, 0, 0, time.UTC),
DistanceM: 20_000,
}))