mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 15:11:29 +00:00
8b75e0311b
Mechanical sed across the main go.mod's module declaration, the f5-mock-icontrol
sub-module's go.mod, every Go file's import path (361 files), and a rebuild of
the checked-in f5-mock-icontrol binary so its embedded build-info reflects the
new module path. No behavior change.
Choice B from cowork/transfer-certctl-to-org.md, executed 2026-05-04. Choice A
(keep module path declared as github.com/shankar0123/certctl regardless of
repo URL) shipped on the day of the org transfer (2026-05-03) since we had no
external Go consumers; this commit closes that deferral.
Backward-compat: GitHub HTTP redirects continue to forward
github.com/shankar0123/certctl → github.com/certctl-io/certctl at the URL
level, but Go's module proxy uses the path declared in go.mod as the
canonical name. Pre-fix, anyone trying `go get github.com/certctl-io/certctl/...`
hit a "module path mismatch" error because go.mod said
github.com/shankar0123/certctl and the URL they fetched it from said
certctl-io/certctl. Post-fix, the canonical name and the URL agree, so
go get / go install / external Go consumers / Go-tooling integrations
work cleanly via either the new path (preferred) or the old path (which
redirects and Go follows the redirect for source fetch).
Anyone still importing the old path inside their own code keeps working
provided they update their go.mod's `require` line to match — the module
path declared in their consumer's go.sum / go.mod is the authoritative
import name, so a mass sed across their import statements is the migration
on the consumer side. No external consumers exist today.
Diff shape:
361 *.go files — import path replacement only
2 go.mod — module declaration replacement only
1 binary — deploy/test/f5-mock-icontrol/f5-mock-icontrol rebuilt
so embedded build-info reflects the new path (8618965 vs
8618933 bytes; 32-byte diff is the build-info change)
Total: 364 files, 730 insertions / 730 deletions, net-zero size, pure
mechanical substitution.
Verification:
gofmt: 17 files needed re-alignment after sed (the new path is one char
shorter than the old, so column-aligned import groups drifted). Applied
`gofmt -w` to fix.
go mod tidy: clean exit on both modules.
go vet ./...: clean exit.
go build ./...: clean exit.
go test -short -count=1 on representative packages: all green
(internal/domain, internal/validation, internal/crypto, internal/crypto/signer,
cmd/agent). Test output now reads `ok github.com/certctl-io/certctl/...`
confirming the module path resolves correctly.
binary: f5-mock-icontrol rebuilt; `strings | grep shankar0123` returns
nothing; `strings | grep certctl-io/certctl` shows the new module path
embedded in build-info.
Files intentionally NOT touched in this commit:
README.md / CHANGELOG.md / docs/ / etc. — already swept to certctl-io
URLs in commit 0729ee4 (the post-transfer URL refresh). This commit is
purely the Go-tooling layer.
Scarf pixels (`shankar0123.docker.scarf.sh/...`) — Scarf-account
namespace, not a Go import or GitHub repo URL. Stays.
This is a non-blocking, non-customer-impacting change. Operators pulling
container images, running `make verify`, hitting the API, or installing the
agent see no functional difference. Only Go-tooling consumers (none today)
are affected, and they're enabled — not broken — by this commit.
691 lines
18 KiB
Go
691 lines
18 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/certctl-io/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(context.Background(), 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(context.Background(), "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(context.Background(), 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(context.Background(), "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(context.Background(), "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")
|
|
}
|
|
}
|