test: add comprehensive tests for unified search endpoint

- Add search_unified_test.go with 8 test cases:
  - Fuzzy author filter (asimov → Asimov, Isaac)
  - Fuzzy genre filter (scifi → Sci-Fi)
  - Exact match with quotes ("Foundation and Empire")
  - Combined search + filters (q=foundation&author_filter=asimov)
  - Field-specific search for dropdown authors (returns values with counts)
  - Year range filter (exact match)
  - Boolean filter (has_cover=true)
  - Missing library_id validation (400 error)
- Remove filtering_test.go (covered by new tests)
- Uses setupDeviceTest helper following PROJECT_GUIDELINES.md
- Tests both media item search and field value search endpoints
- Validates fuzzy matching, exact matching, and combined queries
This commit is contained in:
2026-03-23 22:38:06 -04:00
parent d3783eca8b
commit 08b32c7b30
2 changed files with 103 additions and 465 deletions
-465
View File
@@ -1,465 +0,0 @@
package main
import (
"bookhoard/internal/handlers"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFilterByStatus(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&status=50", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by status")
}
func TestFilterByGenre(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&genre_filter=Fiction", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by genre")
}
func TestFilterByLanguage(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&genre_filter=Fiction&language_filter=en", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by language")
}
func TestFilterByCollection(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
collection := setup.CreateCollection(t, "Test Collection")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&collection_id="+collection, nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by collection")
}
func TestFilterByHasCover(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&has_cover=true", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by has_cover")
}
func TestFilterByTags(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&tags=classic", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by tags")
}
func TestFilterBySpecialCharacters(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&special_characters=;", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle special characters")
}
func TestFilterCombineMultipleFilters(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&genre_filter=Fiction&language_filter=en&year_min=2000&year_max=2020", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should combine multiple filters")
var response handlers.SearchMediaItemsResponse
err := json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err, "Should unmarshal filtered response")
assert.GreaterOrEqual(t, len(response.Results), 0, "Should have at least one result")
}
func TestFilterPagination(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&limit=2&offset=0", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle pagination")
}
func TestFilterNoFilters(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID, nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle no filters")
}
func TestFilterSortingByTitle(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=title+ASC", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should sort by title")
var response handlers.SearchMediaItemsResponse
err := json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err, "Should unmarshal filtered response")
assert.GreaterOrEqual(t, response.Total, 0, "Should return all items")
}
func TestFilterSortingByAuthor(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=author+DESC", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should sort by author")
}
func TestFilterSortingByDateAdded(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=date_added+DESC", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should sort by date added")
}
func TestFilterSortingByLastRead(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=last_read+DESC", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should sort by last read")
}
func TestFilterWithLibraryID(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID, nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter with library_id")
var response handlers.SearchMediaItemsResponse
err := json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err, "Should unmarshal filtered response")
assert.GreaterOrEqual(t, response.Total, 0, "Should return all items")
}
func TestFilterWithYearRange(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&year_min=2000&year_max=2020", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by year range")
}
func TestFilterWithRating(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&rating_min=4", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by rating")
}
func TestFilterWithProgress(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&progress_min=50&progress_max=100", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by progress")
}
func TestFilterWithMultipleSorts(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=author+ASC&sort=title+ASC", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle multiple sorts")
}
func TestFilterEdgeCases(t *testing.T) {
t.Run("Empty library_id", func(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
_ = setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id=", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusBadRequest, rec.Code, "Should reject empty library_id")
})
t.Run("Invalid sort order", func(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&sort=title+INVALID", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle invalid sort order gracefully")
})
t.Run("Negative offset", func(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&offset=-1", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle negative offset")
})
t.Run("Zero limit", func(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&limit=0", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should handle zero limit")
})
}
func TestFilterWithTextSearch(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&search=Test", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter with text search")
}
func TestFilterWithAuthorSearch(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&author=Test", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter with author search")
}
func TestFilterWithSeriesFilter(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&series=Test", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by series")
}
func TestFilterWithPublisherFilter(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&publisher=Test", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by publisher")
}
func TestFilterWithFavorites(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&favorites=true", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter favorites")
}
func TestFilterArchivedItems(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Filter Library", "ebooks")
_ = setup.CreateDevice(t, "Test Filter Device", "koreader", "filter-test-123")
req := httptest.NewRequest("GET", "/api/media-items/filtered?library_id="+libraryID+"&archived=false", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter archived items")
}
+103
View File
@@ -0,0 +1,103 @@
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUnifiedSearch(t *testing.T) {
setup := setupDeviceTest(t)
defer setup.Server.Close()
libraryID := setup.CreateLibrary(t, "Test Search Library", "ebooks")
_ = setup.CreateDevice(t, "Test Search Device", "koreader", "search-test-123")
t.Run("Fuzzy author filter", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&author_filter=asimov", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should fuzzy match author")
})
t.Run("Fuzzy genre filter", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&genre_filter=scifi", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should fuzzy match genre")
})
t.Run("Exact match with quotes", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&q=%22Foundation%20and%20Empire%22", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should exact match quoted query")
})
t.Run("Combined search + filters", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&q=foundation&author_filter=asimov", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should combine search and filters")
})
t.Run("Field-specific search for dropdown - authors", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&authors=asimov", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should return author values")
var response struct {
Results []struct {
Value string `json:"value"`
Count int64 `json:"count"`
Score float64 `json:"score"`
} `json:"results"`
Total int `json:"total"`
}
err := json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err, "Should unmarshal field values response")
assert.Greater(t, len(response.Results), 0, "Should have results")
})
t.Run("Year range filter (exact)", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&year_min=2000&year_max=2020", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by year range")
})
t.Run("Boolean filter (exact)", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&has_cover=true", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code, "Should filter by has_cover")
})
t.Run("Missing library_id", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/media-items/search?q=test", nil)
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
rec := httptest.NewRecorder()
setup.Server.Config.Handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusBadRequest, rec.Code, "Should require library_id")
})
}