63ede5c237
- refactor: move HTTP status and DTO concerns out of model and service layers into API and handler code. - feat: add admin service boundary and route auth through services instead of direct repository access. - test: add architecture and error tests covering package boundaries, redaction, and service behavior. - docs: record the protocol-neutral boundary decision and update architecture and roadmap notes.
70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/dhao2001/mygo/internal/model"
|
|
"github.com/dhao2001/mygo/internal/repository"
|
|
)
|
|
|
|
func setupAdminService(t *testing.T) (*AdminService, repository.UserRepository) {
|
|
t.Helper()
|
|
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open db: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.User{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
|
|
userRepo := repository.NewUserRepository(db)
|
|
return NewAdminService(userRepo), userRepo
|
|
}
|
|
|
|
func TestAdminServiceGetUserMissingReturnsNotFound(t *testing.T) {
|
|
svc, _ := setupAdminService(t)
|
|
|
|
_, err := svc.GetUser(context.Background(), "missing")
|
|
var ae *model.AppError
|
|
if !errors.As(err, &ae) {
|
|
t.Fatalf("expected AppError, got %T: %v", err, err)
|
|
}
|
|
if ae.Kind != model.KindNotFound {
|
|
t.Fatalf("kind = %q, want %q", ae.Kind, model.KindNotFound)
|
|
}
|
|
}
|
|
|
|
func TestAdminServiceListIncludesDeletedUsers(t *testing.T) {
|
|
svc, repo := setupAdminService(t)
|
|
ctx := context.Background()
|
|
|
|
active := &model.User{ID: "active-1", Username: "active", Email: "active@example.com", Status: model.StatusActive}
|
|
deleted := &model.User{ID: "deleted-1", Username: "deleted", Email: "deleted@example.com", Status: model.StatusActive}
|
|
if err := repo.Create(ctx, active); err != nil {
|
|
t.Fatalf("create active: %v", err)
|
|
}
|
|
if err := repo.Create(ctx, deleted); err != nil {
|
|
t.Fatalf("create deleted: %v", err)
|
|
}
|
|
if err := repo.Delete(ctx, deleted.ID); err != nil {
|
|
t.Fatalf("delete user: %v", err)
|
|
}
|
|
|
|
users, total, err := svc.ListUsers(ctx, 0, 10)
|
|
if err != nil {
|
|
t.Fatalf("ListUsers = %v", err)
|
|
}
|
|
if total != 2 {
|
|
t.Fatalf("total = %d, want 2", total)
|
|
}
|
|
if len(users) != 2 {
|
|
t.Fatalf("len(users) = %d, want 2", len(users))
|
|
}
|
|
}
|