package handlers_test import ( "bytes" "context" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "erp-mvp/core-service/internal/api/handlers" "erp-mvp/core-service/internal/models" ) // MockLocationService мок для LocationService type MockLocationService struct { mock.Mock } func (m *MockLocationService) GetLocations(ctx context.Context, orgID uuid.UUID) ([]*models.StorageLocation, error) { args := m.Called(ctx, orgID) return args.Get(0).([]*models.StorageLocation), args.Error(1) } func (m *MockLocationService) CreateLocation(ctx context.Context, orgID uuid.UUID, req *models.CreateLocationRequest) (*models.StorageLocation, error) { args := m.Called(ctx, orgID, req) return args.Get(0).(*models.StorageLocation), args.Error(1) } func (m *MockLocationService) GetLocation(ctx context.Context, orgID uuid.UUID, locationID uuid.UUID) (*models.StorageLocation, error) { args := m.Called(ctx, orgID, locationID) return args.Get(0).(*models.StorageLocation), args.Error(1) } func (m *MockLocationService) UpdateLocation(ctx context.Context, orgID uuid.UUID, locationID uuid.UUID, req *models.CreateLocationRequest) (*models.StorageLocation, error) { args := m.Called(ctx, orgID, locationID, req) return args.Get(0).(*models.StorageLocation), args.Error(1) } func (m *MockLocationService) DeleteLocation(ctx context.Context, orgID uuid.UUID, locationID uuid.UUID) error { args := m.Called(ctx, orgID, locationID) return args.Error(0) } func (m *MockLocationService) GetChildren(ctx context.Context, orgID uuid.UUID, parentID uuid.UUID) ([]*models.StorageLocation, error) { args := m.Called(ctx, orgID, parentID) return args.Get(0).([]*models.StorageLocation), args.Error(1) } // TestNewLocationHandler тестирует создание LocationHandler func TestNewLocationHandler(t *testing.T) { // Arrange mockService := &MockLocationService{} // Act handler := handlers.NewLocationHandler(mockService) // Assert assert.NotNil(t, handler) } // TestLocationHandler_GetLocations_Success тестирует успешное получение локаций func TestLocationHandler_GetLocations_Success(t *testing.T) { // Arrange gin.SetMode(gin.TestMode) mockLocationService := &MockLocationService{} handler := handlers.NewLocationHandler(mockLocationService) orgID := uuid.New() expectedLocations := []*models.StorageLocation{ { ID: uuid.New(), OrganizationID: orgID, Name: "Warehouse A", Address: "123 Main St", Type: "warehouse", }, { ID: uuid.New(), OrganizationID: orgID, Name: "Shelf 1", Address: "Warehouse A, Section 1", Type: "shelf", }, } mockLocationService.On("GetLocations", mock.Anything, orgID).Return(expectedLocations, nil) router := gin.New() router.GET("/locations", func(c *gin.Context) { // Устанавливаем claims в контекст c.Set("user_id", uuid.New()) c.Set("organization_id", orgID) c.Set("email", "test@example.com") c.Set("role", "admin") handler.GetLocations(c) }) // Act w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/locations", nil) router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) var response []*models.StorageLocation err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Len(t, response, 2) assert.Equal(t, "Warehouse A", response[0].Name) assert.Equal(t, "Shelf 1", response[1].Name) mockLocationService.AssertExpectations(t) } // TestLocationHandler_CreateLocation_Success тестирует успешное создание локации func TestLocationHandler_CreateLocation_Success(t *testing.T) { // Arrange gin.SetMode(gin.TestMode) mockLocationService := &MockLocationService{} handler := handlers.NewLocationHandler(mockLocationService) orgID := uuid.New() locationID := uuid.New() createReq := &models.CreateLocationRequest{ Name: "New Warehouse", Address: "456 Oak St", Type: "warehouse", Coordinates: models.JSON{"lat": 55.7558, "lng": 37.6176}, } expectedLocation := &models.StorageLocation{ ID: locationID, OrganizationID: orgID, Name: "New Warehouse", Address: "456 Oak St", Type: "warehouse", Coordinates: models.JSON{"lat": 55.7558, "lng": 37.6176}, } mockLocationService.On("CreateLocation", mock.Anything, orgID, createReq).Return(expectedLocation, nil) router := gin.New() router.POST("/locations", func(c *gin.Context) { // Устанавливаем claims в контекст c.Set("user_id", uuid.New()) c.Set("organization_id", orgID) c.Set("email", "test@example.com") c.Set("role", "admin") handler.CreateLocation(c) }) reqBody, _ := json.Marshal(createReq) // Act w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/locations", bytes.NewBuffer(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusCreated, w.Code) var response models.StorageLocation err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "New Warehouse", response.Name) assert.Equal(t, "warehouse", response.Type) mockLocationService.AssertExpectations(t) } // TestLocationHandler_CreateLocation_ValidationError тестирует ошибку валидации при создании локации func TestLocationHandler_CreateLocation_ValidationError(t *testing.T) { // Arrange gin.SetMode(gin.TestMode) mockLocationService := &MockLocationService{} handler := handlers.NewLocationHandler(mockLocationService) orgID := uuid.New() // Невалидный запрос (пустое имя) invalidReq := map[string]interface{}{ "name": "", // Пустое имя "address": "456 Oak St", "type": "warehouse", } router := gin.New() router.POST("/locations", func(c *gin.Context) { // Устанавливаем claims в контекст c.Set("user_id", uuid.New()) c.Set("organization_id", orgID) c.Set("email", "test@example.com") c.Set("role", "admin") handler.CreateLocation(c) }) reqBody, _ := json.Marshal(invalidReq) // Act w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/locations", bytes.NewBuffer(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusBadRequest, w.Code) mockLocationService.AssertNotCalled(t, "CreateLocation") } // TestLocationHandler_GetLocation_Success тестирует успешное получение локации по ID func TestLocationHandler_GetLocation_Success(t *testing.T) { // Arrange gin.SetMode(gin.TestMode) mockLocationService := &MockLocationService{} handler := handlers.NewLocationHandler(mockLocationService) orgID := uuid.New() locationID := uuid.New() expectedLocation := &models.StorageLocation{ ID: locationID, OrganizationID: orgID, Name: "Test Warehouse", Address: "123 Test St", Type: "warehouse", } mockLocationService.On("GetLocation", mock.Anything, locationID, orgID).Return(expectedLocation, nil) router := gin.New() router.GET("/locations/:id", func(c *gin.Context) { // Устанавливаем claims в контекст c.Set("user_id", uuid.New()) c.Set("organization_id", orgID) c.Set("email", "test@example.com") c.Set("role", "admin") handler.GetLocation(c) }) // Act w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/locations/"+locationID.String(), nil) router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) var response models.StorageLocation err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "Test Warehouse", response.Name) assert.Equal(t, locationID, response.ID) mockLocationService.AssertExpectations(t) } // TestLocationHandler_GetChildren_Success тестирует успешное получение дочерних локаций func TestLocationHandler_GetChildren_Success(t *testing.T) { // Arrange gin.SetMode(gin.TestMode) mockLocationService := &MockLocationService{} handler := handlers.NewLocationHandler(mockLocationService) orgID := uuid.New() parentID := uuid.New() expectedChildren := []*models.StorageLocation{ { ID: uuid.New(), OrganizationID: orgID, ParentID: &parentID, Name: "Shelf 1", Address: "Warehouse A, Section 1", Type: "shelf", }, { ID: uuid.New(), OrganizationID: orgID, ParentID: &parentID, Name: "Shelf 2", Address: "Warehouse A, Section 2", Type: "shelf", }, } mockLocationService.On("GetChildren", mock.Anything, parentID, orgID).Return(expectedChildren, nil) router := gin.New() router.GET("/locations/:id/children", func(c *gin.Context) { // Устанавливаем claims в контекст c.Set("user_id", uuid.New()) c.Set("organization_id", orgID) c.Set("email", "test@example.com") c.Set("role", "admin") handler.GetChildren(c) }) // Act w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/locations/"+parentID.String()+"/children", nil) router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) var response []*models.StorageLocation err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Len(t, response, 2) assert.Equal(t, "Shelf 1", response[0].Name) assert.Equal(t, "Shelf 2", response[1].Name) mockLocationService.AssertExpectations(t) }