refactor(db): thread context.Context through all Store methods
Enables request-scoped cancellation, timeouts, and graceful shutdown for all database operations across API handlers, CLI commands, and TUI.
This commit is contained in:
+116
-87
@@ -1,6 +1,7 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -11,15 +12,16 @@ func ptr[T any](v T) *T {
|
||||
|
||||
func TestCreate_Note(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "hello world", Glyph: GlyphNote}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e.ID == "" {
|
||||
t.Fatal("ID not set")
|
||||
}
|
||||
|
||||
got, err := s.Get(e.ID)
|
||||
got, err := s.Get(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -33,12 +35,13 @@ func TestCreate_Note(t *testing.T) {
|
||||
|
||||
func TestCreate_TodoWithTimeAnchor(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "deploy", Glyph: GlyphTodo, TimeAnchor: ptr("14:00")}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := s.Get(e.ID)
|
||||
got, err := s.Get(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -49,12 +52,13 @@ func TestCreate_TodoWithTimeAnchor(t *testing.T) {
|
||||
|
||||
func TestCreate_WithTags(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "deploy nginx", Glyph: GlyphNote, Tags: []string{"ops", "nginx"}}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := s.Get(e.ID)
|
||||
got, err := s.Get(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -65,13 +69,14 @@ func TestCreate_WithTags(t *testing.T) {
|
||||
|
||||
func TestCreate_WithCardType(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
ct := CardSnippet
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote, CardType: &ct}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := s.Get(e.ID)
|
||||
got, err := s.Get(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -82,7 +87,7 @@ func TestCreate_WithCardType(t *testing.T) {
|
||||
|
||||
func TestGet_NotFound(t *testing.T) {
|
||||
s := testStore(t)
|
||||
_, err := s.Get("01NONEXISTENT0000000000000")
|
||||
_, err := s.Get(context.Background(), "01NONEXISTENT0000000000000")
|
||||
if err != ErrNotFound {
|
||||
t.Errorf("expected ErrNotFound, got %v", err)
|
||||
}
|
||||
@@ -90,11 +95,12 @@ func TestGet_NotFound(t *testing.T) {
|
||||
|
||||
func TestList_DefaultParams(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 3; i++ {
|
||||
s.Create(&Entity{Body: "note", Glyph: GlyphNote})
|
||||
s.Create(ctx, &Entity{Body: "note", Glyph: GlyphNote})
|
||||
}
|
||||
|
||||
entities, err := s.List(DefaultListParams())
|
||||
entities, err := s.List(ctx, DefaultListParams())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -109,15 +115,16 @@ func TestList_DefaultParams(t *testing.T) {
|
||||
|
||||
func TestList_FilterByTag(t *testing.T) {
|
||||
s := testStore(t)
|
||||
s.Create(&Entity{Body: "a", Glyph: GlyphNote, Tags: []string{"ops"}})
|
||||
s.Create(&Entity{Body: "b", Glyph: GlyphNote, Tags: []string{"home"}})
|
||||
s.Create(&Entity{Body: "c", Glyph: GlyphNote, Tags: []string{"ops", "home"}})
|
||||
ctx := context.Background()
|
||||
s.Create(ctx, &Entity{Body: "a", Glyph: GlyphNote, Tags: []string{"ops"}})
|
||||
s.Create(ctx, &Entity{Body: "b", Glyph: GlyphNote, Tags: []string{"home"}})
|
||||
s.Create(ctx, &Entity{Body: "c", Glyph: GlyphNote, Tags: []string{"ops", "home"}})
|
||||
|
||||
p := DefaultListParams()
|
||||
tag := "ops"
|
||||
p.Tag = &tag
|
||||
|
||||
entities, err := s.List(p)
|
||||
entities, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -128,13 +135,14 @@ func TestList_FilterByTag(t *testing.T) {
|
||||
|
||||
func TestList_FilterByDate(t *testing.T) {
|
||||
s := testStore(t)
|
||||
s.Create(&Entity{Body: "today", Glyph: GlyphNote})
|
||||
ctx := context.Background()
|
||||
s.Create(ctx, &Entity{Body: "today", Glyph: GlyphNote})
|
||||
|
||||
p := DefaultListParams()
|
||||
date := time.Now().UTC().Format("2006-01-02")
|
||||
p.Date = &date
|
||||
|
||||
entities, err := s.List(p)
|
||||
entities, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -144,7 +152,7 @@ func TestList_FilterByDate(t *testing.T) {
|
||||
|
||||
otherDate := "2020-01-01"
|
||||
p.Date = &otherDate
|
||||
entities, err = s.List(p)
|
||||
entities, err = s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -155,13 +163,14 @@ func TestList_FilterByDate(t *testing.T) {
|
||||
|
||||
func TestList_CardsOnly(t *testing.T) {
|
||||
s := testStore(t)
|
||||
s.Create(&Entity{Body: "fluid", Glyph: GlyphNote})
|
||||
ctx := context.Background()
|
||||
s.Create(ctx, &Entity{Body: "fluid", Glyph: GlyphNote})
|
||||
ct := CardSnippet
|
||||
s.Create(&Entity{Body: "card", Glyph: GlyphNote, CardType: &ct})
|
||||
s.Create(ctx, &Entity{Body: "card", Glyph: GlyphNote, CardType: &ct})
|
||||
|
||||
p := DefaultListParams()
|
||||
p.CardsOnly = true
|
||||
entities, err := s.List(p)
|
||||
entities, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -175,12 +184,13 @@ func TestList_CardsOnly(t *testing.T) {
|
||||
|
||||
func TestList_IncludeDeleted(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "doomed", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.SoftDelete(e.ID)
|
||||
s.Create(ctx, e)
|
||||
s.SoftDelete(ctx, e.ID)
|
||||
|
||||
p := DefaultListParams()
|
||||
entities, err := s.List(p)
|
||||
entities, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -189,7 +199,7 @@ func TestList_IncludeDeleted(t *testing.T) {
|
||||
}
|
||||
|
||||
p.IncludeDeleted = true
|
||||
entities, err = s.List(p)
|
||||
entities, err = s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -200,17 +210,18 @@ func TestList_IncludeDeleted(t *testing.T) {
|
||||
|
||||
func TestList_SortByUseCount(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
ct := CardSnippet
|
||||
e1 := &Entity{Body: "low", Glyph: GlyphNote, CardType: &ct}
|
||||
e2 := &Entity{Body: "high", Glyph: GlyphNote, CardType: &ct}
|
||||
s.Create(e1)
|
||||
s.Create(e2)
|
||||
s.IncrementUse(e2.ID)
|
||||
s.IncrementUse(e2.ID)
|
||||
s.Create(ctx, e1)
|
||||
s.Create(ctx, e2)
|
||||
s.IncrementUse(ctx, e2.ID)
|
||||
s.IncrementUse(ctx, e2.ID)
|
||||
|
||||
p := DefaultListParams()
|
||||
p.Sort = "use_count"
|
||||
entities, err := s.List(p)
|
||||
entities, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -221,14 +232,15 @@ func TestList_SortByUseCount(t *testing.T) {
|
||||
|
||||
func TestList_Pagination(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 10; i++ {
|
||||
s.Create(&Entity{Body: "note", Glyph: GlyphNote})
|
||||
s.Create(ctx, &Entity{Body: "note", Glyph: GlyphNote})
|
||||
}
|
||||
|
||||
p := DefaultListParams()
|
||||
p.Limit = 3
|
||||
p.Offset = 0
|
||||
page1, err := s.List(p)
|
||||
page1, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -237,7 +249,7 @@ func TestList_Pagination(t *testing.T) {
|
||||
}
|
||||
|
||||
p.Offset = 3
|
||||
page2, err := s.List(p)
|
||||
page2, err := s.List(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -251,16 +263,17 @@ func TestList_Pagination(t *testing.T) {
|
||||
|
||||
func TestUpdate_Body(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "old", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
newBody := "new"
|
||||
if err := s.Update(e.ID, &EntityUpdate{Body: &newBody}); err != nil {
|
||||
if err := s.Update(ctx, e.ID, &EntityUpdate{Body: &newBody}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.Body != "new" {
|
||||
t.Errorf("body not updated: %q", got.Body)
|
||||
}
|
||||
@@ -271,15 +284,16 @@ func TestUpdate_Body(t *testing.T) {
|
||||
|
||||
func TestUpdate_Tags(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "test", Glyph: GlyphNote, Tags: []string{"old"}}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
newTags := []string{"new1", "new2"}
|
||||
if err := s.Update(e.ID, &EntityUpdate{Tags: &newTags}); err != nil {
|
||||
if err := s.Update(ctx, e.ID, &EntityUpdate{Tags: &newTags}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if len(got.Tags) != 2 {
|
||||
t.Fatalf("expected 2 tags, got %d: %v", len(got.Tags), got.Tags)
|
||||
}
|
||||
@@ -287,14 +301,15 @@ func TestUpdate_Tags(t *testing.T) {
|
||||
|
||||
func TestPromote_Success(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
if err := s.Promote(e.ID, CardSnippet, nil); err != nil {
|
||||
if err := s.Promote(ctx, e.ID, CardSnippet, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.CardType == nil || *got.CardType != CardSnippet {
|
||||
t.Errorf("expected snippet, got %v", got.CardType)
|
||||
}
|
||||
@@ -302,26 +317,28 @@ func TestPromote_Success(t *testing.T) {
|
||||
|
||||
func TestPromote_AlreadyPromoted(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
ct := CardSnippet
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote, CardType: &ct}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
if err := s.Promote(e.ID, CardTemplate, nil); err != ErrAlreadyPromoted {
|
||||
if err := s.Promote(ctx, e.ID, CardTemplate, nil); err != ErrAlreadyPromoted {
|
||||
t.Errorf("expected ErrAlreadyPromoted, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDemote_Success(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Promote(e.ID, CardSnippet, nil)
|
||||
s.Create(ctx, e)
|
||||
s.Promote(ctx, e.ID, CardSnippet, nil)
|
||||
|
||||
if err := s.Demote(e.ID); err != nil {
|
||||
if err := s.Demote(ctx, e.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.CardType != nil {
|
||||
t.Errorf("expected nil card_type, got %v", got.CardType)
|
||||
}
|
||||
@@ -332,20 +349,22 @@ func TestDemote_Success(t *testing.T) {
|
||||
|
||||
func TestDemote_AlreadyFluid(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
if err := s.Demote(e.ID); err != ErrAlreadyFluid {
|
||||
if err := s.Demote(ctx, e.ID); err != ErrAlreadyFluid {
|
||||
t.Errorf("expected ErrAlreadyFluid, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSoftDelete_First(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "doomed", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
result, err := s.SoftDelete(e.ID)
|
||||
result, err := s.SoftDelete(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -353,7 +372,7 @@ func TestSoftDelete_First(t *testing.T) {
|
||||
t.Errorf("expected DeletedSoft, got %d", result)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.DeletedAt == nil {
|
||||
t.Error("expected deleted_at to be set")
|
||||
}
|
||||
@@ -361,11 +380,12 @@ func TestSoftDelete_First(t *testing.T) {
|
||||
|
||||
func TestSoftDelete_Second(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "doomed", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
s.SoftDelete(e.ID)
|
||||
result, err := s.SoftDelete(e.ID)
|
||||
s.SoftDelete(ctx, e.ID)
|
||||
result, err := s.SoftDelete(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -373,7 +393,7 @@ func TestSoftDelete_Second(t *testing.T) {
|
||||
t.Errorf("expected DeletedHard, got %d", result)
|
||||
}
|
||||
|
||||
_, err = s.Get(e.ID)
|
||||
_, err = s.Get(ctx, e.ID)
|
||||
if err != ErrNotFound {
|
||||
t.Errorf("expected ErrNotFound after hard delete, got %v", err)
|
||||
}
|
||||
@@ -381,7 +401,7 @@ func TestSoftDelete_Second(t *testing.T) {
|
||||
|
||||
func TestSoftDelete_NotFound(t *testing.T) {
|
||||
s := testStore(t)
|
||||
_, err := s.SoftDelete("01NONEXISTENT0000000000000")
|
||||
_, err := s.SoftDelete(context.Background(), "01NONEXISTENT0000000000000")
|
||||
if err != ErrNotFound {
|
||||
t.Errorf("expected ErrNotFound, got %v", err)
|
||||
}
|
||||
@@ -389,15 +409,16 @@ func TestSoftDelete_NotFound(t *testing.T) {
|
||||
|
||||
func TestIncrementUse(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
ct := CardSnippet
|
||||
e := &Entity{Body: "trick", Glyph: GlyphNote, CardType: &ct}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
if err := s.IncrementUse(e.ID); err != nil {
|
||||
if err := s.IncrementUse(ctx, e.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.UseCount != 1 {
|
||||
t.Errorf("expected use_count=1, got %d", got.UseCount)
|
||||
}
|
||||
@@ -408,10 +429,11 @@ func TestIncrementUse(t *testing.T) {
|
||||
|
||||
func TestResolve_FullID(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "test", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
got, err := s.Resolve(e.ID)
|
||||
got, err := s.Resolve(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -422,10 +444,11 @@ func TestResolve_FullID(t *testing.T) {
|
||||
|
||||
func TestResolve_Prefix(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "test", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
got, err := s.Resolve(e.ID[:6])
|
||||
got, err := s.Resolve(ctx, e.ID[:6])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -436,7 +459,7 @@ func TestResolve_Prefix(t *testing.T) {
|
||||
|
||||
func TestResolve_NotFound(t *testing.T) {
|
||||
s := testStore(t)
|
||||
_, err := s.Resolve("ZZZZZZZZZ")
|
||||
_, err := s.Resolve(context.Background(), "ZZZZZZZZZ")
|
||||
if err != ErrNotFound {
|
||||
t.Errorf("expected ErrNotFound, got %v", err)
|
||||
}
|
||||
@@ -444,24 +467,25 @@ func TestResolve_NotFound(t *testing.T) {
|
||||
|
||||
func TestAbsorb_SourceIsCard(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
target := &Entity{Body: "target", Glyph: GlyphNote, Tags: []string{"a"}}
|
||||
s.Create(target)
|
||||
s.Create(ctx, target)
|
||||
|
||||
source := &Entity{Body: "source", Glyph: GlyphNote}
|
||||
s.Create(source)
|
||||
s.Promote(source.ID, CardSnippet, nil)
|
||||
s.IncrementUse(source.ID)
|
||||
s.Create(ctx, source)
|
||||
s.Promote(ctx, source.ID, CardSnippet, nil)
|
||||
s.IncrementUse(ctx, source.ID)
|
||||
|
||||
if err := s.Absorb(target.ID, source.ID); err != nil {
|
||||
if err := s.Absorb(ctx, target.ID, source.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(target.ID)
|
||||
got, _ := s.Get(ctx, target.ID)
|
||||
if got.Body != "target\nsource" {
|
||||
t.Errorf("merged body: %q", got.Body)
|
||||
}
|
||||
|
||||
src, _ := s.Get(source.ID)
|
||||
src, _ := s.Get(ctx, source.ID)
|
||||
if src.CardType != nil {
|
||||
t.Error("source card_type should be cleared after absorb")
|
||||
}
|
||||
@@ -475,6 +499,7 @@ func TestAbsorb_SourceIsCard(t *testing.T) {
|
||||
|
||||
func TestCreate_WithTitleAndDescription(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{
|
||||
Body: "body text",
|
||||
Title: ptr("nginx trick"),
|
||||
@@ -482,11 +507,11 @@ func TestCreate_WithTitleAndDescription(t *testing.T) {
|
||||
Glyph: GlyphNote,
|
||||
Tags: []string{"ops"},
|
||||
}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := s.Get(e.ID)
|
||||
got, err := s.Get(ctx, e.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -503,12 +528,13 @@ func TestCreate_WithTitleAndDescription(t *testing.T) {
|
||||
|
||||
func TestCreate_WithoutTitle(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "just body", Glyph: GlyphNote}
|
||||
if err := s.Create(e); err != nil {
|
||||
if err := s.Create(ctx, e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.Title != nil {
|
||||
t.Errorf("expected nil title, got %v", got.Title)
|
||||
}
|
||||
@@ -519,15 +545,16 @@ func TestCreate_WithoutTitle(t *testing.T) {
|
||||
|
||||
func TestUpdate_Title(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "body", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
newTitle := "new title"
|
||||
if err := s.Update(e.ID, &EntityUpdate{Title: &newTitle}); err != nil {
|
||||
if err := s.Update(ctx, e.ID, &EntityUpdate{Title: &newTitle}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.Title == nil || *got.Title != "new title" {
|
||||
t.Errorf("title: got %v", got.Title)
|
||||
}
|
||||
@@ -535,15 +562,16 @@ func TestUpdate_Title(t *testing.T) {
|
||||
|
||||
func TestUpdate_Description(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
e := &Entity{Body: "body", Glyph: GlyphNote}
|
||||
s.Create(e)
|
||||
s.Create(ctx, e)
|
||||
|
||||
newDesc := "new desc"
|
||||
if err := s.Update(e.ID, &EntityUpdate{Description: &newDesc}); err != nil {
|
||||
if err := s.Update(ctx, e.ID, &EntityUpdate{Description: &newDesc}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(e.ID)
|
||||
got, _ := s.Get(ctx, e.ID)
|
||||
if got.Description == nil || *got.Description != "new desc" {
|
||||
t.Errorf("description: got %v", got.Description)
|
||||
}
|
||||
@@ -551,16 +579,17 @@ func TestUpdate_Description(t *testing.T) {
|
||||
|
||||
func TestAbsorb_PreservesTargetTitle(t *testing.T) {
|
||||
s := testStore(t)
|
||||
ctx := context.Background()
|
||||
target := &Entity{Body: "target body", Title: ptr("target title"), Glyph: GlyphNote}
|
||||
source := &Entity{Body: "source body", Title: ptr("source title"), Glyph: GlyphNote}
|
||||
s.Create(target)
|
||||
s.Create(source)
|
||||
s.Create(ctx, target)
|
||||
s.Create(ctx, source)
|
||||
|
||||
if err := s.Absorb(target.ID, source.ID); err != nil {
|
||||
if err := s.Absorb(ctx, target.ID, source.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, _ := s.Get(target.ID)
|
||||
got, _ := s.Get(ctx, target.ID)
|
||||
if got.Title == nil || *got.Title != "target title" {
|
||||
t.Errorf("target title should be preserved, got %v", got.Title)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user