store: add User type and ProvisionUser
Lays the groundwork for per-user accounts: CreateUser/GetUserBySub/ ListUsers plus ProvisionUser, which seeds a brand-new user's profile, default workout-kind taxonomy, and sync state in one transaction. Depends on later tasks scoping GetProfile/ListWorkoutKinds/GetSyncState to compile and pass -- expected or committing to a shared branch.
This commit is contained in:
91
backend/internal/store/users_test.go
Normal file
91
backend/internal/store/users_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetUserBySub_NotFoundReturnsFalseNotError(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
_, found, err := db.GetUserBySub(context.Background(), "no-such-sub")
|
||||
if err != nil {
|
||||
t.Fatalf("GetUserBySub: %v", err)
|
||||
}
|
||||
if found {
|
||||
t.Fatal("expected found=false for an unknown sub")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisionUser_SeedsProfileTaxonomyAndSyncState(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
userID, err := db.ProvisionUser(ctx, "sub-123", "Lucie")
|
||||
if err != nil {
|
||||
t.Fatalf("ProvisionUser: %v", err)
|
||||
}
|
||||
|
||||
u, found, err := db.GetUserBySub(ctx, "sub-123")
|
||||
if err != nil || !found {
|
||||
t.Fatalf("GetUserBySub: found=%v err=%v", found, err)
|
||||
}
|
||||
if u.ID != userID || u.DisplayName != "Lucie" {
|
||||
t.Fatalf("got %+v, want ID=%d DisplayName=Lucie", u, userID)
|
||||
}
|
||||
|
||||
profile, err := db.GetProfile(ctx, userID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetProfile: %v", err)
|
||||
}
|
||||
if profile.Name != "Lucie" {
|
||||
t.Errorf("profile.Name = %q, want %q", profile.Name, "Lucie")
|
||||
}
|
||||
if profile.RollingWindowDays != 90 {
|
||||
t.Errorf("profile.RollingWindowDays = %d, want 90 (default)", profile.RollingWindowDays)
|
||||
}
|
||||
|
||||
kinds, err := db.ListWorkoutKinds(ctx, userID, false)
|
||||
if err != nil {
|
||||
t.Fatalf("ListWorkoutKinds: %v", err)
|
||||
}
|
||||
if len(kinds) != 8 {
|
||||
t.Fatalf("expected 8 seeded workout kinds, got %d", len(kinds))
|
||||
}
|
||||
|
||||
state, err := db.GetSyncState(ctx, userID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSyncState: %v", err)
|
||||
}
|
||||
if state.EarliestSyncedDate != nil || state.BackfillComplete {
|
||||
t.Errorf("expected fresh sync state, got %+v", state)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisionUser_TwoUsersGetIndependentTaxonomies(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
userA, err := db.ProvisionUser(ctx, "sub-a", "A")
|
||||
if err != nil {
|
||||
t.Fatalf("ProvisionUser(a): %v", err)
|
||||
}
|
||||
userB, err := db.ProvisionUser(ctx, "sub-b", "B")
|
||||
if err != nil {
|
||||
t.Fatalf("ProvisionUser(b): %v", err)
|
||||
}
|
||||
|
||||
kindsA, err := db.ListWorkoutKinds(ctx, userA, false)
|
||||
if err != nil {
|
||||
t.Fatalf("ListWorkoutKinds(a): %v", err)
|
||||
}
|
||||
kindsB, err := db.ListWorkoutKinds(ctx, userB, false)
|
||||
if err != nil {
|
||||
t.Fatalf("ListWorkoutKinds(b): %v", err)
|
||||
}
|
||||
if len(kindsA) != 8 || len(kindsB) != 8 {
|
||||
t.Fatalf("expected 8 kinds each, got a=%d b=%d", len(kindsA), len(kindsB))
|
||||
}
|
||||
if kindsA[0].ID == kindsB[0].ID {
|
||||
t.Fatal("expected each user's seeded kinds to be distinct rows")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user