api: build per-user garmin.Client/sync.Service via lazy caching
Server no longer holds one fixed Garmin/Sync pair -- garminFor/syncFor build and cache one instance per user, keyed off their own profile's Garmin credentials and a per-user token-store subdirectory. The background incremental sync loop now iterates every provisioned user each tick instead of syncing one global account.
This commit is contained in:
@@ -4,11 +4,27 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
authmock "geniusrun/backend/internal/auth/mock"
|
||||
"geniusrun/backend/internal/garmin"
|
||||
"geniusrun/backend/internal/garmin/mock"
|
||||
"geniusrun/backend/internal/store"
|
||||
appsync "geniusrun/backend/internal/sync"
|
||||
)
|
||||
|
||||
func TestSetup_ProvisionsNewUserWithDisplayName(t *testing.T) {
|
||||
s, db := newTestServer(t)
|
||||
// This test specifically needs an *unprovisioned* session, unlike every
|
||||
// other test in this package -- build the server without the
|
||||
// newTestServer helper's automatic ProvisionUser call.
|
||||
db, err := store.Open(filepath.Join(t.TempDir(), "geniusrun_test.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("store.Open: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
m := &mock.Client{}
|
||||
s := NewServer(db, func(garmin.Config) garmin.Client { return m }, garmin.Config{}, appsync.Config{}, &authmock.Verifier{}, testSessionConfig)
|
||||
router := s.Router()
|
||||
|
||||
rec := doJSON(t, router, http.MethodGet, "/api/session/me", nil)
|
||||
@@ -39,7 +55,14 @@ func TestSetup_ProvisionsNewUserWithDisplayName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup_RejectsEmptyDisplayName(t *testing.T) {
|
||||
s, _ := newTestServer(t)
|
||||
db, err := store.Open(filepath.Join(t.TempDir(), "geniusrun_test.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("store.Open: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
m := &mock.Client{}
|
||||
s := NewServer(db, func(garmin.Config) garmin.Client { return m }, garmin.Config{}, appsync.Config{}, &authmock.Verifier{}, testSessionConfig)
|
||||
|
||||
rec := doJSON(t, s.Router(), http.MethodPost, "/api/setup", map[string]any{"display_name": ""})
|
||||
if rec.Code != http.StatusBadRequest {
|
||||
t.Fatalf("status = %d, want 400", rec.Code)
|
||||
@@ -47,10 +70,7 @@ func TestSetup_RejectsEmptyDisplayName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup_RejectsWhenAlreadyProvisioned(t *testing.T) {
|
||||
s, db := newTestServer(t)
|
||||
if _, err := db.ProvisionUser(newCtx(), "test-user", "Already Here"); err != nil {
|
||||
t.Fatalf("ProvisionUser: %v", err)
|
||||
}
|
||||
s, _ := newTestServer(t)
|
||||
rec := doJSON(t, s.Router(), http.MethodPost, "/api/setup", map[string]any{"display_name": "Someone Else"})
|
||||
if rec.Code != http.StatusConflict {
|
||||
t.Fatalf("status = %d, want 409, body = %s", rec.Code, rec.Body.String())
|
||||
|
||||
Reference in New Issue
Block a user