test: rewrite filtering tests with proper struct types

- Convert all map-based responses to handlers.SearchMediaItemsResponse
- Add library creation for each test using CreateLibrary() helper
- Implement 25+ comprehensive test cases covering:
  - Filtering by status, genre, language, collection, has_cover, tags
  - Sorting by title, author, date_added, last_read
  - Pagination and limits
  - Edge cases (empty library_id, invalid sort, negative offset, zero limit)
  - Advanced filters (year range, rating, progress, text search, series, publisher, favorites, archived)

This replaces map-heavy approach with type-safe responses and follows
the project's structured handler pattern.
This commit is contained in:
2026-02-13 20:06:36 -05:00
parent 368c790c67
commit bbe8af5bea
2 changed files with 105 additions and 114 deletions
+11 -16
View File
@@ -1,6 +1,7 @@
package main
import (
"bookhoard/internal/handlers"
"bytes"
"encoding/json"
"net/http"
@@ -36,15 +37,12 @@ func TestAnalyticsReadingStats(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}
var result handlers.ReadingStatsResponse
json.NewDecoder(resp.Body).Decode(&result)
assert.Contains(t, result, "total_books_read")
assert.Contains(t, result, "total_pages_read")
assert.Contains(t, result, "total_reading_time_minutes")
assert.Contains(t, result, "average_session_time_minutes")
assert.Contains(t, result, "completion_rate")
assert.Contains(t, result, "daily_reading_minutes")
assert.GreaterOrEqual(t, result.TotalBooksRead, 0)
assert.GreaterOrEqual(t, result.TotalPagesRead, 0)
assert.GreaterOrEqual(t, result.TotalReadingTime, 0)
})
t.Run("GetReadingStats_WithCustomDateRange", func(t *testing.T) {
@@ -127,12 +125,11 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}
var result handlers.DeviceUsageResponse
json.NewDecoder(resp.Body).Decode(&result)
devices, ok := result["devices"].([]interface{})
assert.True(t, ok)
assert.Equal(t, 0, len(devices))
assert.NotNil(t, result.Devices)
assert.Equal(t, 0, len(result.Devices))
})
t.Run("GetDeviceUsage_WithAuth_WithDevices", func(t *testing.T) {
@@ -224,14 +221,12 @@ func TestAnalyticsPopularBooks(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
var result map[string]interface{}
var result handlers.PopularBooksResponse
json.NewDecoder(resp.Body).Decode(&result)
assert.Contains(t, result, "books")
books := result["books"].([]interface{})
assert.NotNil(t, books)
assert.NotNil(t, result.Books)
// Default limit is 10, but may be fewer if no reading history
assert.True(t, len(books) <= 10)
assert.True(t, len(result.Books) <= 10)
})
t.Run("GetPopularBooks_WithCustomLimit", func(t *testing.T) {