Files
go-garminconnect/internal/api/activities_test.go

190 lines
5.5 KiB
Go

package api
import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestActivitiesEndpoints(t *testing.T) {
mockServer := NewMockServer()
defer mockServer.Close()
client := NewClientWithBaseURL(mockServer.URL())
tests := []struct {
name string
setup func()
testFunc func(t *testing.T)
}{
{
name: "GetActivitiesSuccess",
setup: func() {
mockServer.SetActivitiesHandler(func(w http.ResponseWriter, r *http.Request) {
// Create a properly formatted time string for Garmin format
timeStr := time.Now().Add(-24 * time.Hour).Format("2006-01-02T15:04:05")
// Create response with raw JSON to avoid time marshaling issues
response := map[string]interface{}{
"activities": []map[string]interface{}{
{
"activityId": 1,
"activityName": "Morning Run",
"activityType": "RUNNING",
"startTimeLocal": timeStr,
"duration": 3600.0,
"distance": 10.0,
},
},
"pagination": map[string]interface{}{
"page": 1,
"pageSize": 10,
"totalCount": 1,
},
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
})
},
testFunc: func(t *testing.T) {
activities, pagination, err := client.GetActivities(context.Background(), 1, 10)
assert.NoError(t, err)
assert.Len(t, activities, 1)
assert.Equal(t, int64(1), activities[0].ActivityID)
assert.Equal(t, "Morning Run", activities[0].Name)
assert.NotNil(t, pagination)
assert.Equal(t, 1, pagination.TotalCount)
},
},
{
name: "GetActivityDetailsSuccess",
setup: func() {
mockServer.SetActivityDetailsHandler(func(w http.ResponseWriter, r *http.Request) {
pathParts := strings.Split(r.URL.Path, "/")
if len(pathParts) < 2 {
w.WriteHeader(http.StatusNotFound)
return
}
activityID, err := strconv.ParseInt(pathParts[len(pathParts)-1], 10, 64)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
// Use proper time format for Garmin API
timeStr := time.Now().Add(-24 * time.Hour).Format("2006-01-02T15:04:05")
response := map[string]interface{}{
"activityId": activityID,
"activityName": "Mock Activity",
"activityType": "RUNNING",
"startTimeLocal": timeStr,
"duration": 3600.0,
"distance": 10.0,
"calories": 500.0,
"averageHR": 150,
"maxHR": 170,
"elevationGain": 100.0,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
})
},
testFunc: func(t *testing.T) {
activity, err := client.GetActivityDetails(context.Background(), 1)
assert.NoError(t, err)
assert.Equal(t, int64(1), activity.ActivityID)
assert.Equal(t, "Mock Activity", activity.Name)
assert.Equal(t, float64(500), activity.Calories)
},
},
{
name: "GetActivitiesServerError",
setup: func() {
mockServer.SetActivitiesHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"error": "Internal server error"}`))
})
},
testFunc: func(t *testing.T) {
_, _, err := client.GetActivities(context.Background(), 1, 10)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to get activities")
},
},
{
name: "GetActivitiesEmptyResponse",
setup: func() {
mockServer.SetActivitiesHandler(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ActivitiesResponse{
Activities: []ActivityResponse{}, // Empty activities
Pagination: Pagination{Page: 1, PageSize: 10, TotalCount: 0},
})
})
},
testFunc: func(t *testing.T) {
activities, pagination, err := client.GetActivities(context.Background(), 1, 10)
assert.NoError(t, err) // Should not error when no activities exist
assert.Len(t, activities, 0)
assert.NotNil(t, pagination)
assert.Equal(t, 0, pagination.TotalCount)
},
},
{
name: "UploadActivitySuccess",
setup: func() {
mockServer.SetUploadHandler(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]interface{}{"activityId": 12345})
})
},
testFunc: func(t *testing.T) {
// Create a minimal valid FIT file data for testing
fitData := make([]byte, 20)
fitData[0] = 14 // header size
copy(fitData[8:12], []byte(".FIT"))
id, err := client.UploadActivity(context.Background(), fitData)
assert.NoError(t, err)
assert.Equal(t, int64(12345), id)
},
},
{
name: "GetActivityDetailsNotFound",
setup: func() {
mockServer.SetActivityDetailsHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(`{"error": "Activity not found"}`))
})
},
testFunc: func(t *testing.T) {
_, err := client.GetActivityDetails(context.Background(), 999)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to get activity details")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockServer.Reset()
if tt.setup != nil {
tt.setup()
}
tt.testFunc(t)
})
}
}