aboutsummaryrefslogtreecommitdiffstats
path: root/internal/importer
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-02-18 06:18:28 +0000
committerClaude <noreply@anthropic.com>2026-02-18 06:18:28 +0000
commit269e44da41f9feed32214bbab6fc16ec88fffd85 (patch)
tree6c6312b8ad3fd9175b2992e3e044fa6257e3ef43 /internal/importer
parent8eb86cdc49c3c2f69d8a64f855220ebd68be336c (diff)
downloadneko-269e44da41f9feed32214bbab6fc16ec88fffd85.tar.gz
neko-269e44da41f9feed32214bbab6fc16ec88fffd85.tar.bz2
neko-269e44da41f9feed32214bbab6fc16ec88fffd85.zip
Increase test coverage across lowest-coverage packagesclaude/improve-test-coverage-iBkwc
Major coverage improvements: - safehttp: 46.7% -> 93.3% (SafeDialer, redirect checking, SSRF protection) - api: 81.8% -> 96.4% (HandleImport 0% -> 100%, stream errors, content types) - importer: 85.3% -> 94.7% (ImportFeeds dispatcher, OPML nesting, edge cases) - cmd/neko: 77.1% -> 85.4% (purge, secure-cookies, minutes, allow-local flags) New tests added: - Security regression tests (CSRF token uniqueness, mismatch rejection, auth cookie HttpOnly, security headers, API auth requirements) - Stress tests for concurrent mixed operations and rapid state toggling - SSRF protection tests for SafeDialer hostname resolution and redirect paths https://claude.ai/code/session_01XUBh32rHpbYue1JYXSH64Q
Diffstat (limited to 'internal/importer')
-rw-r--r--internal/importer/importer_test.go178
1 files changed, 178 insertions, 0 deletions
diff --git a/internal/importer/importer_test.go b/internal/importer/importer_test.go
index 59f06f1..631c441 100644
--- a/internal/importer/importer_test.go
+++ b/internal/importer/importer_test.go
@@ -3,6 +3,7 @@ package importer
import (
"os"
"path/filepath"
+ "strings"
"testing"
"adammathes.com/neko/config"
@@ -147,3 +148,180 @@ func TestImportJSONNonexistent(t *testing.T) {
t.Error("ImportJSON should error on nonexistent file")
}
}
+
+// Test the ImportFeeds dispatcher function (previously 0% coverage)
+func TestImportFeedsOPML(t *testing.T) {
+ setupTestDB(t)
+
+ opml := `<?xml version="1.0" encoding="UTF-8"?>
+<opml version="2.0">
+ <head><title>test</title></head>
+ <body>
+ <outline type="rss" text="Feed A" xmlUrl="https://a.com/feed" htmlUrl="https://a.com"/>
+ </body>
+</opml>`
+
+ err := ImportFeeds("opml", strings.NewReader(opml))
+ if err != nil {
+ t.Fatalf("ImportFeeds(opml) failed: %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM feed").Scan(&count)
+ if count != 1 {
+ t.Errorf("expected 1 feed, got %d", count)
+ }
+}
+
+func TestImportFeedsText(t *testing.T) {
+ setupTestDB(t)
+
+ text := "https://example.com/feed1\nhttps://example.com/feed2\n"
+
+ err := ImportFeeds("text", strings.NewReader(text))
+ if err != nil {
+ t.Fatalf("ImportFeeds(text) failed: %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM feed").Scan(&count)
+ if count != 2 {
+ t.Errorf("expected 2 feeds, got %d", count)
+ }
+}
+
+func TestImportFeedsJSON(t *testing.T) {
+ setupTestDB(t)
+
+ jsonContent := `{"title":"A1","url":"https://example.com/1","description":"d","feed":{"url":"https://example.com/feed","title":"F1"}}`
+
+ err := ImportFeeds("json", strings.NewReader(jsonContent))
+ if err != nil {
+ t.Fatalf("ImportFeeds(json) failed: %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM item").Scan(&count)
+ if count != 1 {
+ t.Errorf("expected 1 item, got %d", count)
+ }
+}
+
+func TestImportFeedsUnsupported(t *testing.T) {
+ err := ImportFeeds("csv", strings.NewReader("data"))
+ if err == nil {
+ t.Error("ImportFeeds should error for unsupported format")
+ }
+ if err != nil && !strings.Contains(err.Error(), "unsupported") {
+ t.Errorf("expected 'unsupported' error, got: %v", err)
+ }
+}
+
+func TestImportOPMLInvalid(t *testing.T) {
+ setupTestDB(t)
+ err := ImportOPML(strings.NewReader("not valid xml"))
+ if err == nil {
+ t.Error("ImportOPML should error on invalid XML")
+ }
+}
+
+func TestImportOPMLNestedCategories(t *testing.T) {
+ setupTestDB(t)
+
+ opml := `<?xml version="1.0" encoding="UTF-8"?>
+<opml version="2.0">
+ <head><title>test</title></head>
+ <body>
+ <outline text="Tech">
+ <outline text="Programming">
+ <outline type="rss" text="Blog A" xmlUrl="https://a.com/feed" htmlUrl="https://a.com"/>
+ </outline>
+ </outline>
+ <outline type="rss" xmlUrl="https://b.com/feed" htmlUrl="https://b.com" category="news"/>
+ </body>
+</opml>`
+
+ err := ImportOPML(strings.NewReader(opml))
+ if err != nil {
+ t.Fatalf("ImportOPML failed: %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM feed").Scan(&count)
+ if count != 2 {
+ t.Errorf("expected 2 feeds, got %d", count)
+ }
+
+ // Verify nested category is inherited
+ var category string
+ models.DB.QueryRow("SELECT category FROM feed WHERE url=?", "https://a.com/feed").Scan(&category)
+ if category != "Programming" {
+ t.Errorf("expected category 'Programming' for nested feed, got %q", category)
+ }
+
+ // Feed with category attribute
+ models.DB.QueryRow("SELECT category FROM feed WHERE url=?", "https://b.com/feed").Scan(&category)
+ if category != "news" {
+ t.Errorf("expected category 'news' for feed with category attr, got %q", category)
+ }
+}
+
+func TestInsertIItemNilDate(t *testing.T) {
+ setupTestDB(t)
+
+ ii := &IItem{
+ Title: "No Date Article",
+ Url: "https://example.com/nodate",
+ Description: "Article without date",
+ Date: nil,
+ Feed: &IFeed{
+ Url: "https://example.com/feed",
+ Title: "Test Feed",
+ },
+ }
+
+ err := InsertIItem(ii)
+ if err != nil {
+ t.Errorf("InsertIItem with nil date should not error, got %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM item").Scan(&count)
+ if count != 1 {
+ t.Errorf("expected 1 item, got %d", count)
+ }
+}
+
+func TestImportJSONReaderEmpty(t *testing.T) {
+ setupTestDB(t)
+
+ // Empty reader - should not error (just EOF immediately)
+ err := ImportJSONReader(strings.NewReader(""))
+ if err != nil {
+ t.Errorf("ImportJSONReader with empty input should not error, got %v", err)
+ }
+}
+
+func TestImportTextSkipsCommentsAndBlanks(t *testing.T) {
+ setupTestDB(t)
+
+ text := `
+# This is a comment
+https://example.com/feed1
+
+ # Another comment
+
+https://example.com/feed2
+`
+
+ err := ImportText(strings.NewReader(text))
+ if err != nil {
+ t.Fatalf("ImportText failed: %v", err)
+ }
+
+ var count int
+ models.DB.QueryRow("SELECT COUNT(*) FROM feed").Scan(&count)
+ if count != 2 {
+ t.Errorf("expected 2 feeds (comments and blanks skipped), got %d", count)
+ }
+}