package sqlite_test import ( "errors" "testing" "context" "os" "path/filepath" "time" "git.hrafn.xyz/aether/notes/internal/models" "git.hrafn.xyz/aether/notes/internal/store/sqlite" ) func TestCreateSQLiteStore(t *testing.T) { testcases := []struct { name string dbPath string expectedError bool }{ { name: "valid path", dbPath: filepath.Join(t.TempDir(), "test.db"), expectedError: false, }, { name: "invalid path", dbPath: filepath.Join(t.TempDir(), "Really", "Deep", "Dir", "That", "Does", "Not", "Exist", "test.db"), expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { store, err := sqlite.NewSQLiteStore(context.Background(), tc.dbPath) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } else { if err != nil { t.Errorf("unexpected error: %v", err) } } if !tc.expectedError && store == nil { t.Errorf("expected a store but got none") } defer func() { if store != nil { store.Close() } // Clean up the database file after the test if _, err := os.Stat(tc.dbPath); !errors.Is(err, os.ErrNotExist) { if err := os.Remove(tc.dbPath); err != nil { t.Errorf("failed to clean up database file: %v", err) } } }() }) } } func TestSaveNote(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "test.db") store, err := sqlite.NewSQLiteStore(context.Background(), dbPath) if err != nil { t.Fatalf("failed to create SQLite store: %v", err) } defer func() { store.Close() if _, err := os.Stat(dbPath); !errors.Is(err, os.ErrNotExist) { if err := os.Remove(dbPath); err != nil { t.Errorf("failed to clean up database file: %v", err) } } }() testcases := []struct { name string note models.Note expectedNote models.Note expectedError bool }{ { name: "new note", note: models.Note{ Content: "Test note", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 1, Content: "Test note", LastUpdate: time.Now(), }, expectedError: false, }, { name: "new 2 note", note: models.Note{ Content: "Test note 2!", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 2, Content: "Test note 2!", LastUpdate: time.Now(), }, expectedError: false, }, { name: "update note", note: models.Note{ ID: 1, Content: "Updated note", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 1, Content: "Updated note", LastUpdate: time.Now(), }, expectedError: false, }, { name: "update non-existent note", note: models.Note{ ID: 999, Content: "This note does not exist", LastUpdate: time.Now(), }, expectedNote: models.Note{}, expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { savedNote, err := store.SaveNote(context.Background(), tc.note) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } if !tc.expectedError { if err != nil { t.Errorf("unexpected error: %v", err) } if savedNote.Content != tc.note.Content { t.Errorf("expected content %q but got %q", tc.note.Content, savedNote.Content) } } }) } } func TestGetNoteByID(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "test.db") store, err := sqlite.NewSQLiteStore(context.Background(), dbPath) if err != nil { t.Fatalf("failed to create SQLite store: %v", err) } defer func() { store.Close() if _, err := os.Stat(dbPath); !errors.Is(err, os.ErrNotExist) { if err := os.Remove(dbPath); err != nil { t.Errorf("failed to clean up database file: %v", err) } } }() store.SaveNote(context.Background(), models.Note{ Content: "Test note", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) testcases := []struct { name string id int expectedNote models.Note expectedError bool }{ { name: "get existing note", id: 1, expectedNote: models.Note{ ID: 1, Content: "Test note", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }, expectedError: false, }, { name: "get non-existent note", id: 999, expectedNote: models.Note{}, expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { note, err := store.GetNoteByID(context.Background(), tc.id) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } else { if err != nil { t.Errorf("unexpected error: %v", err) } if note.ID != tc.expectedNote.ID || note.Content != tc.expectedNote.Content || !note.LastUpdate.Equal(tc.expectedNote.LastUpdate) { t.Errorf("expected note %+v but got %+v", tc.expectedNote, note) } } }) } } func TestGetAllNotes(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "test.db") store, err := sqlite.NewSQLiteStore(context.Background(), dbPath) if err != nil { t.Fatalf("failed to create SQLite store: %v", err) } defer func() { store.Close() if _, err := os.Stat(dbPath); !errors.Is(err, os.ErrNotExist) { if err := os.Remove(dbPath); err != nil { t.Errorf("failed to clean up database file: %v", err) } } }() testcases := []struct { name string expectedNotes []models.Note expectedError bool }{ { name: "get all notes when empty", expectedNotes: []models.Note{}, expectedError: false, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { notes, err := store.GetAllNotes(context.Background()) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } else { if err != nil { t.Errorf("unexpected error: %v", err) } if len(notes) != len(tc.expectedNotes) { t.Errorf("expected %d notes but got %d", len(tc.expectedNotes), len(notes)) } } }) } store.SaveNote(context.Background(), models.Note{ Content: "Test note 1", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 2", LastUpdate: time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC), }) testcases = []struct { name string expectedNotes []models.Note expectedError bool }{ { name: "get all notes when not empty", expectedNotes: []models.Note{ { ID: 1, Content: "Test note 1", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }, { ID: 2, Content: "Test note 2", LastUpdate: time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC), }, }, expectedError: false, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { notes, err := store.GetAllNotes(context.Background()) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } else { if err != nil { t.Errorf("unexpected error: %v", err) } if len(notes) != len(tc.expectedNotes) { t.Errorf("expected %d notes but got %d", len(tc.expectedNotes), len(notes)) } } }) } } func TestDeleteNoteByID(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "test.db") store, err := sqlite.NewSQLiteStore(context.Background(), dbPath) if err != nil { t.Fatalf("failed to create SQLite store: %v", err) } defer func() { store.Close() if _, err := os.Stat(dbPath); !errors.Is(err, os.ErrNotExist) { if err := os.Remove(dbPath); err != nil { t.Errorf("failed to clean up database file: %v", err) } } }() store.SaveNote(context.Background(), models.Note{ Content: "Test note 1", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 2", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 3", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) testcases := []struct { name string id int expectedError bool }{ { name: "delete existing note", id: 2, expectedError: false, }, { name: "delete non-existent note", id: 999, expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { err := store.DeleteNoteByID(context.Background(), tc.id) if tc.expectedError { if err == nil { t.Errorf("expected an error but got none") } } else { if err != nil { t.Errorf("unexpected error: %v", err) } else { _, err := store.GetNoteByID(context.Background(), tc.id) if err == nil { t.Errorf("expected an error when retrieving deleted note but got none") } } } }) } }