Files
apocapoc-api/internal/infrastructure/persistence/sqlite/habit_entry_repository_test.go
T
david 0977d3a58b Implement SQLite persistence layer (TDD)
- Add SQLite and UUID dependencies (go-sqlite3, google/uuid)
- Create database connection with automatic migrations
- Implement UserRepository with full CRUD operations
- Implement HabitRepository with JSON serialization for arrays
- Implement HabitEntryRepository with date range queries
- Add comprehensive test coverage for all repositories
- Fix User entity to default timezone to UTC when empty
- All tests passing with TDD approach (Red-Green-Refactor)
2025-11-25 14:29:51 +01:00

206 lines
5.6 KiB
Go

package sqlite
import (
"context"
"testing"
"time"
"habit-tracker-api/internal/domain/entities"
"habit-tracker-api/internal/shared/errors"
)
func TestHabitEntryRepositoryCreate(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
scheduledDate := time.Date(2025, 1, 15, 0, 0, 0, 0, time.UTC)
value := 5.0
entry := entities.NewHabitEntry("habit-123", scheduledDate, &value)
err := repo.Create(ctx, entry)
if err != nil {
t.Fatalf("Create failed: %v", err)
}
if entry.ID == "" {
t.Error("Expected entry ID to be generated, got empty string")
}
}
func TestHabitEntryRepositoryCreateDuplicateDate(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
scheduledDate := time.Date(2025, 1, 20, 0, 0, 0, 0, time.UTC)
habitID := "habit-456"
entry1 := entities.NewHabitEntry(habitID, scheduledDate, nil)
err := repo.Create(ctx, entry1)
if err != nil {
t.Fatalf("First create failed: %v", err)
}
entry2 := entities.NewHabitEntry(habitID, scheduledDate, nil)
err = repo.Create(ctx, entry2)
if err != errors.ErrAlreadyExists {
t.Errorf("Expected ErrAlreadyExists, got %v", err)
}
}
func TestHabitEntryRepositoryFindByHabitIDAndDateRange(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
habitID := "habit-range-test"
date1 := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
date2 := time.Date(2025, 1, 5, 0, 0, 0, 0, time.UTC)
date3 := time.Date(2025, 1, 10, 0, 0, 0, 0, time.UTC)
date4 := time.Date(2025, 1, 15, 0, 0, 0, 0, time.UTC)
entry1 := entities.NewHabitEntry(habitID, date1, nil)
entry2 := entities.NewHabitEntry(habitID, date2, nil)
entry3 := entities.NewHabitEntry(habitID, date3, nil)
entry4 := entities.NewHabitEntry(habitID, date4, nil)
repo.Create(ctx, entry1)
repo.Create(ctx, entry2)
repo.Create(ctx, entry3)
repo.Create(ctx, entry4)
from := time.Date(2025, 1, 5, 0, 0, 0, 0, time.UTC)
to := time.Date(2025, 1, 12, 0, 0, 0, 0, time.UTC)
entries, err := repo.FindByHabitIDAndDateRange(ctx, habitID, from, to)
if err != nil {
t.Fatalf("FindByHabitIDAndDateRange failed: %v", err)
}
if len(entries) != 2 {
t.Errorf("Expected 2 entries in range, got %d", len(entries))
}
}
func TestHabitEntryRepositoryUpdate(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
scheduledDate := time.Date(2025, 2, 1, 0, 0, 0, 0, time.UTC)
entry := entities.NewHabitEntry("habit-update", scheduledDate, nil)
err := repo.Create(ctx, entry)
if err != nil {
t.Fatalf("Create failed: %v", err)
}
now := time.Now()
entry.DeletedAt = &now
err = repo.Update(ctx, entry)
if err != nil {
t.Fatalf("Update failed: %v", err)
}
}
func TestHabitEntryRepositoryUpdateNotFound(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
scheduledDate := time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC)
entry := entities.NewHabitEntry("habit-123", scheduledDate, nil)
entry.ID = "non-existent"
err := repo.Update(ctx, entry)
if err != errors.ErrNotFound {
t.Errorf("Expected ErrNotFound, got %v", err)
}
}
func TestHabitEntryRepositoryWithValue(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
scheduledDate := time.Date(2025, 4, 1, 0, 0, 0, 0, time.UTC)
value := 42.5
entry := entities.NewHabitEntry("habit-value", scheduledDate, &value)
err := repo.Create(ctx, entry)
if err != nil {
t.Fatalf("Create failed: %v", err)
}
from := time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC)
to := time.Date(2025, 5, 1, 0, 0, 0, 0, time.UTC)
entries, err := repo.FindByHabitIDAndDateRange(ctx, "habit-value", from, to)
if err != nil {
t.Fatalf("FindByHabitIDAndDateRange failed: %v", err)
}
if len(entries) != 1 {
t.Fatalf("Expected 1 entry, got %d", len(entries))
}
if entries[0].Value == nil || *entries[0].Value != 42.5 {
t.Errorf("Expected value 42.5, got %v", entries[0].Value)
}
}
func TestHabitEntryRepositoryOrderedByDate(t *testing.T) {
db := setupTestDB(t)
defer db.Close()
repo := NewHabitEntryRepository(db)
ctx := context.Background()
habitID := "habit-order"
date3 := time.Date(2025, 5, 15, 0, 0, 0, 0, time.UTC)
date1 := time.Date(2025, 5, 1, 0, 0, 0, 0, time.UTC)
date2 := time.Date(2025, 5, 10, 0, 0, 0, 0, time.UTC)
repo.Create(ctx, entities.NewHabitEntry(habitID, date3, nil))
repo.Create(ctx, entities.NewHabitEntry(habitID, date1, nil))
repo.Create(ctx, entities.NewHabitEntry(habitID, date2, nil))
from := time.Date(2025, 5, 1, 0, 0, 0, 0, time.UTC)
to := time.Date(2025, 5, 31, 0, 0, 0, 0, time.UTC)
entries, err := repo.FindByHabitIDAndDateRange(ctx, habitID, from, to)
if err != nil {
t.Fatalf("FindByHabitIDAndDateRange failed: %v", err)
}
if len(entries) != 3 {
t.Fatalf("Expected 3 entries, got %d", len(entries))
}
if entries[0].ScheduledDate.Format("2006-01-02") != date1.Format("2006-01-02") {
t.Errorf("First entry should be %s, got %s", date1.Format("2006-01-02"), entries[0].ScheduledDate.Format("2006-01-02"))
}
if entries[1].ScheduledDate.Format("2006-01-02") != date2.Format("2006-01-02") {
t.Errorf("Second entry should be %s, got %s", date2.Format("2006-01-02"), entries[1].ScheduledDate.Format("2006-01-02"))
}
if entries[2].ScheduledDate.Format("2006-01-02") != date3.Format("2006-01-02") {
t.Errorf("Third entry should be %s, got %s", date3.Format("2006-01-02"), entries[2].ScheduledDate.Format("2006-01-02"))
}
}