// SPDX-License-Identifier: AGPL-3.0-or-later package store import ( "testing" ) func TestFaveCRUD(t *testing.T) { db := testDB(t) users := NewUserStore(db) faves := NewFaveStore(db) tags := NewTagStore(db) Argon2Memory = 1024 Argon2Time = 1 defer func() { Argon2Memory = 65536; Argon2Time = 3 }() // Create a user first. user, err := users.Create("testuser", "password123", "user") if err != nil { t.Fatalf("create user: %v", err) } // Create a fave. fave, err := faves.Create(user.ID, "Blade Runner 2049", "https://example.com", "", "", "public") if err != nil { t.Fatalf("create fave: %v", err) } if fave.Description != "Blade Runner 2049" { t.Errorf("description = %q, want %q", fave.Description, "Blade Runner 2049") } if fave.Username != "testuser" { t.Errorf("username = %q, want %q", fave.Username, "testuser") } // Get by ID. got, err := faves.GetByID(fave.ID) if err != nil { t.Fatalf("get fave: %v", err) } if got.Description != fave.Description { t.Errorf("got description = %q, want %q", got.Description, fave.Description) } // Update. err = faves.Update(fave.ID, "Blade Runner 2049 (Final Cut)", "https://example.com/br2049", "", "", "private") if err != nil { t.Fatalf("update fave: %v", err) } updated, _ := faves.GetByID(fave.ID) if updated.Description != "Blade Runner 2049 (Final Cut)" { t.Errorf("updated description = %q", updated.Description) } if updated.Privacy != "private" { t.Errorf("updated privacy = %q, want private", updated.Privacy) } // Set tags. err = tags.SetFaveTags(fave.ID, []string{"film", "sci-fi", "favoritt"}) if err != nil { t.Fatalf("set tags: %v", err) } faveTags, err := tags.ForFave(fave.ID) if err != nil { t.Fatalf("for fave: %v", err) } if len(faveTags) != 3 { t.Errorf("tag count = %d, want 3", len(faveTags)) } // List by user. list, total, err := faves.ListByUser(user.ID, 10, 0) if err != nil { t.Fatalf("list by user: %v", err) } if total != 1 || len(list) != 1 { t.Errorf("list by user: total=%d, len=%d", total, len(list)) } // Load tags for list. err = faves.LoadTags(list) if err != nil { t.Fatalf("load tags: %v", err) } if len(list[0].Tags) != 3 { t.Errorf("loaded tags = %d, want 3", len(list[0].Tags)) } // Public list should be empty (fave is now private). pubList, pubTotal, err := faves.ListPublicByUser(user.ID, 10, 0) if err != nil { t.Fatalf("list public: %v", err) } if pubTotal != 0 || len(pubList) != 0 { t.Errorf("public list should be empty: total=%d, len=%d", pubTotal, len(pubList)) } // Delete. err = faves.Delete(fave.ID) if err != nil { t.Fatalf("delete fave: %v", err) } _, err = faves.GetByID(fave.ID) if err != ErrFaveNotFound { t.Errorf("deleted fave error = %v, want ErrFaveNotFound", err) } } func TestFaveNotes(t *testing.T) { db := testDB(t) users := NewUserStore(db) faves := NewFaveStore(db) Argon2Memory = 1024 Argon2Time = 1 defer func() { Argon2Memory = 65536; Argon2Time = 3 }() user, _ := users.Create("testuser", "password123", "user") // Create with notes. fave, err := faves.Create(user.ID, "Film", "https://example.com", "", "En fantastisk film", "public") if err != nil { t.Fatalf("create fave with notes: %v", err) } if fave.Notes != "En fantastisk film" { t.Errorf("notes = %q, want %q", fave.Notes, "En fantastisk film") } // Update notes. err = faves.Update(fave.ID, fave.Description, fave.URL, fave.ImagePath, "Oppdatert anmeldelse", fave.Privacy) if err != nil { t.Fatalf("update notes: %v", err) } updated, _ := faves.GetByID(fave.ID) if updated.Notes != "Oppdatert anmeldelse" { t.Errorf("updated notes = %q", updated.Notes) } // Notes appear in list queries. list, _, _ := faves.ListByUser(user.ID, 10, 0) if len(list) != 1 || list[0].Notes != "Oppdatert anmeldelse" { t.Error("notes should be loaded in list queries") } // Empty notes by default. fave2, _ := faves.Create(user.ID, "No notes", "", "", "", "public") if fave2.Notes != "" { t.Errorf("default notes = %q, want empty", fave2.Notes) } } func TestUpdatePrivacy(t *testing.T) { db := testDB(t) users := NewUserStore(db) faves := NewFaveStore(db) Argon2Memory = 1024 Argon2Time = 1 defer func() { Argon2Memory = 65536; Argon2Time = 3 }() user, _ := users.Create("testuser", "password123", "user") fave, _ := faves.Create(user.ID, "Toggle me", "", "", "", "public") // Toggle to private. err := faves.UpdatePrivacy(fave.ID, "private") if err != nil { t.Fatalf("update privacy: %v", err) } got, _ := faves.GetByID(fave.ID) if got.Privacy != "private" { t.Errorf("privacy = %q, want private", got.Privacy) } // Toggle back to public. faves.UpdatePrivacy(fave.ID, "public") got, _ = faves.GetByID(fave.ID) if got.Privacy != "public" { t.Errorf("privacy = %q, want public", got.Privacy) } } func TestListByTag(t *testing.T) { db := testDB(t) users := NewUserStore(db) faves := NewFaveStore(db) tags := NewTagStore(db) Argon2Memory = 1024 Argon2Time = 1 defer func() { Argon2Memory = 65536; Argon2Time = 3 }() user, _ := users.Create("testuser", "password123", "user") // Create two public faves with overlapping tags. f1, _ := faves.Create(user.ID, "Fave 1", "", "", "", "public") f2, _ := faves.Create(user.ID, "Fave 2", "", "", "", "public") f3, _ := faves.Create(user.ID, "Private Fave", "", "", "", "private") tags.SetFaveTags(f1.ID, []string{"music", "jazz"}) tags.SetFaveTags(f2.ID, []string{"music", "rock"}) tags.SetFaveTags(f3.ID, []string{"music", "secret"}) // ListByTag only returns public faves. list, total, err := faves.ListByTag("music", 10, 0) if err != nil { t.Fatalf("list by tag: %v", err) } if total != 2 { t.Errorf("total = %d, want 2 (private fave should be excluded)", total) } if len(list) != 2 { t.Errorf("len = %d, want 2", len(list)) } } func TestFavePagination(t *testing.T) { db := testDB(t) users := NewUserStore(db) faves := NewFaveStore(db) Argon2Memory = 1024 Argon2Time = 1 defer func() { Argon2Memory = 65536; Argon2Time = 3 }() user, _ := users.Create("testuser", "password123", "user") // Create 5 faves. for i := 0; i < 5; i++ { faves.Create(user.ID, "Fave "+string(rune('A'+i)), "", "", "", "public") } // Page 1 with limit 2. page1, total, err := faves.ListByUser(user.ID, 2, 0) if err != nil { t.Fatalf("page 1: %v", err) } if total != 5 { t.Errorf("total = %d, want 5", total) } if len(page1) != 2 { t.Errorf("page 1 len = %d, want 2", len(page1)) } // Page 3 with limit 2 should have 1 item. page3, _, err := faves.ListByUser(user.ID, 2, 4) if err != nil { t.Fatalf("page 3: %v", err) } if len(page3) != 1 { t.Errorf("page 3 len = %d, want 1", len(page3)) } }