package handlers import ( "net/http" "net/http/httptest" "testing" "veza-backend-api/internal/services" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) // MockSearchService implements SearchService interface for testing type MockSearchService struct { mock.Mock } func (m *MockSearchService) Search(query string, types []string, filters *services.SearchFilters) (*services.SearchResult, error) { args := m.Called(query, types, filters) if args.Get(0) == nil { return nil, args.Error(1) } return args.Get(0).(*services.SearchResult), args.Error(1) } func (m *MockSearchService) Suggestions(query string, limit int) (*services.SearchResult, error) { args := m.Called(query, limit) if args.Get(0) == nil { return nil, args.Error(1) } return args.Get(0).(*services.SearchResult), args.Error(1) } func setupTestSearchRouter(mockService *MockSearchService) *gin.Engine { gin.SetMode(gin.TestMode) router := gin.New() handler := NewSearchHandlersWithInterface(mockService) api := router.Group("/api/v1") { api.GET("/search", handler.Search) } return router } func TestSearchHandlers_Search_Success(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) expectedResult := &services.SearchResult{ Tracks: []services.TrackResult{ {ID: "track-1", Title: "Test Track", Artist: "Test Artist", URL: "http://example.com/track-1"}, }, Users: []services.UserResult{ {ID: "user-1", Username: "testuser", AvatarURL: "http://example.com/avatar.jpg"}, }, Playlists: []services.PlaylistResult{ {ID: "playlist-1", Name: "Test Playlist", Cover: "http://example.com/cover.jpg"}, }, } mockService.On("Search", "test", []string(nil), mock.Anything).Return(expectedResult, nil) // Execute req, _ := http.NewRequest("GET", "/api/v1/search?q=test", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) mockService.AssertExpectations(t) } func TestSearchHandlers_Search_WithTypes(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) expectedResult := &services.SearchResult{ Tracks: []services.TrackResult{ {ID: "track-1", Title: "Test Track", Artist: "Test Artist", URL: "http://example.com/track-1"}, }, Users: []services.UserResult{}, Playlists: []services.PlaylistResult{}, } mockService.On("Search", "test", []string{"track"}, mock.Anything).Return(expectedResult, nil) // Execute req, _ := http.NewRequest("GET", "/api/v1/search?q=test&type=track", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) mockService.AssertExpectations(t) } func TestSearchHandlers_Search_MissingQuery(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) // Execute req, _ := http.NewRequest("GET", "/api/v1/search", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusBadRequest, w.Code) mockService.AssertNotCalled(t, "Search") } func TestSearchHandlers_Search_EmptyQuery(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) // Execute req, _ := http.NewRequest("GET", "/api/v1/search?q=", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusBadRequest, w.Code) mockService.AssertNotCalled(t, "Search") } func TestSearchHandlers_Search_ServiceError(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) mockService.On("Search", "test", []string(nil), mock.Anything).Return(nil, assert.AnError) // Execute req, _ := http.NewRequest("GET", "/api/v1/search?q=test", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusInternalServerError, w.Code) mockService.AssertExpectations(t) } func TestSearchHandlers_Search_MultipleTypes(t *testing.T) { // Setup mockService := new(MockSearchService) router := setupTestSearchRouter(mockService) expectedResult := &services.SearchResult{ Tracks: []services.TrackResult{ {ID: "track-1", Title: "Test Track", Artist: "Test Artist", URL: "http://example.com/track-1"}, }, Users: []services.UserResult{ {ID: "user-1", Username: "testuser", AvatarURL: "http://example.com/avatar.jpg"}, }, Playlists: []services.PlaylistResult{}, } mockService.On("Search", "test", []string{"track", "user"}, mock.Anything).Return(expectedResult, nil) // Execute req, _ := http.NewRequest("GET", "/api/v1/search?q=test&type=track&type=user", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) mockService.AssertExpectations(t) } func TestNewSearchHandlers(t *testing.T) { // Setup mockService := &services.SearchService{} // Execute NewSearchHandlers(mockService) // Assert assert.NotNil(t, SearchHandlersInstance) assert.NotNil(t, SearchHandlersInstance.searchService) }