mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Some checks failed
CI/CD Pipeline / backend-lint (push) Failing after 1m1s
CI/CD Pipeline / backend-build (push) Has been skipped
CI/CD Pipeline / frontend-lint (push) Successful in 1m37s
CI/CD Pipeline / frontend-build (push) Failing after 35s
CI/CD Pipeline / e2e-test (push) Has been skipped
- Replace pgtestdb with Testcontainers for improved test isolation and reliability - Update test setup functions to spin up dedicated PostgreSQL containers for each test - Ensure automatic cleanup of containers after tests to prevent resource leaks - Modify documentation to reflect changes in testing methodology and benefits of using Testcontainers
261 lines
7.2 KiB
Go
261 lines
7.2 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"bugulma/backend/internal/domain"
|
|
"bugulma/backend/internal/geospatial"
|
|
"bugulma/backend/internal/repository"
|
|
"bugulma/backend/internal/service"
|
|
"bugulma/backend/internal/testutils"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/suite"
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type SpatialResourceMatcherTestSuite struct {
|
|
suite.Suite
|
|
db *gorm.DB
|
|
siteRepo domain.SiteRepository
|
|
flowRepo domain.ResourceFlowRepository
|
|
geoSvc *service.GeospatialService
|
|
transportSvc *service.TransportationService
|
|
geoCalc geospatial.Calculator
|
|
matcher *service.SpatialResourceMatcher
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) SetupTest() {
|
|
suite.db = testutils.SetupTestDBWithTestcontainers(suite.T())
|
|
suite.siteRepo = repository.NewSiteRepository(suite.db)
|
|
suite.flowRepo = repository.NewResourceFlowRepository(suite.db)
|
|
suite.geoSvc = service.NewGeospatialService(suite.db, nil) // We'll test without geo features for basic functionality
|
|
suite.geoCalc = geospatial.NewCalculatorWithDefaults()
|
|
suite.transportSvc = service.NewTransportationService(suite.geoCalc)
|
|
suite.matcher = service.NewSpatialResourceMatcher(
|
|
nil, // geoRepo - not needed for basic matching tests
|
|
suite.siteRepo,
|
|
suite.flowRepo,
|
|
suite.geoSvc,
|
|
suite.transportSvc,
|
|
suite.geoCalc,
|
|
)
|
|
|
|
// Create test organization
|
|
org := &domain.Organization{ID: "org-test", Name: "Test Organization"}
|
|
err := repository.NewOrganizationRepository(suite.db).Create(context.Background(), org)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
func TestSpatialResourceMatcher(t *testing.T) {
|
|
suite.Run(t, new(SpatialResourceMatcherTestSuite))
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestNewSpatialResourceMatcher() {
|
|
assert.NotNil(suite.T(), suite.matcher)
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestSiteProvidesResource_PlatformDefault() {
|
|
// Create test site
|
|
site := &domain.Site{
|
|
ID: "site-test",
|
|
Name: "Test Site",
|
|
Latitude: 52.5200,
|
|
Longitude: 13.4050,
|
|
SiteType: domain.SiteTypeIndustrial,
|
|
OwnerOrganizationID: "org-test",
|
|
}
|
|
|
|
err := suite.siteRepo.Create(context.Background(), site)
|
|
suite.Require().NoError(err)
|
|
|
|
// Test that site creation worked
|
|
assert.NotNil(suite.T(), site)
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) setupTestSitesAndFlows() []*domain.Site {
|
|
// Create test sites
|
|
sites := []*domain.Site{
|
|
{
|
|
ID: "site-provider-1",
|
|
Name: "Energy Provider Site",
|
|
Latitude: 52.5200,
|
|
Longitude: 13.4050,
|
|
SiteType: domain.SiteTypeIndustrial,
|
|
OwnerOrganizationID: "org-test",
|
|
},
|
|
{
|
|
ID: "site-provider-2",
|
|
Name: "Waste Provider Site",
|
|
Latitude: 52.5300,
|
|
Longitude: 13.4150,
|
|
SiteType: domain.SiteTypeIndustrial,
|
|
OwnerOrganizationID: "org-test",
|
|
},
|
|
{
|
|
ID: "site-consumer",
|
|
Name: "Manufacturing Site",
|
|
Latitude: 52.5400,
|
|
Longitude: 13.4250,
|
|
SiteType: domain.SiteTypeIndustrial,
|
|
OwnerOrganizationID: "org-test",
|
|
},
|
|
}
|
|
|
|
for _, site := range sites {
|
|
err := suite.siteRepo.Create(context.Background(), site)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
// Create test resource flows
|
|
flows := []*domain.ResourceFlow{
|
|
{
|
|
ID: "flow-energy-output",
|
|
OrganizationID: "org-test",
|
|
SiteID: "site-provider-1",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: datatypes.JSON(`{"amount": 1000, "unit": "kWh"}`),
|
|
EconomicData: datatypes.JSON(`{"cost_out": 0.15}`),
|
|
},
|
|
{
|
|
ID: "flow-waste-output",
|
|
OrganizationID: "org-test",
|
|
SiteID: "site-provider-2",
|
|
Direction: domain.DirectionOutput,
|
|
Type: domain.TypeBiowaste,
|
|
Quantity: datatypes.JSON(`{"amount": 500, "unit": "kg"}`),
|
|
EconomicData: datatypes.JSON(`{"cost_out": 0.05}`),
|
|
},
|
|
{
|
|
ID: "flow-energy-input",
|
|
OrganizationID: "org-test",
|
|
SiteID: "site-consumer",
|
|
Direction: domain.DirectionInput,
|
|
Type: domain.TypeHeat,
|
|
Quantity: datatypes.JSON(`{"amount": 800, "unit": "kWh"}`),
|
|
EconomicData: datatypes.JSON(`{"cost_in": 0.20}`),
|
|
},
|
|
}
|
|
|
|
for _, flow := range flows {
|
|
err := suite.flowRepo.Create(context.Background(), flow)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
return sites
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestFindNearbyResourceProviders_Energy() {
|
|
suite.setupTestSitesAndFlows()
|
|
|
|
results, err := suite.matcher.FindNearbyResourceProviders(
|
|
context.Background(),
|
|
domain.TypeHeat,
|
|
52.5400, 13.4250, // Consumer location
|
|
10.0, // 10km radius
|
|
domain.TransportModeTruck,
|
|
)
|
|
|
|
assert.NoError(suite.T(), err)
|
|
assert.Len(suite.T(), results, 1) // Should find one energy provider
|
|
|
|
result := results[0]
|
|
assert.Equal(suite.T(), "flow-energy-output", result.ResourceFlow.ID)
|
|
assert.Equal(suite.T(), "site-provider-1", result.ProviderSite.ID)
|
|
assert.NotNil(suite.T(), result.SpatialMetrics)
|
|
assert.Greater(suite.T(), result.SpatialMetrics.StraightLineDistance, 0.0)
|
|
assert.Greater(suite.T(), result.MatchScore, 0.0)
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestFindNearbyResourceProviders_Waste() {
|
|
suite.setupTestSitesAndFlows()
|
|
|
|
results, err := suite.matcher.FindNearbyResourceProviders(
|
|
context.Background(),
|
|
domain.TypeBiowaste,
|
|
52.5400, 13.4250,
|
|
10.0,
|
|
domain.TransportModeTruck,
|
|
)
|
|
|
|
assert.NoError(suite.T(), err)
|
|
assert.Len(suite.T(), results, 1)
|
|
|
|
result := results[0]
|
|
assert.Equal(suite.T(), "flow-waste-output", result.ResourceFlow.ID)
|
|
assert.Equal(suite.T(), "site-provider-2", result.ProviderSite.ID)
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestFindNearbyResourceProviders_NoMatches() {
|
|
suite.setupTestSitesAndFlows()
|
|
|
|
// Search for chemical resources (none exist)
|
|
results, err := suite.matcher.FindNearbyResourceProviders(
|
|
context.Background(),
|
|
domain.TypeMaterials,
|
|
52.5400, 13.4250,
|
|
10.0,
|
|
domain.TransportModeTruck,
|
|
)
|
|
|
|
assert.NoError(suite.T(), err)
|
|
assert.Len(suite.T(), results, 0)
|
|
}
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestFindNearbyResourceProviders_OutOfRadius() {
|
|
suite.setupTestSitesAndFlows()
|
|
|
|
// Search with very small radius
|
|
results, err := suite.matcher.FindNearbyResourceProviders(
|
|
context.Background(),
|
|
domain.TypeHeat,
|
|
52.5400, 13.4250,
|
|
0.1, // Very small radius
|
|
domain.TransportModeTruck,
|
|
)
|
|
|
|
assert.NoError(suite.T(), err)
|
|
assert.Len(suite.T(), results, 0) // No providers within 0.1km
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (suite *SpatialResourceMatcherTestSuite) TestSpatialMatchResult_JSONSerialization() {
|
|
flow := &domain.ResourceFlow{
|
|
ID: "test-flow",
|
|
Type: domain.TypeHeat,
|
|
}
|
|
|
|
providerSite := &domain.Site{
|
|
ID: "test-site",
|
|
Name: "Test Provider",
|
|
Latitude: 52.5200,
|
|
Longitude: 13.4050,
|
|
}
|
|
|
|
metrics := &service.SpatialMetrics{
|
|
StraightLineDistance: 5.5,
|
|
TransportCost: 42.5,
|
|
EnvironmentalScore: 7.8,
|
|
}
|
|
|
|
result := &service.SpatialMatchResult{
|
|
ResourceFlow: flow,
|
|
ProviderSite: providerSite,
|
|
SpatialMetrics: metrics,
|
|
MatchScore: 8.2,
|
|
}
|
|
|
|
// This would test JSON serialization if we had JSON tags
|
|
// For now, just verify the struct is properly constructed
|
|
assert.NotNil(suite.T(), result.ResourceFlow)
|
|
assert.NotNil(suite.T(), result.ProviderSite)
|
|
assert.NotNil(suite.T(), result.SpatialMetrics)
|
|
assert.Equal(suite.T(), 8.2, result.MatchScore)
|
|
}
|