turash/bugulma/backend/internal/matching/plugins/registry_test.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

155 lines
4.3 KiB
Go

package plugins
import (
"testing"
"bugulma/backend/internal/domain"
"bugulma/backend/internal/matching/engine"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// MockPlugin is a mock implementation of the Plugin interface
type MockPlugin struct {
mock.Mock
name string
resourceType domain.ResourceType
}
func (m *MockPlugin) Name() string {
return m.name
}
func (m *MockPlugin) ResourceType() domain.ResourceType {
return m.resourceType
}
func (m *MockPlugin) SupportsQualityCheck() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockPlugin) SupportsEconomicCalculation() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockPlugin) SupportsTemporalCheck() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockPlugin) CheckQualityCompatibility(source, target *domain.ResourceFlow) (float64, error) {
args := m.Called(source, target)
return args.Get(0).(float64), args.Error(1)
}
func (m *MockPlugin) CalculateEconomicImpact(source, target *domain.ResourceFlow, distance float64) (float64, error) {
args := m.Called(source, target, distance)
return args.Get(0).(float64), args.Error(1)
}
func (m *MockPlugin) CheckTemporalCompatibility(source, target *domain.ResourceFlow) (float64, error) {
args := m.Called(source, target)
return args.Get(0).(float64), args.Error(1)
}
func (m *MockPlugin) ValidateCandidate(candidate *engine.Candidate) (bool, string) {
args := m.Called(candidate)
return args.Bool(0), args.String(1)
}
func TestRegistry_Register(t *testing.T) {
registry := NewRegistry()
plugin := &MockPlugin{
name: "test_plugin",
resourceType: domain.TypeHeat,
}
err := registry.Register(plugin)
assert.NoError(t, err)
// Try to register the same plugin again - should fail
err = registry.Register(plugin)
assert.Error(t, err)
assert.Contains(t, err.Error(), "already registered")
}
func TestRegistry_GetByResourceType(t *testing.T) {
registry := NewRegistry()
heatPlugin := &MockPlugin{name: "heat_plugin", resourceType: domain.TypeHeat}
biowastePlugin := &MockPlugin{name: "biowaste_plugin", resourceType: domain.TypeBiowaste}
anotherHeatPlugin := &MockPlugin{name: "heat_plugin_2", resourceType: domain.TypeHeat}
registry.Register(heatPlugin)
registry.Register(biowastePlugin)
registry.Register(anotherHeatPlugin)
heatPlugins := registry.GetByResourceType(domain.TypeHeat)
assert.Len(t, heatPlugins, 2)
assert.Contains(t, heatPlugins, heatPlugin)
assert.Contains(t, heatPlugins, anotherHeatPlugin)
biowastePlugins := registry.GetByResourceType(domain.TypeBiowaste)
assert.Len(t, biowastePlugins, 1)
assert.Contains(t, biowastePlugins, biowastePlugin)
waterPlugins := registry.GetByResourceType(domain.TypeWater)
assert.Len(t, waterPlugins, 0)
}
func TestRegistry_GetByName(t *testing.T) {
registry := NewRegistry()
plugin := &MockPlugin{name: "test_plugin", resourceType: domain.TypeHeat}
registry.Register(plugin)
found, err := registry.GetByName("test_plugin")
assert.NoError(t, err)
assert.Equal(t, plugin, found)
_, err = registry.GetByName("nonexistent")
assert.Error(t, err)
assert.Contains(t, err.Error(), "not found")
}
func TestRegistry_ListAll(t *testing.T) {
registry := NewRegistry()
plugin1 := &MockPlugin{name: "plugin1", resourceType: domain.TypeHeat}
plugin2 := &MockPlugin{name: "plugin2", resourceType: domain.TypeWater}
registry.Register(plugin1)
registry.Register(plugin2)
allPlugins := registry.ListAll()
assert.Len(t, allPlugins, 2)
assert.Contains(t, allPlugins, plugin1)
assert.Contains(t, allPlugins, plugin2)
}
func TestRegistry_GetMetadata(t *testing.T) {
registry := NewRegistry()
plugin := &MockPlugin{name: "test_plugin", resourceType: domain.TypeHeat}
plugin.On("SupportsQualityCheck").Return(true)
plugin.On("SupportsEconomicCalculation").Return(false)
plugin.On("SupportsTemporalCheck").Return(true)
registry.Register(plugin)
metadata, err := registry.GetMetadata("test_plugin")
assert.NoError(t, err)
assert.Equal(t, "test_plugin", metadata.Name)
assert.Equal(t, "heat", metadata.ResourceType)
assert.Contains(t, metadata.Capabilities, "quality_check")
assert.Contains(t, metadata.Capabilities, "temporal_check")
assert.NotContains(t, metadata.Capabilities, "economic_calculation")
_, err = registry.GetMetadata("nonexistent")
assert.Error(t, err)
}