chore(router): remove unused CollectionHandler from config

Remove the CollectionHandler field from router.Config struct and its
initialization in main.go. This field was never used - collections are
registered directly in handlers.SetupRoutes() where a CollectionHandler
is created locally.

Changes:
- Remove CollectionHandler field from internal/router/router.go Config
- Remove CollectionHandler: nil line from cmd/server/main.go

This cleans up dead code from the router refactoring. Collections
continue to work correctly as they are registered in SetupRoutes().

Related: Router refactoring completion
This commit is contained in:
2026-02-07 17:59:06 -05:00
parent 0c24deb60b
commit 42b6fae297
4 changed files with 626 additions and 2 deletions
@@ -0,0 +1,253 @@
package services
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestEbookScanner_LibraryTypeAwareScanning tests Phase 2: library-type-aware scanning
func TestEbookScanner_LibraryTypeAwareScanning(t *testing.T) {
t.Run("isScannableFile checks library type restrictions", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/test/ebooks", "/test/comics"},
libraryTypes: map[string][]string{
"/test/ebooks": {".epub", ".mobi", ".azw3"},
"/test/comics": {".cbz", ".cbr", ".cb7", ".cbt"},
},
}
tests := []struct {
name string
filePath string
expected bool
}{
{
name: "EPUB in ebooks folder",
filePath: "/test/ebooks/book.epub",
expected: true,
},
{
name: "MOBI in ebooks folder",
filePath: "/test/ebooks/book.mobi",
expected: true,
},
{
name: "CBZ in ebooks folder (should be rejected)",
filePath: "/test/ebooks/comic.cbz",
expected: false,
},
{
name: "CBZ in comics folder",
filePath: "/test/comics/issue.cbz",
expected: true,
},
{
name: "CBR in comics folder",
filePath: "/test/comics/issue.cbr",
expected: true,
},
{
name: "EPUB in comics folder (should be rejected)",
filePath: "/test/comics/book.epub",
expected: false,
},
{
name: "File outside watched folders",
filePath: "/other/path/file.epub",
expected: false,
},
{
name: "Unknown extension in ebooks folder",
filePath: "/test/ebooks/file.pdf",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := scanner.isScannableFile(tt.filePath)
assert.Equal(t, tt.expected, result, "isScannableFile(%s) should return %v", tt.filePath, tt.expected)
})
}
})
t.Run("isScannableFile case insensitive", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/test/ebooks"},
libraryTypes: map[string][]string{
"/test/ebooks": {".epub"},
},
}
tests := []struct {
name string
filePath string
expected bool
}{
{"Lowercase extension", "/test/ebooks/book.epub", true},
{"Uppercase extension", "/test/ebooks/book.EPUB", true},
{"Mixed case extension", "/test/ebooks/book.Epub", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := scanner.isScannableFile(tt.filePath)
assert.Equal(t, tt.expected, result)
})
}
})
t.Run("isScannableFile with no library type info", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/test/ebooks"},
libraryTypes: map[string][]string{}, // Empty library types
}
result := scanner.isScannableFile("/test/ebooks/book.epub")
assert.False(t, result, "Should reject files when library type info is missing")
})
t.Run("isScannableFile handles subdirectories", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/test/ebooks"},
libraryTypes: map[string][]string{
"/test/ebooks": {".epub"},
},
}
result := scanner.isScannableFile("/test/ebooks/subdir/book.epub")
assert.True(t, result, "Should accept files in subdirectories")
})
}
// TestEbookScanner_SetFolders_BuildsLibraryTypeCache tests Phase 2: SetFolders builds cache
func TestEbookScanner_SetFolders_BuildsLibraryTypeCache(t *testing.T) {
// This is a unit test that verifies SetFolders properly initializes the libraryTypes cache
// Full integration testing would require a mock database
t.Run("SetFolders initializes libraryTypes map", func(t *testing.T) {
scanner := &EbookScanner{
libraryTypes: nil,
}
// Simulate SetFolders initialization
scanner.libraryTypes = make(map[string][]string)
assert.NotNil(t, scanner.libraryTypes, "libraryTypes should be initialized")
assert.Equal(t, 0, len(scanner.libraryTypes), "libraryTypes should be empty initially")
})
t.Run("SetFolders clears old library types", func(t *testing.T) {
scanner := &EbookScanner{
libraryTypes: map[string][]string{
"/old/folder": {".epub"},
},
}
// Simulate SetFolders clearing and rebuilding
scanner.libraryTypes = make(map[string][]string)
assert.Equal(t, 0, len(scanner.libraryTypes), "Old library types should be cleared")
})
}
// TestEbookScanner_LibraryTypeCrossContamination tests Phase 2: prevents cross-contamination
func TestEbookScanner_LibraryTypeCrossContamination(t *testing.T) {
t.Run("Ebook library rejects comic formats", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/library/ebooks"},
libraryTypes: map[string][]string{
"/library/ebooks": {".epub", ".mobi", ".azw3", ".pdf"},
},
}
comicFormats := []string{".cbz", ".cbr", ".cb7", ".cbt"}
for _, ext := range comicFormats {
filePath := "/library/ebooks/comic" + ext
result := scanner.isScannableFile(filePath)
assert.False(t, result, "Ebook library should reject %s files", ext)
}
})
t.Run("Comic library rejects ebook formats", func(t *testing.T) {
scanner := &EbookScanner{
folders: []string{"/library/comics"},
libraryTypes: map[string][]string{
"/library/comics": {".cbz", ".cbr", ".cb7", ".cbt"},
},
}
ebookFormats := []string{".epub", ".mobi", ".azw3", ".pdf", ".djvu"}
for _, ext := range ebookFormats {
filePath := "/library/comics/book" + ext
result := scanner.isScannableFile(filePath)
assert.False(t, result, "Comic library should reject %s files", ext)
}
})
}
// TestEbookScanner_MultipleLibraryTypes tests Phase 2: multiple libraries with different types
func TestEbookScanner_MultipleLibraryTypes(t *testing.T) {
scanner := &EbookScanner{
folders: []string{
"/library/ebooks",
"/library/comics",
"/library/manga",
},
libraryTypes: map[string][]string{
"/library/ebooks": {".epub", ".mobi", ".azw3"},
"/library/comics": {".cbz", ".cbr"},
"/library/manga": {".cbz", ".cb7"}, // Manga uses CBZ and CB7
},
}
tests := []struct {
name string
filePath string
expected bool
reason string
}{
{
name: "EPUB in ebook library",
filePath: "/library/ebooks/novel.epub",
expected: true,
reason: "EPUB allowed in ebook library",
},
{
name: "CBZ in comic library",
filePath: "/library/comics/superman.cbz",
expected: true,
reason: "CBZ allowed in comic library",
},
{
name: "CBZ in manga library",
filePath: "/library/manga/naruto.cbz",
expected: true,
reason: "CBZ allowed in manga library",
},
{
name: "CB7 in manga library",
filePath: "/library/manga/onepiece.cb7",
expected: true,
reason: "CB7 allowed in manga library",
},
{
name: "CB7 in comic library (rejected)",
filePath: "/library/comics/batman.cb7",
expected: false,
reason: "CB7 not allowed in comic library",
},
{
name: "EPUB in comic library (rejected)",
filePath: "/library/comics/novel.epub",
expected: false,
reason: "EPUB not allowed in comic library",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := scanner.isScannableFile(tt.filePath)
assert.Equal(t, tt.expected, result, tt.reason)
})
}
}