package testserver import ( "context" "fmt" "net/http" "time" "DanceLessonsCoach/pkg/config" "DanceLessonsCoach/pkg/server" "github.com/rs/zerolog/log" ) type Server struct { httpServer *http.Server port int baseURL string } func NewServer() *Server { return &Server{ port: 9191, } } func (s *Server) Start() error { s.baseURL = fmt.Sprintf("http://localhost:%d", s.port) // Create real server instance from pkg/server cfg := createTestConfig(s.port) realServer := server.NewServer(cfg, context.Background()) // Start HTTP server in same process s.httpServer = &http.Server{ Addr: fmt.Sprintf(":%d", s.port), Handler: realServer.Router(), } go func() { if err := s.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { if err != http.ErrServerClosed { log.Error().Err(err).Msg("Test server failed") } } }() // Wait for server to be ready return s.waitForServerReady() } func (s *Server) waitForServerReady() error { maxAttempts := 30 attempt := 0 for attempt < maxAttempts { resp, err := http.Get(fmt.Sprintf("%s/api/ready", s.baseURL)) if err == nil && resp.StatusCode == http.StatusOK { resp.Body.Close() return nil } if resp != nil { resp.Body.Close() } attempt++ time.Sleep(100 * time.Millisecond) } return fmt.Errorf("server did not become ready after %d attempts", maxAttempts) } func (s *Server) Stop() error { if s.httpServer == nil { return nil } // Shutdown HTTP server gracefully ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() return s.httpServer.Shutdown(ctx) } func (s *Server) GetBaseURL() string { return s.baseURL } func createTestConfig(port int) *config.Config { return &config.Config{ Server: config.ServerConfig{ Host: "localhost", Port: port, }, Shutdown: config.ShutdownConfig{ Timeout: 5 * time.Second, }, Logging: config.LoggingConfig{ JSON: false, Level: "trace", }, Telemetry: config.TelemetryConfig{ Enabled: false, }, API: config.APIConfig{ V2Enabled: true, // Enable v2 for testing }, } }