···1+package repo
2+3+import (
4+ "context"
5+ "database/sql"
6+ "testing"
7+8+ _ "github.com/mattn/go-sqlite3"
9+ "github.com/stormlightlabs/noteleaf/internal/models"
10+)
11+12+func createNoteTestDB(t *testing.T) *sql.DB {
13+ db, err := sql.Open("sqlite3", ":memory:")
14+ if err != nil {
15+ t.Fatalf("Failed to create in-memory database: %v", err)
16+ }
17+18+ if _, err := db.Exec("PRAGMA foreign_keys = ON"); err != nil {
19+ t.Fatalf("Failed to enable foreign keys: %v", err)
20+ }
21+22+ schema := `
23+ CREATE TABLE IF NOT EXISTS notes (
24+ id INTEGER PRIMARY KEY AUTOINCREMENT,
25+ title TEXT NOT NULL,
26+ content TEXT NOT NULL,
27+ tags TEXT,
28+ archived BOOLEAN DEFAULT FALSE,
29+ created DATETIME DEFAULT CURRENT_TIMESTAMP,
30+ modified DATETIME DEFAULT CURRENT_TIMESTAMP,
31+ file_path TEXT
32+ );
33+ `
34+35+ if _, err := db.Exec(schema); err != nil {
36+ t.Fatalf("Failed to create schema: %v", err)
37+ }
38+39+ t.Cleanup(func() {
40+ db.Close()
41+ })
42+43+ return db
44+}
45+46+func createSampleNote() *models.Note {
47+ return &models.Note{
48+ Title: "Test Note",
49+ Content: "This is test content with **markdown**",
50+ Tags: []string{"personal", "work"},
51+ Archived: false,
52+ FilePath: "/path/to/note.md",
53+ }
54+}
55+56+func TestNoteRepository_CRUD(t *testing.T) {
57+ db := createNoteTestDB(t)
58+ repo := NewNoteRepository(db)
59+ ctx := context.Background()
60+61+ t.Run("Create Note", func(t *testing.T) {
62+ note := createSampleNote()
63+64+ id, err := repo.Create(ctx, note)
65+ if err != nil {
66+ t.Errorf("Failed to create note: %v", err)
67+ }
68+69+ if id == 0 {
70+ t.Error("Expected non-zero ID")
71+ }
72+73+ if note.ID != id {
74+ t.Errorf("Expected note ID to be set to %d, got %d", id, note.ID)
75+ }
76+77+ if note.Created.IsZero() {
78+ t.Error("Expected Created timestamp to be set")
79+ }
80+ if note.Modified.IsZero() {
81+ t.Error("Expected Modified timestamp to be set")
82+ }
83+ })
84+85+ t.Run("Get Note", func(t *testing.T) {
86+ original := createSampleNote()
87+ id, err := repo.Create(ctx, original)
88+ if err != nil {
89+ t.Fatalf("Failed to create note: %v", err)
90+ }
91+92+ retrieved, err := repo.Get(ctx, id)
93+ if err != nil {
94+ t.Fatalf("Failed to get note: %v", err)
95+ }
96+97+ if retrieved.ID != original.ID {
98+ t.Errorf("Expected ID %d, got %d", original.ID, retrieved.ID)
99+ }
100+ if retrieved.Title != original.Title {
101+ t.Errorf("Expected title %s, got %s", original.Title, retrieved.Title)
102+ }
103+ if retrieved.Content != original.Content {
104+ t.Errorf("Expected content %s, got %s", original.Content, retrieved.Content)
105+ }
106+ if len(retrieved.Tags) != len(original.Tags) {
107+ t.Errorf("Expected %d tags, got %d", len(original.Tags), len(retrieved.Tags))
108+ }
109+ if retrieved.Archived != original.Archived {
110+ t.Errorf("Expected archived %v, got %v", original.Archived, retrieved.Archived)
111+ }
112+ if retrieved.FilePath != original.FilePath {
113+ t.Errorf("Expected file path %s, got %s", original.FilePath, retrieved.FilePath)
114+ }
115+ })
116+117+ t.Run("Update Note", func(t *testing.T) {
118+ note := createSampleNote()
119+ id, err := repo.Create(ctx, note)
120+ if err != nil {
121+ t.Fatalf("Failed to create note: %v", err)
122+ }
123+124+ originalModified := note.Modified
125+126+ note.Title = "Updated Title"
127+ note.Content = "Updated content"
128+ note.Tags = []string{"updated", "test"}
129+ note.Archived = true
130+ note.FilePath = "/new/path/note.md"
131+132+ err = repo.Update(ctx, note)
133+ if err != nil {
134+ t.Errorf("Failed to update note: %v", err)
135+ }
136+137+ retrieved, err := repo.Get(ctx, id)
138+ if err != nil {
139+ t.Fatalf("Failed to get updated note: %v", err)
140+ }
141+142+ if retrieved.Title != "Updated Title" {
143+ t.Errorf("Expected updated title, got %s", retrieved.Title)
144+ }
145+ if retrieved.Content != "Updated content" {
146+ t.Errorf("Expected updated content, got %s", retrieved.Content)
147+ }
148+ if len(retrieved.Tags) != 2 || retrieved.Tags[0] != "updated" || retrieved.Tags[1] != "test" {
149+ t.Errorf("Expected updated tags, got %v", retrieved.Tags)
150+ }
151+ if !retrieved.Archived {
152+ t.Error("Expected note to be archived")
153+ }
154+ if retrieved.FilePath != "/new/path/note.md" {
155+ t.Errorf("Expected updated file path, got %s", retrieved.FilePath)
156+ }
157+ if !retrieved.Modified.After(originalModified) {
158+ t.Error("Expected Modified timestamp to be updated")
159+ }
160+ })
161+162+ t.Run("Delete Note", func(t *testing.T) {
163+ note := createSampleNote()
164+ id, err := repo.Create(ctx, note)
165+ if err != nil {
166+ t.Fatalf("Failed to create note: %v", err)
167+ }
168+169+ err = repo.Delete(ctx, id)
170+ if err != nil {
171+ t.Errorf("Failed to delete note: %v", err)
172+ }
173+174+ _, err = repo.Get(ctx, id)
175+ if err == nil {
176+ t.Error("Expected error when getting deleted note")
177+ }
178+ })
179+}
180+181+func TestNoteRepository_List(t *testing.T) {
182+ db := createNoteTestDB(t)
183+ repo := NewNoteRepository(db)
184+ ctx := context.Background()
185+186+ notes := []*models.Note{
187+ {Title: "First Note", Content: "Content 1", Tags: []string{"work"}, Archived: false},
188+ {Title: "Second Note", Content: "Content 2", Tags: []string{"personal"}, Archived: true},
189+ {Title: "Third Note", Content: "Important content", Tags: []string{"work", "important"}, Archived: false},
190+ }
191+192+ for _, note := range notes {
193+ _, err := repo.Create(ctx, note)
194+ if err != nil {
195+ t.Fatalf("Failed to create test note: %v", err)
196+ }
197+ }
198+199+ t.Run("List All Notes", func(t *testing.T) {
200+ results, err := repo.List(ctx, NoteListOptions{})
201+ if err != nil {
202+ t.Fatalf("Failed to list notes: %v", err)
203+ }
204+205+ if len(results) != 3 {
206+ t.Errorf("Expected 3 notes, got %d", len(results))
207+ }
208+ })
209+210+ t.Run("List Archived Notes Only", func(t *testing.T) {
211+ archived := true
212+ results, err := repo.List(ctx, NoteListOptions{Archived: &archived})
213+ if err != nil {
214+ t.Fatalf("Failed to list archived notes: %v", err)
215+ }
216+217+ if len(results) != 1 {
218+ t.Errorf("Expected 1 archived note, got %d", len(results))
219+ }
220+ if !results[0].Archived {
221+ t.Error("Retrieved note should be archived")
222+ }
223+ })
224+225+ t.Run("List Active Notes Only", func(t *testing.T) {
226+ archived := false
227+ results, err := repo.List(ctx, NoteListOptions{Archived: &archived})
228+ if err != nil {
229+ t.Fatalf("Failed to list active notes: %v", err)
230+ }
231+232+ if len(results) != 2 {
233+ t.Errorf("Expected 2 active notes, got %d", len(results))
234+ }
235+ for _, note := range results {
236+ if note.Archived {
237+ t.Error("Retrieved note should not be archived")
238+ }
239+ }
240+ })
241+242+ t.Run("Search by Title", func(t *testing.T) {
243+ results, err := repo.List(ctx, NoteListOptions{Title: "First"})
244+ if err != nil {
245+ t.Fatalf("Failed to search by title: %v", err)
246+ }
247+248+ if len(results) != 1 {
249+ t.Errorf("Expected 1 note, got %d", len(results))
250+ }
251+ if results[0].Title != "First Note" {
252+ t.Errorf("Expected 'First Note', got %s", results[0].Title)
253+ }
254+ })
255+256+ t.Run("Search by Content", func(t *testing.T) {
257+ results, err := repo.List(ctx, NoteListOptions{Content: "Important"})
258+ if err != nil {
259+ t.Fatalf("Failed to search by content: %v", err)
260+ }
261+262+ if len(results) != 1 {
263+ t.Errorf("Expected 1 note, got %d", len(results))
264+ }
265+ if results[0].Title != "Third Note" {
266+ t.Errorf("Expected 'Third Note', got %s", results[0].Title)
267+ }
268+ })
269+270+ t.Run("Limit and Offset", func(t *testing.T) {
271+ results, err := repo.List(ctx, NoteListOptions{Limit: 2})
272+ if err != nil {
273+ t.Fatalf("Failed to list with limit: %v", err)
274+ }
275+276+ if len(results) != 2 {
277+ t.Errorf("Expected 2 notes, got %d", len(results))
278+ }
279+280+ results, err = repo.List(ctx, NoteListOptions{Limit: 2, Offset: 1})
281+ if err != nil {
282+ t.Fatalf("Failed to list with limit and offset: %v", err)
283+ }
284+285+ if len(results) != 2 {
286+ t.Errorf("Expected 2 notes with offset, got %d", len(results))
287+ }
288+ })
289+}
290+291+func TestNoteRepository_SpecializedMethods(t *testing.T) {
292+ db := createNoteTestDB(t)
293+ repo := NewNoteRepository(db)
294+ ctx := context.Background()
295+296+ notes := []*models.Note{
297+ {Title: "Work Note", Content: "Work content", Tags: []string{"work"}, Archived: false},
298+ {Title: "Personal Note", Content: "Personal content", Tags: []string{"personal"}, Archived: true},
299+ {Title: "Important Note", Content: "Important content", Tags: []string{"work", "important"}, Archived: false},
300+ }
301+302+ for _, note := range notes {
303+ _, err := repo.Create(ctx, note)
304+ if err != nil {
305+ t.Fatalf("Failed to create test note: %v", err)
306+ }
307+ }
308+309+ t.Run("GetByTitle", func(t *testing.T) {
310+ results, err := repo.GetByTitle(ctx, "Work")
311+ if err != nil {
312+ t.Fatalf("Failed to get by title: %v", err)
313+ }
314+315+ if len(results) != 1 {
316+ t.Errorf("Expected 1 note, got %d", len(results))
317+ }
318+ if results[0].Title != "Work Note" {
319+ t.Errorf("Expected 'Work Note', got %s", results[0].Title)
320+ }
321+ })
322+323+ t.Run("GetArchived", func(t *testing.T) {
324+ results, err := repo.GetArchived(ctx)
325+ if err != nil {
326+ t.Fatalf("Failed to get archived notes: %v", err)
327+ }
328+329+ if len(results) != 1 {
330+ t.Errorf("Expected 1 archived note, got %d", len(results))
331+ }
332+ if !results[0].Archived {
333+ t.Error("Retrieved note should be archived")
334+ }
335+ })
336+337+ t.Run("GetActive", func(t *testing.T) {
338+ results, err := repo.GetActive(ctx)
339+ if err != nil {
340+ t.Fatalf("Failed to get active notes: %v", err)
341+ }
342+343+ if len(results) != 2 {
344+ t.Errorf("Expected 2 active notes, got %d", len(results))
345+ }
346+ for _, note := range results {
347+ if note.Archived {
348+ t.Error("Retrieved note should not be archived")
349+ }
350+ }
351+ })
352+353+ t.Run("Archive and Unarchive", func(t *testing.T) {
354+ note := &models.Note{
355+ Title: "Test Archive",
356+ Content: "Archive test",
357+ Archived: false,
358+ }
359+ id, err := repo.Create(ctx, note)
360+ if err != nil {
361+ t.Fatalf("Failed to create note: %v", err)
362+ }
363+364+ err = repo.Archive(ctx, id)
365+ if err != nil {
366+ t.Fatalf("Failed to archive note: %v", err)
367+ }
368+369+ retrieved, err := repo.Get(ctx, id)
370+ if err != nil {
371+ t.Fatalf("Failed to get note: %v", err)
372+ }
373+ if !retrieved.Archived {
374+ t.Error("Note should be archived")
375+ }
376+377+ err = repo.Unarchive(ctx, id)
378+ if err != nil {
379+ t.Fatalf("Failed to unarchive note: %v", err)
380+ }
381+382+ retrieved, err = repo.Get(ctx, id)
383+ if err != nil {
384+ t.Fatalf("Failed to get note: %v", err)
385+ }
386+ if retrieved.Archived {
387+ t.Error("Note should not be archived")
388+ }
389+ })
390+391+ t.Run("SearchContent", func(t *testing.T) {
392+ results, err := repo.SearchContent(ctx, "Important")
393+ if err != nil {
394+ t.Fatalf("Failed to search content: %v", err)
395+ }
396+397+ if len(results) != 1 {
398+ t.Errorf("Expected 1 note, got %d", len(results))
399+ }
400+ if results[0].Title != "Important Note" {
401+ t.Errorf("Expected 'Important Note', got %s", results[0].Title)
402+ }
403+ })
404+405+ t.Run("GetRecent", func(t *testing.T) {
406+ results, err := repo.GetRecent(ctx, 2)
407+ if err != nil {
408+ t.Fatalf("Failed to get recent notes: %v", err)
409+ }
410+411+ if len(results) != 2 {
412+ t.Errorf("Expected 2 notes, got %d", len(results))
413+ }
414+ })
415+}
416+417+func TestNoteRepository_TagMethods(t *testing.T) {
418+ db := createNoteTestDB(t)
419+ repo := NewNoteRepository(db)
420+ ctx := context.Background()
421+422+ note := &models.Note{
423+ Title: "Tag Test Note",
424+ Content: "Testing tags",
425+ Tags: []string{"initial"},
426+ }
427+ id, err := repo.Create(ctx, note)
428+ if err != nil {
429+ t.Fatalf("Failed to create note: %v", err)
430+ }
431+432+ t.Run("AddTag", func(t *testing.T) {
433+ err := repo.AddTag(ctx, id, "new-tag")
434+ if err != nil {
435+ t.Fatalf("Failed to add tag: %v", err)
436+ }
437+438+ retrieved, err := repo.Get(ctx, id)
439+ if err != nil {
440+ t.Fatalf("Failed to get note: %v", err)
441+ }
442+443+ if len(retrieved.Tags) != 2 {
444+ t.Errorf("Expected 2 tags, got %d", len(retrieved.Tags))
445+ }
446+447+ found := false
448+ for _, tag := range retrieved.Tags {
449+ if tag == "new-tag" {
450+ found = true
451+ break
452+ }
453+ }
454+ if !found {
455+ t.Error("New tag not found in note")
456+ }
457+ })
458+459+ t.Run("AddTag Duplicate", func(t *testing.T) {
460+ err := repo.AddTag(ctx, id, "new-tag")
461+ if err != nil {
462+ t.Fatalf("Failed to add duplicate tag: %v", err)
463+ }
464+465+ retrieved, err := repo.Get(ctx, id)
466+ if err != nil {
467+ t.Fatalf("Failed to get note: %v", err)
468+ }
469+470+ if len(retrieved.Tags) != 2 {
471+ t.Errorf("Expected 2 tags (no duplicate), got %d", len(retrieved.Tags))
472+ }
473+ })
474+475+ t.Run("RemoveTag", func(t *testing.T) {
476+ err := repo.RemoveTag(ctx, id, "initial")
477+ if err != nil {
478+ t.Fatalf("Failed to remove tag: %v", err)
479+ }
480+481+ retrieved, err := repo.Get(ctx, id)
482+ if err != nil {
483+ t.Fatalf("Failed to get note: %v", err)
484+ }
485+486+ if len(retrieved.Tags) != 1 {
487+ t.Errorf("Expected 1 tag after removal, got %d", len(retrieved.Tags))
488+ }
489+490+ for _, tag := range retrieved.Tags {
491+ if tag == "initial" {
492+ t.Error("Removed tag still found in note")
493+ }
494+ }
495+ })
496+497+ t.Run("GetByTags", func(t *testing.T) {
498+ note1 := &models.Note{
499+ Title: "Note 1",
500+ Content: "Content 1",
501+ Tags: []string{"work", "urgent"},
502+ }
503+ note2 := &models.Note{
504+ Title: "Note 2",
505+ Content: "Content 2",
506+ Tags: []string{"personal", "ideas"},
507+ }
508+ note3 := &models.Note{
509+ Title: "Note 3",
510+ Content: "Content 3",
511+ Tags: []string{"work", "planning"},
512+ }
513+514+ _, err := repo.Create(ctx, note1)
515+ if err != nil {
516+ t.Fatalf("Failed to create note1: %v", err)
517+ }
518+ _, err = repo.Create(ctx, note2)
519+ if err != nil {
520+ t.Fatalf("Failed to create note2: %v", err)
521+ }
522+ _, err = repo.Create(ctx, note3)
523+ if err != nil {
524+ t.Fatalf("Failed to create note3: %v", err)
525+ }
526+527+ results, err := repo.GetByTags(ctx, []string{"work"})
528+ if err != nil {
529+ t.Fatalf("Failed to get notes by tag: %v", err)
530+ }
531+532+ if len(results) < 2 {
533+ t.Errorf("Expected at least 2 notes with 'work' tag, got %d", len(results))
534+ }
535+536+ results, err = repo.GetByTags(ctx, []string{"nonexistent"})
537+ if err != nil {
538+ t.Fatalf("Failed to get notes by nonexistent tag: %v", err)
539+ }
540+541+ if len(results) != 0 {
542+ t.Errorf("Expected 0 notes with nonexistent tag, got %d", len(results))
543+ }
544+545+ results, err = repo.GetByTags(ctx, []string{})
546+ if err != nil {
547+ t.Fatalf("Failed to get notes with empty tags: %v", err)
548+ }
549+550+ if len(results) != 0 {
551+ t.Errorf("Expected 0 notes with empty tag list, got %d", len(results))
552+ }
553+ })
554+}
555+556+func TestNoteRepository_ErrorCases(t *testing.T) {
557+ db := createNoteTestDB(t)
558+ repo := NewNoteRepository(db)
559+ ctx := context.Background()
560+561+ t.Run("Get Nonexistent Note", func(t *testing.T) {
562+ _, err := repo.Get(ctx, 999)
563+ if err == nil {
564+ t.Error("Expected error when getting nonexistent note")
565+ }
566+ })
567+568+ t.Run("Update Nonexistent Note", func(t *testing.T) {
569+ note := &models.Note{
570+ ID: 999,
571+ Title: "Nonexistent",
572+ Content: "Should fail",
573+ }
574+575+ err := repo.Update(ctx, note)
576+ if err == nil {
577+ t.Error("Expected error when updating nonexistent note")
578+ }
579+ })
580+581+ t.Run("Delete Nonexistent Note", func(t *testing.T) {
582+ err := repo.Delete(ctx, 999)
583+ if err == nil {
584+ t.Error("Expected error when deleting nonexistent note")
585+ }
586+ })
587+588+ t.Run("Archive Nonexistent Note", func(t *testing.T) {
589+ err := repo.Archive(ctx, 999)
590+ if err == nil {
591+ t.Error("Expected error when archiving nonexistent note")
592+ }
593+ })
594+595+ t.Run("AddTag to Nonexistent Note", func(t *testing.T) {
596+ err := repo.AddTag(ctx, 999, "tag")
597+ if err == nil {
598+ t.Error("Expected error when adding tag to nonexistent note")
599+ }
600+ })
601+}
602+603+func TestNoteRepository_EdgeCases(t *testing.T) {
604+ db := createNoteTestDB(t)
605+ repo := NewNoteRepository(db)
606+ ctx := context.Background()
607+608+ t.Run("Note with Empty Tags", func(t *testing.T) {
609+ note := &models.Note{
610+ Title: "No Tags Note",
611+ Content: "This note has no tags",
612+ Tags: []string{},
613+ }
614+615+ id, err := repo.Create(ctx, note)
616+ if err != nil {
617+ t.Fatalf("Failed to create note with empty tags: %v", err)
618+ }
619+620+ retrieved, err := repo.Get(ctx, id)
621+ if err != nil {
622+ t.Fatalf("Failed to get note: %v", err)
623+ }
624+625+ if len(retrieved.Tags) != 0 {
626+ t.Errorf("Expected empty tags slice, got %d tags", len(retrieved.Tags))
627+ }
628+ })
629+630+ t.Run("Note with Nil Tags", func(t *testing.T) {
631+ note := &models.Note{
632+ Title: "Nil Tags Note",
633+ Content: "This note has nil tags",
634+ Tags: nil,
635+ }
636+637+ id, err := repo.Create(ctx, note)
638+ if err != nil {
639+ t.Fatalf("Failed to create note with nil tags: %v", err)
640+ }
641+642+ retrieved, err := repo.Get(ctx, id)
643+ if err != nil {
644+ t.Fatalf("Failed to get note: %v", err)
645+ }
646+647+ if retrieved.Tags != nil {
648+ t.Errorf("Expected nil tags, got %v", retrieved.Tags)
649+ }
650+ })
651+652+ t.Run("Note with Long Content", func(t *testing.T) {
653+ longContent := ""
654+ for i := 0; i < 1000; i++ {
655+ longContent += "This is a very long content string. "
656+ }
657+658+ note := &models.Note{
659+ Title: "Long Content Note",
660+ Content: longContent,
661+ }
662+663+ id, err := repo.Create(ctx, note)
664+ if err != nil {
665+ t.Fatalf("Failed to create note with long content: %v", err)
666+ }
667+668+ retrieved, err := repo.Get(ctx, id)
669+ if err != nil {
670+ t.Fatalf("Failed to get note: %v", err)
671+ }
672+673+ if retrieved.Content != longContent {
674+ t.Error("Long content was not stored/retrieved correctly")
675+ }
676+ })
677+}
+2
internal/repo/repo.go
···10 Movies *MovieRepository
11 TV *TVRepository
12 Books *BookRepository
013}
1415// NewRepositories creates a new set of repositories
···19 Movies: NewMovieRepository(db),
20 TV: NewTVRepository(db),
21 Books: NewBookRepository(db),
022 }
23}
···10 Movies *MovieRepository
11 TV *TVRepository
12 Books *BookRepository
13+ Notes *NoteRepository
14}
1516// NewRepositories creates a new set of repositories
···20 Movies: NewMovieRepository(db),
21 TV: NewTVRepository(db),
22 Books: NewBookRepository(db),
23+ Notes: NewNoteRepository(db),
24 }
25}
+44-1
internal/repo/repositories_test.go
···20 t.Fatalf("Failed to enable foreign keys: %v", err)
21 }
2223- // Create all tables
24 schema := `
25 -- Tasks table
26 CREATE TABLE IF NOT EXISTS tasks (
···78 started DATETIME,
79 finished DATETIME
80 );
00000000000081 `
8283 if _, err := db.Exec(schema); err != nil {
···155 if bookID == 0 {
156 t.Error("Expected non-zero book ID")
157 }
0000000000000158 })
159160 t.Run("Retrieve all resources", func(t *testing.T) {
···188 }
189 if len(books) != 1 {
190 t.Errorf("Expected 1 book, got %d", len(books))
00000000191 }
192 })
193···257 if len(queuedBooks) != 1 {
258 t.Errorf("Expected 1 queued book, got %d", len(queuedBooks))
259 }
00000000260 })
261 })
262···276 }
277 if repos.Books == nil {
278 t.Error("Books repository should be initialized")
000279 }
280 })
281
···20 t.Fatalf("Failed to enable foreign keys: %v", err)
21 }
22023 schema := `
24 -- Tasks table
25 CREATE TABLE IF NOT EXISTS tasks (
···77 started DATETIME,
78 finished DATETIME
79 );
80+81+ -- Notes table
82+ CREATE TABLE IF NOT EXISTS notes (
83+ id INTEGER PRIMARY KEY AUTOINCREMENT,
84+ title TEXT NOT NULL,
85+ content TEXT NOT NULL,
86+ tags TEXT,
87+ archived BOOLEAN DEFAULT FALSE,
88+ created DATETIME DEFAULT CURRENT_TIMESTAMP,
89+ modified DATETIME DEFAULT CURRENT_TIMESTAMP,
90+ file_path TEXT
91+ );
92 `
9394 if _, err := db.Exec(schema); err != nil {
···166 if bookID == 0 {
167 t.Error("Expected non-zero book ID")
168 }
169+170+ note := &models.Note{
171+ Title: "Integration Note",
172+ Content: "This is test content for integration",
173+ Tags: []string{"integration", "test"},
174+ }
175+ noteID, err := repos.Notes.Create(ctx, note)
176+ if err != nil {
177+ t.Errorf("Failed to create note: %v", err)
178+ }
179+ if noteID == 0 {
180+ t.Error("Expected non-zero note ID")
181+ }
182 })
183184 t.Run("Retrieve all resources", func(t *testing.T) {
···212 }
213 if len(books) != 1 {
214 t.Errorf("Expected 1 book, got %d", len(books))
215+ }
216+217+ notes, err := repos.Notes.List(ctx, NoteListOptions{})
218+ if err != nil {
219+ t.Errorf("Failed to list notes: %v", err)
220+ }
221+ if len(notes) != 1 {
222+ t.Errorf("Expected 1 note, got %d", len(notes))
223 }
224 })
225···289 if len(queuedBooks) != 1 {
290 t.Errorf("Expected 1 queued book, got %d", len(queuedBooks))
291 }
292+293+ activeNotes, err := repos.Notes.GetActive(ctx)
294+ if err != nil {
295+ t.Errorf("Failed to get active notes: %v", err)
296+ }
297+ if len(activeNotes) != 1 {
298+ t.Errorf("Expected 1 active note, got %d", len(activeNotes))
299+ }
300 })
301 })
302···316 }
317 if repos.Books == nil {
318 t.Error("Books repository should be initialized")
319+ }
320+ if repos.Notes == nil {
321+ t.Error("Notes repository should be initialized")
322 }
323 })
324