test: add comprehensive media-item ISBN validation tests
New test file with 5 test suites: - TestMediaItemISBNNormalization (8 test cases) - TestMediaItemISBNEdgeCases (3 test cases) - TestMediaItemsPagination (5 test cases) - TestMediaItemLibraryRequirement (2 test cases) - TestUpdateMediaItemISBN (1 test case) Features: - Tests use /api/media-items endpoint (not deprecated /api/ebooks) - Real API calls (not mock handlers) - Comprehensive ISBN-10/ISBN-13 normalization coverage - Pagination validation with limit/offset edge cases - Library requirement validation This replaces the functionality lost from isbn_and_library_test.go with modern, working tests using current API endpoints. Phase 3: Test Suite Cleanup - Replacement Tests
This commit is contained in:
@@ -0,0 +1,445 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// createTestLibrary creates a test library and returns its ID
|
||||
func createTestLibrary(t *testing.T, ts *httptest.Server, token, name string) string {
|
||||
t.Helper()
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"name": name,
|
||||
"description": "Test library for ISBN tests",
|
||||
"type": "ebooks",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/libraries", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
require.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&result)
|
||||
|
||||
return result["id"].(string)
|
||||
}
|
||||
|
||||
// TestMediaItemISBNNormalization tests ISBN normalization with media-items endpoint
|
||||
func TestMediaItemISBNNormalization(t *testing.T) {
|
||||
ts, db, _, _ := setupTestServer(t)
|
||||
defer ts.Close()
|
||||
|
||||
// Create an ebook library first
|
||||
token := loginTestUser(t, ts, db)
|
||||
libID := createTestLibrary(t, ts, token, "test-isbn-lib")
|
||||
|
||||
// Test ISBN normalization cases
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ISBN-13 with hyphens (978-0-12345-678-9)",
|
||||
input: "978-0-12345-678-9",
|
||||
expected: "9780123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-13 with single hyphen (978-0123456789)",
|
||||
input: "978-0123456789",
|
||||
expected: "9780123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-13 without hyphens",
|
||||
input: "9780123456789",
|
||||
expected: "9780123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-13 with spaces",
|
||||
input: "978 0123456789",
|
||||
expected: "9780123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-13 with mixed hyphens and spaces",
|
||||
input: "978-0 1234-56789",
|
||||
expected: "9780123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-10 with hyphens",
|
||||
input: "0-12345-678-9",
|
||||
expected: "0123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-10 without hyphens",
|
||||
input: "0123456789",
|
||||
expected: "0123456789",
|
||||
},
|
||||
{
|
||||
name: "ISBN-10 with X",
|
||||
input: "0-12345-678-X",
|
||||
expected: "012345678X",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
payload := map[string]interface{}{
|
||||
"title": fmt.Sprintf("Test Book %s", tc.name),
|
||||
"isbn": tc.input,
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var response map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
// Verify ISBN was normalized
|
||||
assert.Equal(t, tc.expected, response["isbn"])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestMediaItemISBNEdgeCases tests ISBN edge cases
|
||||
func TestMediaItemISBNEdgeCases(t *testing.T) {
|
||||
ts, db, _, _ := setupTestServer(t)
|
||||
defer ts.Close()
|
||||
|
||||
token := loginTestUser(t, ts, db)
|
||||
libID := createTestLibrary(t, ts, token, "test-isbn-edge-lib")
|
||||
|
||||
t.Run("Empty ISBN should be accepted", func(t *testing.T) {
|
||||
payload := map[string]interface{}{
|
||||
"title": "Book without ISBN",
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("ISBN with multiple hyphens", func(t *testing.T) {
|
||||
payload := map[string]interface{}{
|
||||
"title": "Multi-Hyphen ISBN",
|
||||
"isbn": "978-0-123-45678-9",
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var response map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
assert.Equal(t, "9780123456789", response["isbn"])
|
||||
})
|
||||
|
||||
t.Run("ISBN with trailing hyphen", func(t *testing.T) {
|
||||
payload := map[string]interface{}{
|
||||
"title": "Trailing Hyphen ISBN",
|
||||
"isbn": "9780123456789-",
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var response map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
assert.Equal(t, "9780123456789", response["isbn"])
|
||||
})
|
||||
}
|
||||
|
||||
// TestMediaItemsPagination tests pagination with media-items endpoint
|
||||
func TestMediaItemsPagination(t *testing.T) {
|
||||
ts, db, _, _ := setupTestServer(t)
|
||||
defer ts.Close()
|
||||
|
||||
token := loginTestUser(t, ts, db)
|
||||
libID := createTestLibrary(t, ts, token, "test-pagination-lib")
|
||||
|
||||
// Create some test media items
|
||||
for i := 1; i <= 5; i++ {
|
||||
payload := map[string]interface{}{
|
||||
"title": fmt.Sprintf("Book %d", i),
|
||||
"isbn": fmt.Sprintf("97801234567%d", i),
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
t.Run("Valid pagination parameters", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", ts.URL+"/api/media-items?library_id="+libID+"&limit=2&offset=0", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var response []map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
// Should get 2 items
|
||||
assert.Equal(t, 2, len(response))
|
||||
})
|
||||
|
||||
t.Run("Pagination with offset", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", ts.URL+"/api/media-items?library_id="+libID+"&limit=2&offset=2", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var response []map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
// Should get 2 items starting from offset 2
|
||||
assert.Equal(t, 2, len(response))
|
||||
})
|
||||
|
||||
t.Run("Negative limit should fail", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", ts.URL+"/api/media-items?library_id="+libID+"&limit=-10&offset=0", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return 400 Bad Request or handle it gracefully
|
||||
assert.NotEqual(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Negative offset should fail", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", ts.URL+"/api/media-items?library_id="+libID+"&limit=10&offset=-5", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return 400 Bad Request or handle it gracefully
|
||||
assert.NotEqual(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Limit exceeds maximum", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", ts.URL+"/api/media-items?library_id="+libID+"&limit=10000&offset=0", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should be capped at maximum or return error
|
||||
// The application uses maxPaginationLimit = 1000
|
||||
assert.NotEqual(t, http.StatusInternalServerError, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
// TestMediaItemLibraryRequirement tests that media items require a library
|
||||
func TestMediaItemLibraryRequirement(t *testing.T) {
|
||||
ts, db, _, _ := setupTestServer(t)
|
||||
defer ts.Close()
|
||||
|
||||
token := loginTestUser(t, ts, db)
|
||||
|
||||
t.Run("Create media-item without library should fail gracefully", func(t *testing.T) {
|
||||
payload := map[string]interface{}{
|
||||
"title": "Orphan Book",
|
||||
"isbn": "9780123456789",
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should fail - library_id is required
|
||||
assert.NotEqual(t, http.StatusCreated, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Create media-item with existing library should succeed", func(t *testing.T) {
|
||||
libID := createTestLibrary(t, ts, token, "test-req-lib")
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"title": "Valid Book",
|
||||
"isbn": "978-0123456789",
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var response map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
// Verify ISBN was normalized
|
||||
assert.Equal(t, "9780123456789", response["isbn"])
|
||||
assert.Equal(t, libID, response["library_id"])
|
||||
})
|
||||
}
|
||||
|
||||
// TestUpdateMediaItemISBN tests updating media-item ISBN
|
||||
func TestUpdateMediaItemISBN(t *testing.T) {
|
||||
ts, db, _, _ := setupTestServer(t)
|
||||
defer ts.Close()
|
||||
|
||||
token := loginTestUser(t, ts, db)
|
||||
libID := createTestLibrary(t, ts, token, "test-update-lib")
|
||||
|
||||
// First create a media item
|
||||
createPayload := map[string]interface{}{
|
||||
"title": "Original Title",
|
||||
"isbn": "9780123456789",
|
||||
"library_id": libID,
|
||||
"file_path": "/test/path.epub",
|
||||
"file_size": 1024,
|
||||
"mime_type": "application/epub+zip",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(createPayload)
|
||||
req, _ := http.NewRequest("POST", ts.URL+"/api/media-items", bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
var createResponse map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&createResponse)
|
||||
resp.Body.Close()
|
||||
|
||||
mediaItemID := createResponse["id"].(string)
|
||||
|
||||
// Now update with new ISBN
|
||||
t.Run("Update with normalized ISBN", func(t *testing.T) {
|
||||
updatePayload := map[string]interface{}{
|
||||
"title": "Updated Title",
|
||||
"isbn": "978-987654321-0",
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(updatePayload)
|
||||
req, _ := http.NewRequest("PUT", ts.URL+"/api/media-items/"+mediaItemID, bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var response map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&response)
|
||||
|
||||
// Verify ISBN was normalized
|
||||
assert.Equal(t, "9789876543210", response["isbn"])
|
||||
assert.Equal(t, "Updated Title", response["title"])
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user