package web import ( "database/sql" "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "regexp" "testing" "github.com/martinlehoux/biking_home/internal/ridetest" "github.com/martinlehoux/biking_home/official_climb" "github.com/martinlehoux/biking_home/ride" "github.com/martinlehoux/biking_home/rideanalysis" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func recordFixtureAttempts(t *testing.T, server *Server, rideID int64, climb official_climb.OfficialClimb) { t.Helper() parsed, _ := testRideForClimb(t) analysis := rideanalysis.Analyze(parsed, nil, []official_climb.OfficialClimb{climb}, official_climb.DefaultMatchPolicy()) server.recordOfficialClimbAttempts(rideID, parsed, analysis) } func storeRideFixtureFile(t *testing.T, db *sql.DB, rideID int64) { t.Helper() parsed, _ := testRideForClimb(t) fitPath := filepath.Join(t.TempDir(), "ride.fit") fitFile, err := os.Create(fitPath) require.NoError(t, err) require.NoError(t, ride.EncodeFIT(parsed, fitFile)) require.NoError(t, fitFile.Close()) _, err = db.Exec("UPDATE rides SET fit_path = ? WHERE id = ?", fitPath, rideID) require.NoError(t, err) } // climbProfileData reads the profile JSON the climb page embeds. func climbProfileData(t *testing.T, body string) ClimbProfileData { t.Helper() match := regexp.MustCompile(`(?s)id="climb-profile-data"[^>]*>(.*?)`).FindStringSubmatch(body) require.Len(t, match, 2, "climb page must embed its profile JSON") var profile ClimbProfileData require.NoError(t, json.Unmarshal([]byte(match[1]), &profile)) return profile } func TestHandleClimbRendersAttemptsAndProfile(t *testing.T) { server, db := newWebTestServer(t) _, climbFixture := testRideForClimb(t) created, err := official_climb.Create(db, climbFixture) require.NoError(t, err) rideID := insertTestRide(t, db) storeRideFixtureFile(t, db, rideID) recordFixtureAttempts(t, server, rideID, created) recorder := httptest.NewRecorder() server.Handler().ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, climbDetailURL(created.ID), nil)) require.Equal(t, http.StatusOK, recorder.Code) body := recorder.Body.String() assert.Contains(t, body, "Col de Test") assert.Contains(t, body, "climb-profile-data") profile := climbProfileData(t, body) require.NotEmpty(t, profile.Sections) assert.InDelta(t, 0, profile.Sections[0].StartKm, 0.01) assert.InDelta(t, 300, profile.Sections[0].StartElevationM, 1) lastSection := profile.Sections[len(profile.Sections)-1] assert.InDelta(t, 1, lastSection.EndKm, 0.01) assert.InDelta(t, 447, lastSection.EndElevationM, 2) assert.Contains(t, body, "Test Ride") // A ride without a power meter renders a dash, not a fabricated value. assert.Contains(t, body, `