Files
geniusrun/backend/internal/store/reset_test.go
Christophe Vila 518bccf5ab Dedup Garmin data storage, configurable chart colors, taxonomy fixes, sync/progression fixes
- Remove duplicated Garmin fields from storage; decode display-only fields
  (activity name/type, lap duration/HR, structured workout raw JSON) from
  RawJSON at API-response time instead of storing redundant columns
- Add a fully configurable chart color system (pace/HR main-line colors, 4
  effort-kind colors, tint/darken/brighten intensity knobs) under Profile >
  Chart colors
- Rename training types and fix their display order (Easy, Long, 60'/30'
  Threshold, Tempo, Intervals, MAS Test, Race) everywhere they're listed
- Add an Efficiency Factor progression metric; fix Progression chart axes to
  use tight non-zero-based domains, m:ss/km pace formatting, and rounded
  ticks instead of raw floating-point labels
- Expose the raw get_workout_by_id() payload in the raw-data viewer
  alongside activity/lap/detail JSON; enlarge the modal and shrink array
  indentation for readability
- Fix "last sync" reporting a meaningless activity count: record one
  combined sync run per manual "Sync now" and count genuinely new
  activities instead of re-listing whatever Garmin returned for the queried
  window
- Let a Review Queue activity be manually cleared back to Unclassified, and
  make "Reset all" available even while disconnected from Garmin

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 06:33:47 +02:00

72 lines
2.3 KiB
Go

package store
import (
"context"
"testing"
)
func TestResetAllSyncedData_DeletesActivitiesCascadesAndRewindsWatermark(t *testing.T) {
db := openTestDB(t)
ctx := context.Background()
activityID, err := db.UpsertActivity(ctx, Activity{GarminActivityID: 1, StartTimeUTC: "2026-07-11 06:00:00", RawJSON: "{}"})
if err != nil {
t.Fatalf("UpsertActivity: %v", err)
}
kindID, err := db.CreateWorkoutKind(ctx, WorkoutKind{Name: "Test Reset Kind", RuleJSON: `{"match":"all","conditions":[]}`, IsActive: true})
if err != nil {
t.Fatalf("CreateWorkoutKind: %v", err)
}
if err := db.ReplaceLaps(ctx, activityID, []Lap{{LapIndex: 1}}); err != nil {
t.Fatalf("ReplaceLaps: %v", err)
}
if _, err := db.InsertKindAssignment(ctx, KindAssignment{
ActivityID: activityID, WorkoutKindID: &kindID, AssignmentSource: AssignmentSourceRuleEngine,
Status: AssignmentStatusAssigned, CandidateKindsJSON: "[]",
}); err != nil {
t.Fatalf("InsertKindAssignment: %v", err)
}
if err := db.UpdateSyncState(ctx, "2020-01-01", true); err != nil {
t.Fatalf("UpdateSyncState: %v", err)
}
if err := db.ResetAllSyncedData(ctx); err != nil {
t.Fatalf("ResetAllSyncedData: %v", err)
}
activities, err := db.ListActivities(ctx, ActivityFilter{})
if err != nil {
t.Fatalf("ListActivities: %v", err)
}
if len(activities) != 0 {
t.Errorf("expected 0 activities after reset, got %d", len(activities))
}
laps, err := db.LapsForActivity(ctx, activityID)
if err != nil {
t.Fatalf("LapsForActivity: %v", err)
}
if len(laps) != 0 {
t.Errorf("expected laps to cascade-delete, got %d", len(laps))
}
if _, ok, err := db.CurrentAssignment(ctx, activityID); err != nil || ok {
t.Errorf("expected kind assignment to cascade-delete, ok=%v err=%v", ok, err)
}
state, err := db.GetSyncState(ctx)
if err != nil {
t.Fatalf("GetSyncState: %v", err)
}
if state.EarliestSyncedDate != nil || state.BackfillComplete {
t.Errorf("expected watermark rewound to fresh state, got %+v", state)
}
// Workout kinds (the user's taxonomy) must survive a reset.
kind, ok, err := db.GetWorkoutKind(ctx, kindID)
if err != nil || !ok {
t.Fatalf("GetWorkoutKind after reset: ok=%v err=%v", ok, err)
}
if kind.Name != "Test Reset Kind" {
t.Errorf("workout kind was unexpectedly affected by reset: %+v", kind)
}
}