mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Some checks failed
CI/CD Pipeline / backend-build (push) Blocked by required conditions
CI/CD Pipeline / e2e-test (push) Blocked by required conditions
CI/CD Pipeline / frontend-lint (push) Successful in 1m40s
CI/CD Pipeline / frontend-build (push) Failing after 36s
CI/CD Pipeline / backend-lint (push) Has been cancelled
- Replace instances of SetupTestDBWithTestcontainers with SetupTestDBWithTestcontainersForGinkgo in test files for better integration with Ginkgo - Ensure consistent test database setup across various handlers to enhance test isolation and reliability
263 lines
10 KiB
Go
263 lines
10 KiB
Go
package handler_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
|
|
"bugulma/backend/internal/testutils"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
|
|
"bugulma/backend/internal/domain"
|
|
"bugulma/backend/internal/handler"
|
|
"bugulma/backend/internal/repository"
|
|
"bugulma/backend/internal/service"
|
|
)
|
|
|
|
var _ = Describe("ResourceFlowHandler", func() {
|
|
var (
|
|
resourceHandler *handler.ResourceFlowHandler
|
|
resourceService *service.ResourceFlowService
|
|
resourceRepo domain.ResourceFlowRepository
|
|
organizationRepo domain.OrganizationRepository
|
|
siteRepo domain.SiteRepository
|
|
router *gin.Engine
|
|
db *gorm.DB
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
// Setup PostgreSQL test database using pgtestdb
|
|
db = testutils.SetupTestDBWithTestcontainersForGinkgo(GinkgoT())
|
|
|
|
resourceRepo = repository.NewResourceFlowRepository(db)
|
|
organizationRepo = repository.NewOrganizationRepository(db)
|
|
siteRepo = repository.NewSiteRepository(db)
|
|
resourceService = service.NewResourceFlowService(resourceRepo, nil)
|
|
resourceHandler = handler.NewResourceFlowHandler(resourceService)
|
|
|
|
router = gin.New()
|
|
router.POST("/resources", resourceHandler.Create)
|
|
router.GET("/resources/:id", resourceHandler.GetByID)
|
|
router.PUT("/resources/:id", resourceHandler.Update)
|
|
router.GET("/sites/:siteId/resources", resourceHandler.GetBySite)
|
|
router.GET("/organizations/:organizationId/resources", resourceHandler.GetByOrganization)
|
|
router.DELETE("/resources/:id", resourceHandler.Delete)
|
|
})
|
|
|
|
AfterEach(func() {
|
|
// pgtestdb automatically cleans up the database after each test
|
|
})
|
|
|
|
Describe("Create", func() {
|
|
It("should create a resource flow", func() {
|
|
// Create organization and site first (required for foreign keys)
|
|
org := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
site := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
Expect(organizationRepo.Create(context.TODO(), org)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site)).To(Succeed())
|
|
|
|
reqBody := handler.CreateResourceFlowRequest{
|
|
OrganizationID: "org-1",
|
|
SiteID: "site-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: domain.Quantity{
|
|
Amount: 100,
|
|
Unit: "kWh",
|
|
},
|
|
}
|
|
body, _ := json.Marshal(reqBody)
|
|
req, _ := http.NewRequest("POST", "/resources", 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.ResourceFlow
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.OrganizationID).To(Equal("org-1"))
|
|
Expect(resp.ID).NotTo(BeEmpty())
|
|
})
|
|
})
|
|
|
|
Describe("GetByID", func() {
|
|
It("should return resource flow by ID", func() {
|
|
// Create organization and site first
|
|
org := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
site := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
Expect(organizationRepo.Create(context.TODO(), org)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site)).To(Succeed())
|
|
|
|
rf := &domain.ResourceFlow{
|
|
ID: "rf-1",
|
|
OrganizationID: "org-1",
|
|
SiteID: "site-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: datatypes.JSON(`{"amount": 100, "unit": "kWh"}`),
|
|
}
|
|
Expect(resourceRepo.Create(context.TODO(), rf)).To(Succeed())
|
|
|
|
req, _ := http.NewRequest("GET", "/resources/rf-1", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
|
|
var resp domain.ResourceFlow
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.ID).To(Equal("rf-1"))
|
|
})
|
|
})
|
|
|
|
Describe("GetBySite", func() {
|
|
It("should return resources for a site", func() {
|
|
// Create organizations and sites first
|
|
org1 := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
org2 := &domain.Organization{ID: "org-2", Name: "Org 2"}
|
|
site1 := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
site2 := &domain.Site{ID: "site-2", Name: "Site 2", Latitude: 52.53, Longitude: 13.406, OwnerOrganizationID: "org-2"}
|
|
Expect(organizationRepo.Create(context.TODO(), org1)).To(Succeed())
|
|
Expect(organizationRepo.Create(context.TODO(), org2)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site1)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site2)).To(Succeed())
|
|
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-1", OrganizationID: "org-1", SiteID: "site-1", Direction: domain.DirectionOutput, Type: domain.TypeHeat, Quantity: datatypes.JSON(`{"amount": 100, "unit": "kWh"}`)})).To(Succeed())
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-2", OrganizationID: "org-1", SiteID: "site-1", Direction: domain.DirectionOutput, Type: domain.TypeWater, Quantity: datatypes.JSON(`{"amount": 50, "unit": "liters"}`)})).To(Succeed())
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-3", OrganizationID: "org-2", SiteID: "site-2", Direction: domain.DirectionOutput, Type: domain.TypeHeat, Quantity: datatypes.JSON(`{"amount": 200, "unit": "kWh"}`)})).To(Succeed())
|
|
|
|
req, _ := http.NewRequest("GET", "/sites/site-1/resources", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
|
|
var resp []domain.ResourceFlow
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp).To(HaveLen(2))
|
|
})
|
|
})
|
|
|
|
Describe("Update", func() {
|
|
It("should update a resource flow", func() {
|
|
// Create organization and site first
|
|
org := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
site := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
Expect(organizationRepo.Create(context.TODO(), org)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site)).To(Succeed())
|
|
|
|
rf := &domain.ResourceFlow{
|
|
ID: "rf-1",
|
|
OrganizationID: "org-1",
|
|
SiteID: "site-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: datatypes.JSON(`{"amount": 100, "unit": "kWh"}`),
|
|
}
|
|
Expect(resourceRepo.Create(context.TODO(), rf)).To(Succeed())
|
|
|
|
updateReq := handler.CreateResourceFlowRequest{
|
|
OrganizationID: "org-1",
|
|
SiteID: "site-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: domain.Quantity{
|
|
Amount: 150,
|
|
Unit: "kWh",
|
|
},
|
|
}
|
|
jsonData, _ := json.Marshal(updateReq)
|
|
|
|
req, _ := http.NewRequest("PUT", "/resources/rf-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 := resourceRepo.GetByID(context.Background(), "rf-1")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(updated.Quantity).NotTo(BeNil())
|
|
})
|
|
})
|
|
|
|
Describe("GetByOrganization", func() {
|
|
It("should return resources for an organization", func() {
|
|
// Create organizations and sites first
|
|
org1 := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
org2 := &domain.Organization{ID: "org-2", Name: "Org 2"}
|
|
site1 := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
site2 := &domain.Site{ID: "site-2", Name: "Site 2", Latitude: 52.53, Longitude: 13.406, OwnerOrganizationID: "org-1"}
|
|
Expect(organizationRepo.Create(context.TODO(), org1)).To(Succeed())
|
|
Expect(organizationRepo.Create(context.TODO(), org2)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site1)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site2)).To(Succeed())
|
|
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-1", OrganizationID: "org-1", SiteID: "site-1", Direction: domain.DirectionOutput, Type: domain.TypeHeat, Quantity: datatypes.JSON(`{"amount": 100, "unit": "kWh"}`)})).To(Succeed())
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-2", OrganizationID: "org-1", SiteID: "site-2", Direction: domain.DirectionOutput, Type: domain.TypeWater, Quantity: datatypes.JSON(`{"amount": 50, "unit": "liters"}`)})).To(Succeed())
|
|
Expect(resourceRepo.Create(context.TODO(), &domain.ResourceFlow{ID: "rf-3", OrganizationID: "org-2", SiteID: "site-1", Direction: domain.DirectionOutput, Type: domain.TypeHeat, Quantity: datatypes.JSON(`{"amount": 200, "unit": "kWh"}`)})).To(Succeed())
|
|
|
|
req, _ := http.NewRequest("GET", "/organizations/org-1/resources", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
|
|
var resp []domain.ResourceFlow
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp).To(HaveLen(2))
|
|
})
|
|
})
|
|
|
|
Describe("Delete", func() {
|
|
It("should delete a resource flow", func() {
|
|
// Create organization and site first
|
|
org := &domain.Organization{ID: "org-1", Name: "Org 1"}
|
|
site := &domain.Site{ID: "site-1", Name: "Site 1", Latitude: 52.52, Longitude: 13.405, OwnerOrganizationID: "org-1"}
|
|
Expect(organizationRepo.Create(context.TODO(), org)).To(Succeed())
|
|
Expect(siteRepo.Create(context.TODO(), site)).To(Succeed())
|
|
|
|
rf := &domain.ResourceFlow{
|
|
ID: "rf-1",
|
|
OrganizationID: "org-1",
|
|
SiteID: "site-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: datatypes.JSON(`{"amount": 100, "unit": "kWh"}`),
|
|
}
|
|
Expect(resourceRepo.Create(context.TODO(), rf)).To(Succeed())
|
|
|
|
req, _ := http.NewRequest("DELETE", "/resources/rf-1", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
Expect(w.Code).To(Equal(http.StatusNoContent))
|
|
|
|
// Verify it's gone
|
|
_, err := resourceRepo.GetByID(context.Background(), "rf-1")
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
})
|
|
})
|