package service_test import ( "context" "encoding/json" "testing" "bugulma/backend/internal/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "gorm.io/gorm" "bugulma/backend/internal/domain" "bugulma/backend/internal/repository" "bugulma/backend/internal/service" ) type SiteServiceTestSuite struct { suite.Suite db *gorm.DB repo domain.SiteRepository orgRepo domain.OrganizationRepository svc *service.SiteService } func (suite *SiteServiceTestSuite) SetupTest() { // Setup PostgreSQL test database using pgtestdb suite.db = testutils.SetupTestDB(suite.T()) suite.repo = repository.NewSiteRepository(suite.db) suite.orgRepo = repository.NewOrganizationRepository(suite.db) suite.svc = service.NewSiteService(suite.repo) } func (suite *SiteServiceTestSuite) TearDownTest() { // pgtestdb automatically cleans up the database after each test } func (suite *SiteServiceTestSuite) TestCreate() { // Create organization first (required for foreign key constraint) org := &domain.Organization{ID: "org-1", Name: "Test Organization"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org)) req := service.CreateSiteRequest{ Name: "Test Site", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, FloorAreaM2: 1000.0, Ownership: domain.OwnershipOwned, OwnerOrganizationID: "org-1", AvailableUtilities: []string{"electricity", "water"}, ParkingSpaces: 50, LoadingDocks: 5, CraneCapacityTonnes: 10.0, EnergyRating: "A", } site, err := suite.svc.Create(context.Background(), req) assert.NoError(suite.T(), err) assert.NotEmpty(suite.T(), site.ID) assert.Equal(suite.T(), "Test Site", site.Name) assert.Equal(suite.T(), domain.SiteTypeIndustrial, site.SiteType) assert.Equal(suite.T(), 1000.0, site.FloorAreaM2) assert.Equal(suite.T(), 50, site.ParkingSpaces) var utilities []string err = json.Unmarshal(site.AvailableUtilities, &utilities) assert.NoError(suite.T(), err) assert.Equal(suite.T(), []string{"electricity", "water"}, utilities) } func (suite *SiteServiceTestSuite) TestGetByID() { // Create organization first org := &domain.Organization{ID: "org-1", Name: "Test Organization"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org)) req := service.CreateSiteRequest{ Name: "Test Site", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } created, err := suite.svc.Create(context.Background(), req) suite.Require().NoError(err) found, err := suite.svc.GetByID(context.Background(), created.ID) assert.NoError(suite.T(), err) assert.Equal(suite.T(), created.ID, found.ID) assert.Equal(suite.T(), "Test Site", found.Name) } func (suite *SiteServiceTestSuite) TestGetByIDNotFound() { _, err := suite.svc.GetByID(context.Background(), "non-existent-id") assert.Error(suite.T(), err) } func (suite *SiteServiceTestSuite) TestGetAll() { // Create organizations first org1 := &domain.Organization{ID: "org-1", Name: "Test Organization 1"} org2 := &domain.Organization{ID: "org-2", Name: "Test Organization 2"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org1)) suite.Require().NoError(suite.orgRepo.Create(context.Background(), org2)) req1 := service.CreateSiteRequest{ Name: "Site 1", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } req2 := service.CreateSiteRequest{ Name: "Site 2", Latitude: 52.53, Longitude: 13.406, SiteType: domain.SiteTypeRetail, OwnerOrganizationID: "org-2", } _, err := suite.svc.Create(context.Background(), req1) suite.Require().NoError(err) _, err = suite.svc.Create(context.Background(), req2) suite.Require().NoError(err) sites, err := suite.svc.GetAll(context.Background()) assert.NoError(suite.T(), err) assert.Len(suite.T(), sites, 2) } func (suite *SiteServiceTestSuite) TestGetByOrganizationID() { // Create organizations first org1 := &domain.Organization{ID: "org-1", Name: "Test Organization 1"} org2 := &domain.Organization{ID: "org-2", Name: "Test Organization 2"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org1)) suite.Require().NoError(suite.orgRepo.Create(context.Background(), org2)) req1 := service.CreateSiteRequest{ Name: "Site 1", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } req2 := service.CreateSiteRequest{ Name: "Site 2", Latitude: 52.53, Longitude: 13.406, SiteType: domain.SiteTypeRetail, OwnerOrganizationID: "org-2", } _, err := suite.svc.Create(context.Background(), req1) suite.Require().NoError(err) _, err = suite.svc.Create(context.Background(), req2) suite.Require().NoError(err) sites, err := suite.svc.GetByOrganizationID(context.Background(), "org-1") assert.NoError(suite.T(), err) assert.Len(suite.T(), sites, 1) assert.Equal(suite.T(), "Site 1", sites[0].Name) } func (suite *SiteServiceTestSuite) TestGetByOrganizationIDNoSites() { sites, err := suite.svc.GetByOrganizationID(context.Background(), "non-existent-org") assert.NoError(suite.T(), err) assert.Len(suite.T(), sites, 0) } func (suite *SiteServiceTestSuite) TestGetNearby() { // Create organization first org := &domain.Organization{ID: "org-1", Name: "Test Organization"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org)) req := service.CreateSiteRequest{ Name: "Test Site", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } _, err := suite.svc.Create(context.Background(), req) suite.Require().NoError(err) sites, err := suite.svc.GetNearby(context.Background(), 52.52, 13.405, 10) assert.NoError(suite.T(), err) assert.Len(suite.T(), sites, 1) } func (suite *SiteServiceTestSuite) TestGetNearbyNoSites() { sites, err := suite.svc.GetNearby(context.Background(), 0, 0, 1) assert.NoError(suite.T(), err) assert.Len(suite.T(), sites, 0) } func (suite *SiteServiceTestSuite) TestUpdate() { // Create organization first org := &domain.Organization{ID: "org-1", Name: "Test Organization"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org)) req := service.CreateSiteRequest{ Name: "Test Site", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } site, err := suite.svc.Create(context.Background(), req) suite.Require().NoError(err) site.Name = "Updated Site" site.FloorAreaM2 = 2000.0 site.ParkingSpaces = 100 err = suite.svc.Update(context.Background(), site) assert.NoError(suite.T(), err) found, err := suite.svc.GetByID(context.Background(), site.ID) assert.NoError(suite.T(), err) assert.Equal(suite.T(), "Updated Site", found.Name) assert.Equal(suite.T(), 2000.0, found.FloorAreaM2) assert.Equal(suite.T(), 100, found.ParkingSpaces) } func (suite *SiteServiceTestSuite) TestDelete() { // Create organization first org := &domain.Organization{ID: "org-1", Name: "Test Organization"} suite.Require().NoError(suite.orgRepo.Create(context.Background(), org)) req := service.CreateSiteRequest{ Name: "Test Site", Latitude: 52.52, Longitude: 13.405, SiteType: domain.SiteTypeIndustrial, OwnerOrganizationID: "org-1", } site, err := suite.svc.Create(context.Background(), req) suite.Require().NoError(err) err = suite.svc.Delete(context.Background(), site.ID) assert.NoError(suite.T(), err) _, err = suite.svc.GetByID(context.Background(), site.ID) assert.Error(suite.T(), err) } func TestSiteServiceTestSuite(t *testing.T) { suite.Run(t, new(SiteServiceTestSuite)) }