mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 18:01:37 +00:00
a8fc177118
Root cause: certificate_versions.csr_pem is nullable in the schema but Go code scanned it into a plain string. Used sql.NullString in ListVersions and GetLatestVersion to handle NULL values correctly. Also includes: partial update fetch-merge-update pattern to prevent FK violations, nil directory guard in discovery service, diagnostic slog logging in handlers, export handler 422 for unparseable PEM, OpenAPI spec corrections, MCP tool description improvements, and test fixes. Rewrites the Release Sign-Off section in testing-guide.md to individual test-level granularity (320 rows) with smoke test results audited and checked off (121 pass, 5 skip, 194 manual remaining). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
691 lines
18 KiB
Go
691 lines
18 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/shankar0123/certctl/internal/domain"
|
|
)
|
|
|
|
// mockTeamRepo is a test implementation of TeamRepository
|
|
type mockTeamRepo struct {
|
|
teams map[string]*domain.Team
|
|
CreateErr error
|
|
UpdateErr error
|
|
DeleteErr error
|
|
GetErr error
|
|
ListErr error
|
|
}
|
|
|
|
func (m *mockTeamRepo) List(ctx context.Context) ([]*domain.Team, error) {
|
|
if m.ListErr != nil {
|
|
return nil, m.ListErr
|
|
}
|
|
var teams []*domain.Team
|
|
for _, t := range m.teams {
|
|
teams = append(teams, t)
|
|
}
|
|
return teams, nil
|
|
}
|
|
|
|
func (m *mockTeamRepo) Get(ctx context.Context, id string) (*domain.Team, error) {
|
|
if m.GetErr != nil {
|
|
return nil, m.GetErr
|
|
}
|
|
team, ok := m.teams[id]
|
|
if !ok {
|
|
return nil, errNotFound
|
|
}
|
|
return team, nil
|
|
}
|
|
|
|
func (m *mockTeamRepo) Create(ctx context.Context, team *domain.Team) error {
|
|
if m.CreateErr != nil {
|
|
return m.CreateErr
|
|
}
|
|
m.teams[team.ID] = team
|
|
return nil
|
|
}
|
|
|
|
func (m *mockTeamRepo) Update(ctx context.Context, team *domain.Team) error {
|
|
if m.UpdateErr != nil {
|
|
return m.UpdateErr
|
|
}
|
|
m.teams[team.ID] = team
|
|
return nil
|
|
}
|
|
|
|
func (m *mockTeamRepo) Delete(ctx context.Context, id string) error {
|
|
if m.DeleteErr != nil {
|
|
return m.DeleteErr
|
|
}
|
|
delete(m.teams, id)
|
|
return nil
|
|
}
|
|
|
|
func (m *mockTeamRepo) AddTeam(team *domain.Team) {
|
|
m.teams[team.ID] = team
|
|
}
|
|
|
|
func newMockTeamRepository() *mockTeamRepo {
|
|
return &mockTeamRepo{
|
|
teams: make(map[string]*domain.Team),
|
|
}
|
|
}
|
|
|
|
// TestTeamService_List tests retrieving teams with pagination
|
|
func TestTeamService_List(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Add test teams
|
|
for i := 0; i < 5; i++ {
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-" + string(rune(i)),
|
|
Name: "Team " + string(rune(48+i)),
|
|
})
|
|
}
|
|
|
|
teams, total, err := teamService.List(ctx, 1, 2)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if total != 5 {
|
|
t.Errorf("expected total 5, got %d", total)
|
|
}
|
|
|
|
if len(teams) != 2 {
|
|
t.Errorf("expected 2 teams on page 1, got %d", len(teams))
|
|
}
|
|
}
|
|
|
|
// TestTeamService_List_DefaultPagination tests default pagination values
|
|
func TestTeamService_List_DefaultPagination(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Add test teams
|
|
for i := 0; i < 10; i++ {
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-" + string(rune(i)),
|
|
Name: "Team " + string(rune(48+i)),
|
|
})
|
|
}
|
|
|
|
// Test page < 1 defaults to 1
|
|
teams, total, err := teamService.List(ctx, 0, 5)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if total != 10 {
|
|
t.Errorf("expected total 10, got %d", total)
|
|
}
|
|
|
|
if len(teams) != 5 {
|
|
t.Errorf("expected 5 teams, got %d", len(teams))
|
|
}
|
|
|
|
// Test perPage < 1 defaults to 50
|
|
teams, _, err = teamService.List(ctx, 1, 0)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if len(teams) != 10 {
|
|
t.Errorf("expected 10 teams with perPage=50, got %d", len(teams))
|
|
}
|
|
}
|
|
|
|
// TestTeamService_List_RepositoryError tests error handling from repo
|
|
func TestTeamService_List_RepositoryError(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
mockTeamRepo.ListErr = errors.New("database error")
|
|
|
|
_, _, err := teamService.List(ctx, 1, 50)
|
|
if err == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), "database error") {
|
|
t.Errorf("expected error containing 'database error', got %v", err)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_List_EmptyResult tests empty list response
|
|
func TestTeamService_List_EmptyResult(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
teams, total, err := teamService.List(ctx, 1, 50)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if total != 0 {
|
|
t.Errorf("expected total 0, got %d", total)
|
|
}
|
|
|
|
if len(teams) != 0 {
|
|
t.Errorf("expected empty slice, got %d teams", len(teams))
|
|
}
|
|
}
|
|
|
|
// TestTeamService_List_PageBeyondRange tests pagination beyond available data
|
|
func TestTeamService_List_PageBeyondRange(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Add only 3 teams
|
|
for i := 0; i < 3; i++ {
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-" + string(rune(i)),
|
|
Name: "Team " + string(rune(48+i)),
|
|
})
|
|
}
|
|
|
|
// Request page beyond range
|
|
teams, total, err := teamService.List(ctx, 10, 2)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if total != 3 {
|
|
t.Errorf("expected total 3, got %d", total)
|
|
}
|
|
|
|
if teams != nil && len(teams) != 0 {
|
|
t.Errorf("expected empty slice for page beyond range, got %d teams", len(teams))
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Get tests retrieving a single team
|
|
func TestTeamService_Get(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
testTeam := &domain.Team{
|
|
ID: "team-1",
|
|
Name: "Test Team",
|
|
}
|
|
mockTeamRepo.AddTeam(testTeam)
|
|
|
|
team, err := teamService.Get(ctx, "team-1")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if team.ID != "team-1" || team.Name != "Test Team" {
|
|
t.Errorf("expected team-1/Test Team, got %s/%s", team.ID, team.Name)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Get_NotFound tests retrieval of nonexistent team
|
|
func TestTeamService_Get_NotFound(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
_, err := teamService.Get(ctx, "nonexistent")
|
|
if err == nil {
|
|
t.Fatalf("expected error for nonexistent team, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Create tests creating a new team
|
|
func TestTeamService_Create(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
team := &domain.Team{
|
|
Name: "New Team",
|
|
Description: "A test team",
|
|
}
|
|
|
|
err := teamService.Create(ctx, team, "test-user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify ID was generated
|
|
if team.ID == "" {
|
|
t.Errorf("expected ID to be generated, got empty")
|
|
}
|
|
|
|
if !(team.ID[:5] == "team-") {
|
|
t.Logf("note: generated ID is %s", team.ID)
|
|
}
|
|
|
|
// Verify timestamps were set
|
|
if team.CreatedAt.IsZero() {
|
|
t.Errorf("expected CreatedAt to be set")
|
|
}
|
|
|
|
if team.UpdatedAt.IsZero() {
|
|
t.Errorf("expected UpdatedAt to be set")
|
|
}
|
|
|
|
// Verify team was stored
|
|
stored, err := teamService.Get(ctx, team.ID)
|
|
if err != nil {
|
|
t.Fatalf("failed to retrieve created team: %v", err)
|
|
}
|
|
|
|
if stored.Name != "New Team" {
|
|
t.Errorf("expected name 'New Team', got %s", stored.Name)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Create_EmptyName tests validation on empty name
|
|
func TestTeamService_Create_EmptyName(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
team := &domain.Team{
|
|
Name: "",
|
|
}
|
|
|
|
err := teamService.Create(ctx, team, "test-user")
|
|
if err == nil {
|
|
t.Fatalf("expected validation error for empty name, got nil")
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), "team name is required") {
|
|
t.Errorf("expected error containing 'team name is required', got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Create_WithExistingID tests preserving provided ID
|
|
func TestTeamService_Create_WithExistingID(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
team := &domain.Team{
|
|
ID: "custom-team-id",
|
|
Name: "Custom Team",
|
|
}
|
|
|
|
err := teamService.Create(ctx, team, "test-user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if team.ID != "custom-team-id" {
|
|
t.Errorf("expected ID to be preserved as custom-team-id, got %s", team.ID)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Create_RepositoryError tests repo error handling
|
|
func TestTeamService_Create_RepositoryError(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
mockTeamRepo.CreateErr = errors.New("database insert failed")
|
|
|
|
team := &domain.Team{
|
|
Name: "Test Team",
|
|
}
|
|
|
|
err := teamService.Create(ctx, team, "test-user")
|
|
if err == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Create_AuditRecorded tests audit event recording
|
|
func TestTeamService_Create_AuditRecorded(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
team := &domain.Team{
|
|
ID: "audit-test-team",
|
|
Name: "Audit Test Team",
|
|
}
|
|
|
|
err := teamService.Create(ctx, team, "audit-user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify audit event was recorded
|
|
if len(mockAuditRepo.Events) != 1 {
|
|
t.Errorf("expected 1 audit event, got %d", len(mockAuditRepo.Events))
|
|
}
|
|
|
|
if mockAuditRepo.Events[0].Action != "create_team" {
|
|
t.Errorf("expected action 'create_team', got %s", mockAuditRepo.Events[0].Action)
|
|
}
|
|
|
|
if mockAuditRepo.Events[0].ResourceID != "audit-test-team" {
|
|
t.Errorf("expected resource ID 'audit-test-team', got %s", mockAuditRepo.Events[0].ResourceID)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Update tests updating an existing team
|
|
func TestTeamService_Update(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Create initial team
|
|
initialTeam := &domain.Team{
|
|
ID: "team-update",
|
|
Name: "Original Name",
|
|
Description: "Original description",
|
|
}
|
|
mockTeamRepo.AddTeam(initialTeam)
|
|
|
|
// Update team
|
|
updateTeam := &domain.Team{
|
|
Name: "Updated Name",
|
|
Description: "Updated description",
|
|
}
|
|
|
|
err := teamService.Update(ctx, "team-update", updateTeam, "update-user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify ID was set correctly
|
|
if updateTeam.ID != "team-update" {
|
|
t.Errorf("expected ID to be set to team-update, got %s", updateTeam.ID)
|
|
}
|
|
|
|
// Verify team was updated
|
|
updated, err := teamService.Get(ctx, "team-update")
|
|
if err != nil {
|
|
t.Fatalf("failed to retrieve updated team: %v", err)
|
|
}
|
|
|
|
if updated.Name != "Updated Name" {
|
|
t.Errorf("expected name 'Updated Name', got %s", updated.Name)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Update_EmptyName tests validation on update
|
|
func TestTeamService_Update_EmptyName(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-1",
|
|
Name: "Original",
|
|
})
|
|
|
|
updateTeam := &domain.Team{
|
|
Name: "",
|
|
}
|
|
|
|
err := teamService.Update(ctx, "team-1", updateTeam, "user")
|
|
if err == nil {
|
|
t.Fatalf("expected validation error for empty name, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Update_RepositoryError tests repo error handling
|
|
func TestTeamService_Update_RepositoryError(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
mockTeamRepo.UpdateErr = errors.New("database update failed")
|
|
|
|
updateTeam := &domain.Team{
|
|
Name: "Updated",
|
|
}
|
|
|
|
err := teamService.Update(ctx, "team-1", updateTeam, "user")
|
|
if err == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Delete tests deleting a team
|
|
func TestTeamService_Delete(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Create team to delete
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-delete",
|
|
Name: "Team to Delete",
|
|
})
|
|
|
|
err := teamService.Delete(ctx, "team-delete", "delete-user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify team was deleted
|
|
_, err = teamService.Get(ctx, "team-delete")
|
|
if err == nil {
|
|
t.Errorf("expected error for deleted team, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_Delete_RepositoryError tests repo error handling
|
|
func TestTeamService_Delete_RepositoryError(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
mockTeamRepo.DeleteErr = errors.New("database delete failed")
|
|
|
|
err := teamService.Delete(ctx, "team-1", "user")
|
|
if err == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_ListTeams_HandlerInterface tests handler interface method
|
|
func TestTeamService_ListTeams_HandlerInterface(t *testing.T) {
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Add test teams
|
|
for i := 0; i < 3; i++ {
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "team-" + string(rune(i)),
|
|
Name: "Team " + string(rune(48+i)),
|
|
})
|
|
}
|
|
|
|
teams, total, err := teamService.ListTeams(1, 2)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if total != 3 {
|
|
t.Errorf("expected total 3, got %d", total)
|
|
}
|
|
|
|
if len(teams) != 3 {
|
|
t.Errorf("expected 3 teams (ListTeams doesn't paginate), got %d", len(teams))
|
|
}
|
|
}
|
|
|
|
// TestTeamService_GetTeam_HandlerInterface tests handler interface method
|
|
func TestTeamService_GetTeam_HandlerInterface(t *testing.T) {
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
testTeam := &domain.Team{
|
|
ID: "handler-team",
|
|
Name: "Handler Test Team",
|
|
}
|
|
mockTeamRepo.AddTeam(testTeam)
|
|
|
|
team, err := teamService.GetTeam("handler-team")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if team.ID != "handler-team" || team.Name != "Handler Test Team" {
|
|
t.Errorf("expected handler-team/Handler Test Team, got %s/%s", team.ID, team.Name)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_CreateTeam_HandlerInterface tests handler interface method
|
|
func TestTeamService_CreateTeam_HandlerInterface(t *testing.T) {
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
team := domain.Team{
|
|
Name: "Handler Create Team",
|
|
Description: "Created via handler",
|
|
}
|
|
|
|
result, err := teamService.CreateTeam(team)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if result.ID == "" {
|
|
t.Errorf("expected ID to be generated")
|
|
}
|
|
|
|
if result.Name != "Handler Create Team" {
|
|
t.Errorf("expected name 'Handler Create Team', got %s", result.Name)
|
|
}
|
|
|
|
if result.CreatedAt.IsZero() {
|
|
t.Errorf("expected CreatedAt to be set")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_UpdateTeam_HandlerInterface tests handler interface method
|
|
func TestTeamService_UpdateTeam_HandlerInterface(t *testing.T) {
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Create initial team
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "handler-update-team",
|
|
Name: "Original",
|
|
})
|
|
|
|
updateTeam := domain.Team{
|
|
Name: "Updated via Handler",
|
|
Description: "Handler update",
|
|
}
|
|
|
|
result, err := teamService.UpdateTeam("handler-update-team", updateTeam)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if result.ID != "handler-update-team" {
|
|
t.Errorf("expected ID handler-update-team, got %s", result.ID)
|
|
}
|
|
|
|
if result.Name != "Updated via Handler" {
|
|
t.Errorf("expected name 'Updated via Handler', got %s", result.Name)
|
|
}
|
|
}
|
|
|
|
// TestTeamService_DeleteTeam_HandlerInterface tests handler interface method
|
|
func TestTeamService_DeleteTeam_HandlerInterface(t *testing.T) {
|
|
mockTeamRepo := newMockTeamRepository()
|
|
mockAuditRepo := newMockAuditRepository()
|
|
auditService := NewAuditService(mockAuditRepo)
|
|
teamService := NewTeamService(mockTeamRepo, auditService)
|
|
|
|
// Create team to delete
|
|
mockTeamRepo.AddTeam(&domain.Team{
|
|
ID: "handler-delete-team",
|
|
Name: "To Delete",
|
|
})
|
|
|
|
err := teamService.DeleteTeam("handler-delete-team")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify deletion
|
|
_, err = mockTeamRepo.Get(context.Background(), "handler-delete-team")
|
|
if err == nil {
|
|
t.Errorf("expected error for deleted team")
|
|
}
|
|
}
|
|
|
|
// TestTeamService_NilAuditService tests behavior when audit service is nil
|
|
func TestTeamService_NilAuditService(t *testing.T) {
|
|
ctx := context.Background()
|
|
mockTeamRepo := newMockTeamRepository()
|
|
teamService := NewTeamService(mockTeamRepo, nil)
|
|
|
|
team := &domain.Team{
|
|
Name: "Test Team",
|
|
}
|
|
|
|
// Should not panic with nil audit service
|
|
err := teamService.Create(ctx, team, "user")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if team.ID == "" {
|
|
t.Errorf("expected ID to be generated")
|
|
}
|
|
}
|