diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-13 18:43:03 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-13 18:43:03 -0800 |
| commit | 21b4eec6c1e096573bcd5f2079bc21e23a960621 (patch) | |
| tree | 58c8fe2e86aef9859debd05344084e9060dc38c9 /models | |
| parent | 01d4bbe4b2842cb8c2e4319b6cf03d3050f38d06 (diff) | |
| download | neko-21b4eec6c1e096573bcd5f2079bc21e23a960621.tar.gz neko-21b4eec6c1e096573bcd5f2079bc21e23a960621.tar.bz2 neko-21b4eec6c1e096573bcd5f2079bc21e23a960621.zip | |
refactor(backend): improve testability and add tests (NK-6q9nyg)
Diffstat (limited to 'models')
| -rw-r--r-- | models/db.out | 6 | ||||
| -rw-r--r-- | models/feed/feed.out | 59 | ||||
| -rw-r--r-- | models/item/item_test.go | 72 |
3 files changed, 137 insertions, 0 deletions
diff --git a/models/db.out b/models/db.out new file mode 100644 index 0000000..3ee5101 --- /dev/null +++ b/models/db.out @@ -0,0 +1,6 @@ +mode: set +adammathes.com/neko/models/db.go:16.15,22.16 4 1 +adammathes.com/neko/models/db.go:22.16,24.3 1 0 +adammathes.com/neko/models/db.go:26.2,26.33 1 1 +adammathes.com/neko/models/db.go:26.33,28.3 1 1 +adammathes.com/neko/models/db.go:30.2,77.24 2 1 diff --git a/models/feed/feed.out b/models/feed/feed.out new file mode 100644 index 0000000..1f5b5fc --- /dev/null +++ b/models/feed/feed.out @@ -0,0 +1,59 @@ +mode: set +adammathes.com/neko/models/feed/feed.go:27.32,30.16 3 1 +adammathes.com/neko/models/feed/feed.go:30.16,32.3 1 0 +adammathes.com/neko/models/feed/feed.go:33.2,34.16 2 1 +adammathes.com/neko/models/feed/feed.go:34.16,36.3 1 1 +adammathes.com/neko/models/feed/feed.go:37.2,37.12 1 1 +adammathes.com/neko/models/feed/feed.go:40.29,42.2 1 1 +adammathes.com/neko/models/feed/feed.go:44.44,49.16 2 1 +adammathes.com/neko/models/feed/feed.go:49.16,51.3 1 0 +adammathes.com/neko/models/feed/feed.go:52.2,55.18 3 1 +adammathes.com/neko/models/feed/feed.go:55.18,59.17 4 1 +adammathes.com/neko/models/feed/feed.go:59.17,61.4 1 0 +adammathes.com/neko/models/feed/feed.go:62.3,62.27 1 1 +adammathes.com/neko/models/feed/feed.go:64.2,64.34 1 1 +adammathes.com/neko/models/feed/feed.go:64.34,66.3 1 0 +adammathes.com/neko/models/feed/feed.go:67.2,67.19 1 1 +adammathes.com/neko/models/feed/feed.go:70.25,71.23 1 1 +adammathes.com/neko/models/feed/feed.go:71.23,73.3 1 1 +adammathes.com/neko/models/feed/feed.go:75.2,75.15 1 1 +adammathes.com/neko/models/feed/feed.go:75.15,77.3 1 1 +adammathes.com/neko/models/feed/feed.go:79.2,79.21 1 1 +adammathes.com/neko/models/feed/feed.go:79.21,81.3 1 1 +adammathes.com/neko/models/feed/feed.go:83.2,85.78 1 1 +adammathes.com/neko/models/feed/feed.go:88.25,91.16 2 1 +adammathes.com/neko/models/feed/feed.go:91.16,93.3 1 0 +adammathes.com/neko/models/feed/feed.go:96.40,100.16 2 1 +adammathes.com/neko/models/feed/feed.go:100.16,102.3 1 1 +adammathes.com/neko/models/feed/feed.go:103.2,103.12 1 1 +adammathes.com/neko/models/feed/feed.go:106.31,109.16 2 1 +adammathes.com/neko/models/feed/feed.go:109.16,111.3 1 1 +adammathes.com/neko/models/feed/feed.go:113.2,116.12 3 1 +adammathes.com/neko/models/feed/feed.go:120.40,122.16 2 1 +adammathes.com/neko/models/feed/feed.go:122.16,125.3 1 1 +adammathes.com/neko/models/feed/feed.go:129.2,130.21 2 1 +adammathes.com/neko/models/feed/feed.go:132.18,133.13 1 1 +adammathes.com/neko/models/feed/feed.go:134.22,135.13 1 1 +adammathes.com/neko/models/feed/feed.go:136.29,137.13 1 1 +adammathes.com/neko/models/feed/feed.go:138.30,139.13 1 1 +adammathes.com/neko/models/feed/feed.go:143.2,148.58 4 1 +adammathes.com/neko/models/feed/feed.go:148.58,150.14 1 1 +adammathes.com/neko/models/feed/feed.go:150.14,153.4 1 1 +adammathes.com/neko/models/feed/feed.go:155.3,157.34 3 1 +adammathes.com/neko/models/feed/feed.go:157.34,159.4 1 1 +adammathes.com/neko/models/feed/feed.go:160.3,160.33 1 1 +adammathes.com/neko/models/feed/feed.go:160.33,162.4 1 1 +adammathes.com/neko/models/feed/feed.go:166.2,166.13 1 1 +adammathes.com/neko/models/feed/feed.go:166.13,168.3 1 1 +adammathes.com/neko/models/feed/feed.go:171.2,171.17 1 1 +adammathes.com/neko/models/feed/feed.go:171.17,173.3 1 1 +adammathes.com/neko/models/feed/feed.go:174.2,174.10 1 1 +adammathes.com/neko/models/feed/feed.go:177.40,183.16 2 1 +adammathes.com/neko/models/feed/feed.go:183.16,185.3 1 0 +adammathes.com/neko/models/feed/feed.go:186.2,189.18 3 1 +adammathes.com/neko/models/feed/feed.go:189.18,192.17 3 1 +adammathes.com/neko/models/feed/feed.go:192.17,194.4 1 0 +adammathes.com/neko/models/feed/feed.go:195.3,195.37 1 1 +adammathes.com/neko/models/feed/feed.go:197.2,197.34 1 1 +adammathes.com/neko/models/feed/feed.go:197.34,199.3 1 0 +adammathes.com/neko/models/feed/feed.go:200.2,200.24 1 1 diff --git a/models/item/item_test.go b/models/item/item_test.go index cbd0ca0..4e25aad 100644 --- a/models/item/item_test.go +++ b/models/item/item_test.go @@ -12,6 +12,7 @@ import ( "adammathes.com/neko/config" "adammathes.com/neko/models" + goose "github.com/advancedlogic/GoOse" ) func setupTestDB(t *testing.T) { @@ -582,3 +583,74 @@ func TestRewriteImagesEmpty(t *testing.T) { // Empty input may produce empty output — that's fine } } + +type mockExtractor struct { + Article *goose.Article + Err error +} + +func (m *mockExtractor) Extract(url string) (*goose.Article, error) { + return m.Article, m.Err +} + +func TestGetFullContentWithMock(t *testing.T) { + setupTestDB(t) + feedId := createTestFeed(t) + + oldExtractor := Extractor + defer func() { Extractor = oldExtractor }() + + mock := &mockExtractor{ + Article: &goose.Article{ + CleanedText: "Mocked content", + TopNode: nil, // goose.TopNode is complex, simpler to mock article itself + }, + } + Extractor = mock + + i := &Item{Url: "http://mock", FeedId: feedId} + i.Create() + i.GetFullContent() + + // Since TopNode is nil, FullContent (sanitized HTML) won't be set, + // but md (CleanedText) should be saved in DB. + var md string + err := models.DB.QueryRow("SELECT full_content FROM item WHERE id=?", i.Id).Scan(&md) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(md, "Mocked content") { + t.Errorf("Expected mocked content in DB, got %q", md) + } +} + +func TestRewriteImagesNoSrc(t *testing.T) { + input := `<html><body><img alt="no src"/></body></html>` + result := rewriteImages(input) + if !strings.Contains(result, "alt=\"no src\"") { + t.Errorf("Expected alt attribute to be preserved, got %q", result) + } +} + +func TestRewriteImagesSrcset(t *testing.T) { + input := `<html><body><img srcset="img1.jpg 1x, img2.jpg 2x" src="img1.jpg"/></body></html>` + result := rewriteImages(input) + if !strings.Contains(result, "/image/") { + t.Errorf("Expected srcset to be proxied, got %q", result) + } +} + +func TestItemSaveError(t *testing.T) { + setupTestDB(t) + i := &Item{Id: 1} + // Close DB to force error + models.DB.Close() + i.Save() // Should not panic, just log error +} + +func TestItemFullSaveError(t *testing.T) { + setupTestDB(t) + i := &Item{Id: 1} + models.DB.Close() + i.FullSave() // Should not panic +} |
