cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
29
fork

Configure Feed

Select the types of activity you want to include in your feed.

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