Files
bookhoard/cmd/server/tests/fsnotify_integration_test.go
T
john-okeefe 4d8e3e5358 test: improve test infrastructure and fix integration tests
- Add folder to library before scanning in fsnotify integration test
- Update API endpoint paths from /items to /media-items
- Refactor test server setup to support WebSocket hijacking
- Add JobsHandler to test server configuration
- Implement proper job status polling instead of fixed delays
- Consolidate addFolderToLibrary helper into test_helpers.go
- Remove duplicate helper function from media_item_isbn_test.go
- Add error logging for search test failures
- Improve test robustness with better nil handling and type assertions
- Update worker test to use EnqueueJob and poll for completion
- Add global worker instance reset in test cleanup
- Fix media_scanner_test to initialize folders before testing
2026-03-06 01:52:19 -05:00

117 lines
4.1 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFSNotify_BulkFileDetection(t *testing.T) {
setup := setupTestServer(t)
defer setup.Close()
t.Run("Detects multiple files added simultaneously", func(t *testing.T) {
token := setup.Token
tmpDir := t.TempDir()
// Create library
createLibReq := map[string]interface{}{
"name": "bulk-test-library",
"type": "ebooks",
}
libBody, _ := json.Marshal(createLibReq)
libReq, _ := http.NewRequest("POST", setup.Server.URL+"/api/libraries", bytes.NewBuffer(libBody))
libReq.Header.Set("Content-Type", "application/json")
libReq.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
libResp, err := client.Do(libReq)
require.NoError(t, err)
defer libResp.Body.Close()
require.Equal(t, http.StatusCreated, libResp.StatusCode)
var libResult map[string]interface{}
json.NewDecoder(libResp.Body).Decode(&libResult)
libraryID := libResult["id"].(string)
// Add folder to library
folderURL := fmt.Sprintf("%s/api/libraries/%s/folders", setup.Server.URL, libraryID)
folderReq := map[string]interface{}{
"folder_path": tmpDir,
}
folderBody, _ := json.Marshal(folderReq)
folderHTTPReq, _ := http.NewRequest("POST", folderURL, bytes.NewBuffer(folderBody))
folderHTTPReq.Header.Set("Content-Type", "application/json")
folderHTTPReq.Header.Set("Authorization", "Bearer "+token)
folderResp, err := client.Do(folderHTTPReq)
require.NoError(t, err)
defer folderResp.Body.Close()
require.Equal(t, http.StatusCreated, folderResp.StatusCode, "Folder should be added to library")
// Create 20 test files simultaneously
for i := 0; i < 20; i++ {
fileName := filepath.Join(tmpDir, fmt.Sprintf("book%d.epub", i))
err := os.WriteFile(fileName, []byte(fmt.Sprintf("test %d", i)), 0644)
require.NoError(t, err)
}
// Trigger library scan
scanURL := fmt.Sprintf("%s/api/libraries/%s/scan", setup.Server.URL, libraryID)
scanHTTPReq, _ := http.NewRequest("POST", scanURL, nil)
scanHTTPReq.Header.Set("Authorization", "Bearer "+token)
scanResp, err := client.Do(scanHTTPReq)
require.NoError(t, err)
defer scanResp.Body.Close()
require.Equal(t, http.StatusAccepted, scanResp.StatusCode, "Scan should be accepted")
var scanResponse map[string]interface{}
json.NewDecoder(scanResp.Body).Decode(&scanResponse)
jobID, ok := scanResponse["job_id"].(string)
require.True(t, ok, "job_id should be string")
require.NotEmpty(t, jobID, "job_id should not be empty")
// Wait for scan job to complete
time.Sleep(3 * time.Second)
for i := 0; i < 30; i++ {
if i > 0 {
time.Sleep(1 * time.Second)
}
statusURL := fmt.Sprintf("%s/api/scanner/status/%s", setup.Server.URL, jobID)
statusReq, _ := http.NewRequest("GET", statusURL, nil)
statusReq.Header.Set("Authorization", "Bearer "+token)
statusResp, err := client.Do(statusReq)
require.NoError(t, err)
if statusResp.StatusCode == http.StatusNotFound {
statusResp.Body.Close()
break // Job completed
}
var status map[string]interface{}
json.NewDecoder(statusResp.Body).Decode(&status)
statusResp.Body.Close()
if status["status"] == "completed" || status["status"] == "failed" {
statusResp.Body.Close()
break
}
}
// Check items
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/libraries/"+libraryID+"/media-items", nil)
req.Header.Set("Authorization", "Bearer "+token)
itemsResp, err := client.Do(req)
require.NoError(t, err)
defer itemsResp.Body.Close()
var itemsResult map[string]interface{}
json.NewDecoder(itemsResp.Body).Decode(&itemsResult)
items, ok := itemsResult["data"].([]interface{})
if !ok || items == nil {
items = []interface{}{} // Handle nil or wrong type
}
assert.GreaterOrEqual(t, len(items), 20, "Should detect all 20 files")
// Cleanup
deleteReq, _ := http.NewRequest("DELETE", setup.Server.URL+"/api/libraries/"+libraryID, nil)
deleteReq.Header.Set("Authorization", "Bearer "+token)
client.Do(deleteReq)
})
}