package handler_test import ( "bytes" "context" "encoding/json" "net/http" "net/http/httptest" "github.com/gin-gonic/gin" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "gorm.io/gorm" "bugulma/backend/internal/domain" "bugulma/backend/internal/handler" "bugulma/backend/internal/repository" "bugulma/backend/internal/service" "bugulma/backend/internal/testutils" ) var _ = Describe("OrganizationHandler", func() { var ( orgHandler *handler.OrganizationHandler orgService *service.OrganizationService orgRepo domain.OrganizationRepository router *gin.Engine db *gorm.DB ) BeforeEach(func() { gin.SetMode(gin.TestMode) // Setup PostgreSQL test database using pgtestdb db = testutils.SetupTestDBForGinkgo(GinkgoT()) orgRepo = repository.NewOrganizationRepository(db) orgService = service.NewOrganizationService(orgRepo, nil) // No graph repo for tests resourceFlowRepo := repository.NewResourceFlowRepository(db) resourceFlowService := service.NewResourceFlowService(resourceFlowRepo, nil) orgHandler = handler.NewOrganizationHandler(orgService, nil, resourceFlowService) // No image service for tests router = gin.New() router.POST("/organizations", orgHandler.Create) router.GET("/organizations/:id", orgHandler.GetByID) router.GET("/organizations", orgHandler.GetAll) router.PUT("/organizations/:id", orgHandler.Update) router.DELETE("/organizations/:id", orgHandler.Delete) router.GET("/organizations/subtype/:subtype", orgHandler.GetBySubtype) router.GET("/organizations/sector/:sector", orgHandler.GetBySector) router.GET("/organizations/certification/:cert", orgHandler.GetByCertification) router.GET("/organizations/nearby", orgHandler.GetNearby) }) AfterEach(func() { // pgtestdb automatically cleans up the database after each test }) Describe("Create", func() { It("should create an organization", func() { reqBody := handler.CreateOrganizationRequest{ Name: "Test Org", Sector: "Manufacturing", Subtype: "commercial", Description: "Test Description", } body, _ := json.Marshal(reqBody) req, _ := http.NewRequest("POST", "/organizations", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusCreated)) var resp domain.Organization err := json.Unmarshal(w.Body.Bytes(), &resp) Expect(err).NotTo(HaveOccurred()) Expect(resp.Name).To(Equal("Test Org")) Expect(resp.ID).NotTo(BeEmpty()) }) It("should return 400 for invalid input", func() { reqBody := handler.CreateOrganizationRequest{ // Missing Name and Sector Description: "Test Description", } body, _ := json.Marshal(reqBody) req, _ := http.NewRequest("POST", "/organizations", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusBadRequest)) }) }) Describe("GetByID", func() { It("should return organization by ID", func() { // Create one first org := &domain.Organization{ ID: "org-1", Name: "Existing Org", } Expect(orgRepo.Create(context.TODO(), org)).To(Succeed()) req, _ := http.NewRequest("GET", "/organizations/org-1", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) var resp domain.Organization err := json.Unmarshal(w.Body.Bytes(), &resp) Expect(err).NotTo(HaveOccurred()) Expect(resp.Name).To(Equal("Existing Org")) }) It("should return 404 if not found", func() { req, _ := http.NewRequest("GET", "/organizations/non-existent", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusNotFound)) }) }) Describe("GetAll", func() { It("should return all organizations", func() { Expect(orgRepo.Create(context.TODO(), &domain.Organization{ID: "org-1", Name: "Org 1"})).To(Succeed()) Expect(orgRepo.Create(context.TODO(), &domain.Organization{ID: "org-2", Name: "Org 2"})).To(Succeed()) req, _ := http.NewRequest("GET", "/organizations", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) var resp []domain.Organization err := json.Unmarshal(w.Body.Bytes(), &resp) Expect(err).NotTo(HaveOccurred()) Expect(resp).To(HaveLen(2)) }) }) Describe("Delete", func() { It("should delete organization", func() { Expect(orgRepo.Create(context.TODO(), &domain.Organization{ID: "org-1", Name: "Org 1"})).To(Succeed()) req, _ := http.NewRequest("DELETE", "/organizations/org-1", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusNoContent)) // Verify it's gone _, err := orgRepo.GetByID(context.Background(), "org-1") Expect(err).To(HaveOccurred()) }) }) Describe("Update", func() { It("should update organization", func() { org := &domain.Organization{ ID: "org-1", Name: "Original Name", Sector: "Manufacturing", Subtype: domain.SubtypeCommercial, } Expect(orgRepo.Create(context.TODO(), org)).To(Succeed()) updateReq := map[string]interface{}{ "name": "Updated Name", "sector": "Technology", "subtype": "commercial", } jsonData, _ := json.Marshal(updateReq) req, _ := http.NewRequest("PUT", "/organizations/org-1", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) // Verify update updated, err := orgRepo.GetByID(context.Background(), "org-1") Expect(err).NotTo(HaveOccurred()) Expect(updated.Name).To(Equal("Updated Name")) Expect(updated.Sector).To(Equal("Technology")) }) }) Describe("GetBySubtype", func() { It("should get organizations by subtype", func() { org1 := &domain.Organization{ID: "org-1", Name: "Org 1", Subtype: domain.SubtypeCommercial} org2 := &domain.Organization{ID: "org-2", Name: "Org 2", Subtype: domain.SubtypeGovernment} Expect(orgRepo.Create(context.TODO(), org1)).To(Succeed()) Expect(orgRepo.Create(context.TODO(), org2)).To(Succeed()) req, _ := http.NewRequest("GET", "/organizations/subtype/commercial", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) var response []domain.Organization Expect(json.Unmarshal(w.Body.Bytes(), &response)).To(Succeed()) Expect(len(response)).To(Equal(1)) Expect(response[0].ID).To(Equal("org-1")) }) }) Describe("GetBySector", func() { It("should get organizations by sector", func() { org1 := &domain.Organization{ID: "org-1", Name: "Org 1", Sector: "Manufacturing"} org2 := &domain.Organization{ID: "org-2", Name: "Org 2", Sector: "Technology"} Expect(orgRepo.Create(context.TODO(), org1)).To(Succeed()) Expect(orgRepo.Create(context.TODO(), org2)).To(Succeed()) req, _ := http.NewRequest("GET", "/organizations/sector/Manufacturing", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) var response []domain.Organization Expect(json.Unmarshal(w.Body.Bytes(), &response)).To(Succeed()) Expect(len(response)).To(Equal(1)) Expect(response[0].ID).To(Equal("org-1")) }) }) Describe("GetByCertification", func() { It("should get organizations by certification", func() { certs1, _ := json.Marshal([]string{"ISO 9001", "ISO 14001"}) certs2, _ := json.Marshal([]string{"ISO 14001"}) org1 := &domain.Organization{ ID: "org-1", Name: "Org 1", Certifications: certs1, } org2 := &domain.Organization{ ID: "org-2", Name: "Org 2", Certifications: certs2, } Expect(orgRepo.Create(context.TODO(), org1)).To(Succeed()) Expect(orgRepo.Create(context.TODO(), org2)).To(Succeed()) req, _ := http.NewRequest("GET", "/organizations/certification/ISO 9001", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) Expect(w.Code).To(Equal(http.StatusOK)) var response []domain.Organization Expect(json.Unmarshal(w.Body.Bytes(), &response)).To(Succeed()) // PostgreSQL supports JSON containment operators (@>), so we expect 1 result // org1 has "ISO 9001" in its certifications array Expect(len(response)).To(Equal(1)) Expect(response[0].ID).To(Equal("org-1")) }) }) Describe("GetNearby", func() { It("should get nearby organizations", func() { // This would require PostGIS setup for proper testing // For now, just test that the endpoint exists and returns something req, _ := http.NewRequest("GET", "/organizations/nearby?lat=55.7558&lng=37.6173&radius=10", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // The exact behavior depends on PostGIS setup, but the endpoint should exist Expect(w.Code).To(Or(Equal(http.StatusOK), Equal(http.StatusInternalServerError))) }) }) })