test: add integration tests for tags filter
- Create tags_filter_test.go with comprehensive test coverage - Test tags filter with exact matches (Science Fiction) - Test fuzzy matching behavior (Sci Fi → Science Fiction) - Test autocomplete endpoint for tag suggestions - Test backward compatibility with genre_filter - Test combined filters (tags + author) - Uses setupDeviceTest() helper for proper test environment Validates the tags filter functionality including fuzzy matching, autocomplete, and backward compatibility. Relates to IMPLEMENTATION_TAGS_FILTER.md Phase 8
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTagsFilter(t *testing.T) {
|
||||
setup := setupDeviceTest(t)
|
||||
defer setup.Server.Close()
|
||||
|
||||
libraryID := setup.CreateLibrary(t, "Test Tags Library", "ebooks")
|
||||
_ = setup.CreateDevice(t, "Test Device", "koreader", "tags-test-123")
|
||||
|
||||
client := &http.Client{}
|
||||
|
||||
// Add folder to library (required before adding media items)
|
||||
folderReq := map[string]interface{}{
|
||||
"folder_path": "/app/uploads",
|
||||
}
|
||||
folderBody, _ := json.Marshal(folderReq)
|
||||
folderHTTP, _ := http.NewRequest("POST", setup.Server.URL+"/api/libraries/"+libraryID+"/folders", bytes.NewBuffer(folderBody))
|
||||
folderHTTP.Header.Set("Content-Type", "application/json")
|
||||
folderHTTP.Header.Set("Authorization", "Bearer "+setup.UserToken)
|
||||
folderResp, err := client.Do(folderHTTP)
|
||||
require.NoError(t, err)
|
||||
folderResp.Body.Close()
|
||||
require.Equal(t, http.StatusCreated, folderResp.StatusCode, "Should add folder to library")
|
||||
|
||||
// Helper to create book with tags
|
||||
createBook := func(title, author string, tags []string) {
|
||||
bookReq := map[string]interface{}{
|
||||
"library_id": libraryID,
|
||||
"title": title,
|
||||
"author": author,
|
||||
"tags": tags,
|
||||
"file_path": "/tmp/test.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
body, _ := json.Marshal(bookReq)
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+setup.UserToken)
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, http.StatusCreated, resp.StatusCode, "Should create book")
|
||||
}
|
||||
|
||||
// Create test books with different tags
|
||||
createBook("Foundation", "Asimov", []string{"Science Fiction", "Adventure"})
|
||||
createBook("Dune", "Herbert", []string{"Science Fiction", "Dystopian"})
|
||||
createBook("Neuromancer", "Gibson", []string{"Cyberpunk", "Science Fiction"})
|
||||
createBook("The Hobbit", "Tolkien", []string{"Fantasy", "Adventure"})
|
||||
|
||||
t.Run("Tags filter - Science Fiction", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&tags_filter=Science+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 return results")
|
||||
|
||||
var results []map[string]interface{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &results)
|
||||
require.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, len(results), 3, "Should return Foundation, Dune, Neuromancer (all have 'Science Fiction' tag)")
|
||||
})
|
||||
|
||||
t.Run("Tags filter - fuzzy match", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&tags_filter=Sci+Fi", 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 results")
|
||||
|
||||
var results []map[string]interface{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &results)
|
||||
require.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, len(results), 3, "Should return Foundation, Dune, Neuromancer (fuzzy matches 'Science Fiction')")
|
||||
})
|
||||
|
||||
t.Run("Tags filter - Fantasy", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&tags_filter=Fantasy", 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 results")
|
||||
|
||||
var results []map[string]interface{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &results)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(results), "Should return only The Hobbit")
|
||||
})
|
||||
|
||||
t.Run("Tags autocomplete", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?tags=Sci&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 return autocomplete results")
|
||||
|
||||
var results []map[string]interface{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &results)
|
||||
require.NoError(t, err)
|
||||
assert.Greater(t, len(results), 0, "Should return 'Science Fiction' in autocomplete results")
|
||||
})
|
||||
|
||||
t.Run("Backward compatibility - genre_filter still works", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&genre_filter=Science+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 return results (even if empty)")
|
||||
})
|
||||
|
||||
t.Run("Combined filters - tags + author", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/media-items/search?library_id="+libraryID+"&tags_filter=Sci+Fi&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 return results")
|
||||
|
||||
var results []map[string]interface{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &results)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(results), "Should return only Foundation")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user