test: add comprehensive tests for notes and highlights

- Add complete test suite for media notes API with validation
- Add complete test suite for media highlights API with color validation
- Add backward compatibility tests for ebook endpoints
- Test authentication scenarios (unauthorized access)
- Test request validation and error handling
- Fix existing test import issues and syntax errors
- Add test cases for highlight-note associations
This commit is contained in:
2026-01-28 15:43:30 -05:00
parent 78851a940a
commit 0a457e02a2
3 changed files with 388 additions and 47 deletions
+46 -45
View File
@@ -7,6 +7,9 @@ import (
"net/http/httptest"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestAuthMiddleware verifies JWT middleware works correctly
@@ -15,7 +18,7 @@ func TestAuthMiddleware(t *testing.T) {
t.Run("Missing JWT", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/libraries/visible", nil)
rr := httptest.NewRecorder()
// Simulate auth middleware
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
@@ -24,7 +27,7 @@ func TestAuthMiddleware(t *testing.T) {
w.Write([]byte(`{"message":"missing or malformed jwt"}`))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message":"valid token"}`))
})
@@ -40,7 +43,7 @@ func TestAuthMiddleware(t *testing.T) {
req := httptest.NewRequest("GET", "/api/libraries/visible", nil)
req.Header.Set("Authorization", "invalid-token")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
@@ -48,7 +51,7 @@ func TestAuthMiddleware(t *testing.T) {
w.Write([]byte(`{"message":"missing or malformed jwt"}`))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message":"valid token"}`))
})
@@ -64,7 +67,7 @@ func TestAuthMiddleware(t *testing.T) {
req := httptest.NewRequest("GET", "/api/libraries/visible", nil)
req.Header.Set("Authorization", "Bearer valid-token")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
@@ -72,7 +75,7 @@ func TestAuthMiddleware(t *testing.T) {
w.Write([]byte(`{"message":"missing or malformed jwt"}`))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message":"valid token"}`))
})
@@ -104,7 +107,7 @@ func TestLibraryCreationUnauthorized(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// Simulate missing user context (like non-authenticated)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Simulate missing user context (like non-authenticated)
@@ -138,7 +141,7 @@ func TestLibraryCreationWithValidAdmin(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Simulate admin user context
if r.Header.Get("X-User-Role") != "admin" {
@@ -163,32 +166,32 @@ func TestLibraryTypesResponse(t *testing.T) {
require.NoError(t, err)
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
response := []map[string]interface{}{
{
"id": "test-id-1",
"name": "ebooks",
"description": "Ebook files including EPUB, PDF, MOBI, etc.",
"id": "test-id-1",
"name": "ebooks",
"description": "Ebook files including EPUB, PDF, MOBI, etc.",
"allowed_extensions": []string{".epub", ".pdf", ".mobi", ".azw", ".azw3", ".txt", ".rtf", ".doc", ".docx", ".lit", ".fb2", ".pdb"},
},
{
"id": "test-id-2",
"name": "comics",
"description": "Comic book archives and image formats",
"id": "test-id-2",
"name": "comics",
"description": "Comic book archives and image formats",
"allowed_extensions": []string{".cbz", ".cbr", ".cb7", ".cbt", ".pdf"},
},
{
"id": "test-id-3",
"name": "manga",
"description": "Manga files including archives and image folders",
"id": "test-id-3",
"name": "manga",
"description": "Manga files including archives and image folders",
"allowed_extensions": []string{".cbz", ".cbr", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"},
},
}
jsonData, _ := json.Marshal(response)
w.Write(jsonData)
})
@@ -208,26 +211,26 @@ func TestUserVisibleLibraries(t *testing.T) {
req.Header.Set("Authorization", "Bearer fake-token")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
response := []map[string]interface{}{
{
"id": "lib-1",
"name": "User Library 1",
"type_name": "ebooks",
"id": "lib-1",
"name": "User Library 1",
"type_name": "ebooks",
"is_visible": true,
},
{
"id": "lib-2",
"name": "Hidden Admin Library",
"type_name": "comics",
"id": "lib-2",
"name": "Hidden Admin Library",
"type_name": "comics",
"is_visible": false,
},
}
jsonData, _ := json.Marshal(response)
w.Write(jsonData)
})
@@ -237,9 +240,7 @@ func TestUserVisibleLibraries(t *testing.T) {
assert.Equal(t, http.StatusOK, rr.Code)
assert.Contains(t, rr.Body.String(), "User Library 1")
assert.Contains(t, rr.Body.String(), "ebooks")
assert.Contains(t, // Should not contain hidden library
!strings.Contains(rr.Body.String(), "Hidden Admin Library")
)
assert.False(t, strings.Contains(rr.Body.String(), "Hidden Admin Library")) // Should not contain hidden library
}
// TestMediaItemsList verifies media items endpoint with library filtering
@@ -249,20 +250,20 @@ func TestMediaItemsList(t *testing.T) {
req.Header.Set("Authorization", "Bearer fake-token")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
response := []map[string]interface{}{
{
"id": "media-1",
"title": "Test Book 1",
"library_name": "User Library 1",
"id": "media-1",
"title": "Test Book 1",
"library_name": "User Library 1",
"library_type_name": "ebooks",
},
}
jsonData, _ := json.Marshal(response)
w.Write(jsonData)
})
@@ -315,7 +316,7 @@ func TestJSONValidation(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Simulate successful creation for valid cases
if tc.expectedStatus == http.StatusCreated {
@@ -341,22 +342,22 @@ func TestJSONValidation(t *testing.T) {
func TestErrorHandling(t *testing.T) {
testCases := []struct {
name string
endpoint string
endpoint string
expectedStatus int
}{
{
name: "Missing library ID",
endpoint: "/api/libraries/nonexistent-id",
endpoint: "/api/libraries/nonexistent-id",
expectedStatus: http.StatusBadRequest,
},
{
name: "Invalid UUID",
endpoint: "/api/libraries/invalid-uuid",
endpoint: "/api/libraries/invalid-uuid",
expectedStatus: http.StatusBadRequest,
},
{
name: "Nonexistent user library",
endpoint: "/api/libraries/visible?user_id=nonexistent-user",
endpoint: "/api/libraries/visible?user_id=nonexistent-user",
expectedStatus: http.StatusUnauthorized,
},
}
@@ -367,7 +368,7 @@ func TestErrorHandling(t *testing.T) {
require.NoError(t, err)
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(tc.expectedStatus)
@@ -379,4 +380,4 @@ func TestErrorHandling(t *testing.T) {
assert.Equal(t, tc.expectedStatus, rr.Code)
})
}
}
}