package service import ( "context" "errors" "testing" "secunda-test/internal/domain" ) func TestTeamServiceInviteRequiresOwnerOrAdmin(t *testing.T) { teams := &fakeTeamRepo{members: map[int64]map[int64]domain.Role{1: {10: domain.RoleMember}}} users := &fakeUserRepo{user: domain.User{ID: 20, Email: "new@example.com"}} svc := NewTeamService(teams, users, fakeEmail{}) err := svc.Invite(context.Background(), 10, 1, "new@example.com") if !errors.Is(err, ErrForbidden) { t.Fatalf("expected forbidden, got %v", err) } } func TestTeamServiceInviteAddsMember(t *testing.T) { teams := &fakeTeamRepo{members: map[int64]map[int64]domain.Role{1: {10: domain.RoleAdmin}}} users := &fakeUserRepo{user: domain.User{ID: 20, Email: "new@example.com"}} svc := NewTeamService(teams, users, fakeEmail{}) if err := svc.Invite(context.Background(), 10, 1, "new@example.com"); err != nil { t.Fatalf("unexpected error: %v", err) } if role, ok := teams.members[1][20]; !ok || role != domain.RoleMember { t.Fatalf("expected invited member, got role=%q ok=%v", role, ok) } } type fakeUserRepo struct { user domain.User } func (r *fakeUserRepo) Create(ctx context.Context, email, passwordHash, name string) (domain.User, error) { return domain.User{ID: 1, Email: email, PasswordHash: passwordHash, Name: name}, nil } func (r *fakeUserRepo) FindByEmail(ctx context.Context, email string) (domain.User, error) { if r.user.Email == email { return r.user, nil } return domain.User{}, ErrNotFound } func (r *fakeUserRepo) FindByID(ctx context.Context, id int64) (domain.User, error) { if r.user.ID == id { return r.user, nil } return domain.User{}, ErrNotFound } type fakeEmail struct{} func (fakeEmail) SendInvite(ctx context.Context, email, teamName string) error { return nil }