283 lines
7.4 KiB
Go
283 lines
7.4 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
|
|
"git.threesix.ai/jordan/persona-community-2/pkg/logging"
|
|
"git.threesix.ai/jordan/persona-community-2/services/persona-api/internal/domain"
|
|
"git.threesix.ai/jordan/persona-community-2/services/persona-api/internal/port"
|
|
)
|
|
|
|
// mockExampleRepository implements port.ExampleRepository for testing.
|
|
type mockExampleRepository struct {
|
|
mu sync.RWMutex
|
|
examples map[domain.ExampleID]*domain.Example
|
|
}
|
|
|
|
var _ port.ExampleRepository = (*mockExampleRepository)(nil)
|
|
|
|
func newMockExampleRepository() *mockExampleRepository {
|
|
return &mockExampleRepository{
|
|
examples: make(map[domain.ExampleID]*domain.Example),
|
|
}
|
|
}
|
|
|
|
func (m *mockExampleRepository) List(ctx context.Context) ([]domain.Example, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
result := make([]domain.Example, 0, len(m.examples))
|
|
for _, e := range m.examples {
|
|
result = append(result, *e)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (m *mockExampleRepository) Get(ctx context.Context, id domain.ExampleID) (*domain.Example, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
e, ok := m.examples[id]
|
|
if !ok {
|
|
return nil, domain.ErrExampleNotFound
|
|
}
|
|
// Return a copy to avoid mutation
|
|
copy := *e
|
|
return ©, nil
|
|
}
|
|
|
|
func (m *mockExampleRepository) Create(ctx context.Context, example *domain.Example) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
// Store a copy
|
|
copy := *example
|
|
m.examples[example.ID] = ©
|
|
return nil
|
|
}
|
|
|
|
func (m *mockExampleRepository) Update(ctx context.Context, example *domain.Example) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if _, ok := m.examples[example.ID]; !ok {
|
|
return domain.ErrExampleNotFound
|
|
}
|
|
// Store a copy
|
|
copy := *example
|
|
m.examples[example.ID] = ©
|
|
return nil
|
|
}
|
|
|
|
func (m *mockExampleRepository) Delete(ctx context.Context, id domain.ExampleID) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if _, ok := m.examples[id]; !ok {
|
|
return domain.ErrExampleNotFound
|
|
}
|
|
delete(m.examples, id)
|
|
return nil
|
|
}
|
|
|
|
func (m *mockExampleRepository) ExistsByName(ctx context.Context, name string) (bool, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
for _, e := range m.examples {
|
|
if e.Name == name {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func TestExampleService_Create(t *testing.T) {
|
|
repo := newMockExampleRepository()
|
|
svc := NewExampleService(repo, logging.Nop())
|
|
|
|
t.Run("creates example successfully", func(t *testing.T) {
|
|
example, err := svc.Create(context.Background(), CreateInput{
|
|
Name: "Test Example",
|
|
Description: "A test description",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if example.Name != "Test Example" {
|
|
t.Errorf("expected name 'Test Example', got '%s'", example.Name)
|
|
}
|
|
if example.ID.IsZero() {
|
|
t.Error("expected non-empty ID")
|
|
}
|
|
})
|
|
|
|
t.Run("rejects duplicate name", func(t *testing.T) {
|
|
_, err := svc.Create(context.Background(), CreateInput{
|
|
Name: "Test Example",
|
|
Description: "Another description",
|
|
})
|
|
if err != domain.ErrDuplicateExample {
|
|
t.Errorf("expected ErrDuplicateExample, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects empty name", func(t *testing.T) {
|
|
_, err := svc.Create(context.Background(), CreateInput{
|
|
Name: "",
|
|
Description: "Description",
|
|
})
|
|
if err != domain.ErrInvalidExampleName {
|
|
t.Errorf("expected ErrInvalidExampleName, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExampleService_Get(t *testing.T) {
|
|
repo := newMockExampleRepository()
|
|
svc := NewExampleService(repo, logging.Nop())
|
|
|
|
// Create an example first
|
|
created, _ := svc.Create(context.Background(), CreateInput{
|
|
Name: "Get Test",
|
|
Description: "Description",
|
|
})
|
|
|
|
t.Run("returns existing example", func(t *testing.T) {
|
|
example, err := svc.Get(context.Background(), created.ID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if example.Name != "Get Test" {
|
|
t.Errorf("expected name 'Get Test', got '%s'", example.Name)
|
|
}
|
|
})
|
|
|
|
t.Run("returns not found for missing example", func(t *testing.T) {
|
|
_, err := svc.Get(context.Background(), "nonexistent-id")
|
|
if err != domain.ErrExampleNotFound {
|
|
t.Errorf("expected ErrExampleNotFound, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExampleService_Update(t *testing.T) {
|
|
repo := newMockExampleRepository()
|
|
svc := NewExampleService(repo, logging.Nop())
|
|
|
|
// Create examples
|
|
example1, _ := svc.Create(context.Background(), CreateInput{
|
|
Name: "Update Test 1",
|
|
Description: "Original",
|
|
})
|
|
_, _ = svc.Create(context.Background(), CreateInput{
|
|
Name: "Update Test 2",
|
|
Description: "Other",
|
|
})
|
|
|
|
t.Run("updates example successfully", func(t *testing.T) {
|
|
updated, err := svc.Update(context.Background(), example1.ID, UpdateInput{
|
|
Name: "Updated Name",
|
|
Description: "Updated description",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if updated.Name != "Updated Name" {
|
|
t.Errorf("expected name 'Updated Name', got '%s'", updated.Name)
|
|
}
|
|
})
|
|
|
|
t.Run("allows same name on same example", func(t *testing.T) {
|
|
_, err := svc.Update(context.Background(), example1.ID, UpdateInput{
|
|
Name: "Updated Name",
|
|
Description: "Same name",
|
|
})
|
|
if err != nil {
|
|
t.Errorf("unexpected error updating with same name: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects name conflict", func(t *testing.T) {
|
|
_, err := svc.Update(context.Background(), example1.ID, UpdateInput{
|
|
Name: "Update Test 2",
|
|
Description: "Conflict",
|
|
})
|
|
if err != domain.ErrDuplicateExample {
|
|
t.Errorf("expected ErrDuplicateExample, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("returns not found for missing example", func(t *testing.T) {
|
|
_, err := svc.Update(context.Background(), "nonexistent-id", UpdateInput{
|
|
Name: "Anything",
|
|
Description: "",
|
|
})
|
|
if err != domain.ErrExampleNotFound {
|
|
t.Errorf("expected ErrExampleNotFound, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExampleService_Delete(t *testing.T) {
|
|
repo := newMockExampleRepository()
|
|
svc := NewExampleService(repo, logging.Nop())
|
|
|
|
// Create an example first
|
|
created, _ := svc.Create(context.Background(), CreateInput{
|
|
Name: "Delete Test",
|
|
Description: "To be deleted",
|
|
})
|
|
|
|
t.Run("deletes example successfully", func(t *testing.T) {
|
|
err := svc.Delete(context.Background(), created.ID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify deleted
|
|
_, err = svc.Get(context.Background(), created.ID)
|
|
if err != domain.ErrExampleNotFound {
|
|
t.Errorf("expected ErrExampleNotFound after delete, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("returns not found for missing example", func(t *testing.T) {
|
|
err := svc.Delete(context.Background(), "nonexistent-id")
|
|
if err != domain.ErrExampleNotFound {
|
|
t.Errorf("expected ErrExampleNotFound, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExampleService_List(t *testing.T) {
|
|
repo := newMockExampleRepository()
|
|
svc := NewExampleService(repo, logging.Nop())
|
|
|
|
t.Run("returns empty list initially", func(t *testing.T) {
|
|
examples, err := svc.List(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(examples) != 0 {
|
|
t.Errorf("expected 0 examples, got %d", len(examples))
|
|
}
|
|
})
|
|
|
|
// Create some examples
|
|
_, _ = svc.Create(context.Background(), CreateInput{Name: "List Test 1", Description: ""})
|
|
_, _ = svc.Create(context.Background(), CreateInput{Name: "List Test 2", Description: ""})
|
|
|
|
t.Run("returns all examples", func(t *testing.T) {
|
|
examples, err := svc.List(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(examples) != 2 {
|
|
t.Errorf("expected 2 examples, got %d", len(examples))
|
|
}
|
|
})
|
|
}
|