package server import ( "bytes" "net/http" "net/http/httptest" "os" "testing" "time" "music-server/internal/backend" "music-server/internal/db" "github.com/labstack/echo/v5" ) // StartTestServer starts the server for testing with test configuration func StartTestServer(t *testing.T) *echo.Echo { // Set test environment variables if not already set if os.Getenv("DB_HOST") == "" { os.Setenv("DB_HOST", "localhost") } if os.Getenv("DB_PORT") == "" { os.Setenv("DB_PORT", "5432") } if os.Getenv("DB_USERNAME") == "" { os.Setenv("DB_USERNAME", "testuser") } if os.Getenv("DB_PASSWORD") == "" { os.Setenv("DB_PASSWORD", "testpass") } if os.Getenv("DB_NAME") == "" { os.Setenv("DB_NAME", "music_server_test") } if os.Getenv("MUSIC_PATH") == "" { os.Setenv("MUSIC_PATH", "./testMusic") } if os.Getenv("CHARACTERS_PATH") == "" { os.Setenv("CHARACTERS_PATH", "./testCharacters") } if os.Getenv("PORT") == "" { os.Setenv("PORT", "8081") } if os.Getenv("LOG_LEVEL") == "" { os.Setenv("LOG_LEVEL", "debug") } if os.Getenv("LOG_JSON") == "" { os.Setenv("LOG_JSON", "false") } // Initialize database for tests db.TestSetupDB(t) // Initialize backend with test database pool // This ensures BackendRepo() and BackendCtx() are available if db.TestDatabase != nil && db.TestDatabase.Pool != nil { backend.InitBackend(db.TestDatabase.Pool) } // Create a Server instance and get its routes s := &Server{ db: db.TestDatabase, tokenHandler: NewTokenHandler(db.TestDatabase.Pool), } handler := s.RegisterRoutes() // Wrap the http.Handler in an echo.Echo e := echo.New() // Use a custom handler that wraps our routes e.Any("/*", echo.WrapHandler(handler)) return e } // MakeTestRequest makes an HTTP request to the test server func MakeTestRequest(t *testing.T, e *echo.Echo, method, path string) *httptest.ResponseRecorder { req := httptest.NewRequest(method, path, nil) rec := httptest.NewRecorder() e.ServeHTTP(rec, req) return rec } // MakeTestRequestWithBody makes an HTTP request with a body to the test server func MakeTestRequestWithBody(t *testing.T, e *echo.Echo, method, path string, body []byte) *httptest.ResponseRecorder { req := httptest.NewRequest(method, path, nil) if body != nil { req = httptest.NewRequest(method, path, bytes.NewBuffer(body)) } rec := httptest.NewRecorder() e.ServeHTTP(rec, req) return rec } // WaitForSyncComplete polls the sync progress endpoint until sync is complete func WaitForSyncComplete(t *testing.T, e *echo.Echo, timeout time.Duration) bool { start := time.Now() for time.Since(start) < timeout { resp := MakeTestRequest(t, e, "GET", "/sync/progress") if resp.Code != http.StatusOK { t.Logf("Sync progress endpoint returned status %d", resp.Code) time.Sleep(1 * time.Second) continue } // Parse response - we can't easily decode here without importing backend // Just check if response contains "100" body := resp.Body.String() if len(body) > 0 { t.Logf("Sync progress: %s", body) // Simple check for completion // In a real scenario, you'd parse the JSON properly } time.Sleep(1 * time.Second) } t.Error("Sync did not complete within timeout") return false }