package app_test import ( "context" "errors" "path/filepath" "testing" "havenllo/internal/app" "havenllo/internal/database" "havenllo/internal/domain" ) func newService(t *testing.T) (*app.Service, func()) { t.Helper() db, err := database.Open(context.Background(), filepath.Join(t.TempDir(), "havenllo.db")) if err != nil { t.Fatal(err) } return app.New(db), func() { _ = db.Close() } } func TestLastListProtection(t *testing.T) { t.Parallel() service, closeDB := newService(t) defer closeDB() ctx := context.Background() lists, err := service.Lists(ctx) if err != nil { t.Fatal(err) } for _, list := range lists[:2] { if err := service.DeleteList(ctx, list.ID); err != nil { t.Fatal(err) } } if err := service.DeleteList(ctx, lists[2].ID); !errors.Is(err, domain.ErrLastList) { t.Fatalf("DeleteList error = %v, want ErrLastList", err) } } func TestCardMoveNormalizesCrowdedPositions(t *testing.T) { t.Parallel() service, closeDB := newService(t) defer closeDB() ctx := context.Background() lists, err := service.Lists(ctx) if err != nil { t.Fatal(err) } first := lists[0] a, err := service.CreateCard(ctx, first.ID, "a", "", nil) if err != nil { t.Fatal(err) } b, err := service.CreateCard(ctx, first.ID, "b", "", nil) if err != nil { t.Fatal(err) } position := a.Position + 0.00001 if _, err := service.UpdateCard(ctx, b.ID, app.CardPatch{Position: &position}); err != nil { t.Fatal(err) } cards, err := service.Cards(ctx, first.ID) if err != nil { t.Fatal(err) } if len(cards) != 2 || cards[1].Position-cards[0].Position < 0.0001 { t.Fatalf("cards were not normalized: %#v", cards) } } func TestCardMoveAndCascade(t *testing.T) { t.Parallel() service, closeDB := newService(t) defer closeDB() ctx := context.Background() lists, _ := service.Lists(ctx) card, err := service.CreateCard(ctx, lists[0].ID, "move me", "", nil) if err != nil { t.Fatal(err) } target := lists[1].ID moved, err := service.UpdateCard(ctx, card.ID, app.CardPatch{ListID: &target}) if err != nil { t.Fatal(err) } if moved.ListID != target { t.Fatalf("card list = %d, want %d", moved.ListID, target) } if err := service.DeleteList(ctx, target); err != nil { t.Fatal(err) } if _, err := service.Card(ctx, card.ID); !errors.Is(err, domain.ErrNotFound) { t.Fatalf("card after list deletion = %v, want not found", err) } }