144 lines
5.2 KiB
Go
144 lines
5.2 KiB
Go
package repository
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/wmms/wmms/internal/model"
|
|
"github.com/wmms/wmms/pkg/database"
|
|
)
|
|
|
|
func TestListUsersIncludesAllAssignedRoles(t *testing.T) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("open sql mock: %v", err)
|
|
}
|
|
t.Cleanup(func() { database.DB = nil; db.Close() })
|
|
database.DB = db
|
|
now := time.Date(2026, 9, 16, 9, 0, 0, 0, time.Local)
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users`)).WillReturnRows(
|
|
sqlmock.NewRows([]string{"count"}).AddRow(1),
|
|
)
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, username, password, description, created_at FROM users ORDER BY id LIMIT ? OFFSET ?`)).
|
|
WithArgs(20, 0).
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "username", "password", "description", "created_at"}).
|
|
AddRow(7, "zhangsan", "hash", "测试用户", now))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT ur.user_id, r.id, r.code, r.name, r.enabled, r.created_at, r.updated_at
|
|
FROM user_roles ur JOIN roles r ON r.id = ur.role_id
|
|
WHERE ur.user_id IN (?) ORDER BY ur.user_id, r.id`)).
|
|
WithArgs(int64(7)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"user_id", "id", "code", "name", "enabled", "created_at", "updated_at"}).
|
|
AddRow(7, 2, "warehouse_admin", "仓库管理员", true, now, now).
|
|
AddRow(7, 3, "purchaser", "采购人员", true, now, now))
|
|
|
|
users, total, err := NewUserRepository().List("", 20, 0)
|
|
if err != nil {
|
|
t.Fatalf("list users: %v", err)
|
|
}
|
|
if total != 1 || len(users) != 1 || len(users[0].Roles) != 2 {
|
|
t.Fatalf("unexpected users: total=%d users=%+v", total, users)
|
|
}
|
|
if users[0].Roles[1].Name != "采购人员" {
|
|
t.Fatalf("role names not loaded: %+v", users[0].Roles)
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteRejectsLastSuperAdmin(t *testing.T) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("open sql mock: %v", err)
|
|
}
|
|
t.Cleanup(func() { database.DB = nil; db.Close() })
|
|
database.DB = db
|
|
|
|
mock.ExpectBegin()
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id FROM roles WHERE code = 'super_admin' FOR UPDATE`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM user_roles WHERE user_id = ? AND role_id = ?`)).
|
|
WithArgs(int64(7), int64(1)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM user_roles WHERE role_id = ?`)).
|
|
WithArgs(int64(1)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectRollback()
|
|
|
|
err = NewUserRepository().Delete(7)
|
|
if !errors.Is(err, ErrLastSuperAdmin) {
|
|
t.Fatalf("delete error = %v, want ErrLastSuperAdmin", err)
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateRejectsRemovingRoleFromLastSuperAdmin(t *testing.T) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("open sql mock: %v", err)
|
|
}
|
|
t.Cleanup(func() { database.DB = nil; db.Close() })
|
|
database.DB = db
|
|
|
|
mock.ExpectBegin()
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM roles WHERE enabled = TRUE AND id IN (?)`)).
|
|
WithArgs(int64(2)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id FROM roles WHERE code = 'super_admin' FOR UPDATE`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM user_roles WHERE user_id = ? AND role_id = ?`)).
|
|
WithArgs(int64(7), int64(1)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM user_roles WHERE role_id = ?`)).
|
|
WithArgs(int64(1)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectRollback()
|
|
|
|
user := &model.User{ID: 7, Description: "系统管理员"}
|
|
err = NewUserRepository().Update(user, []int64{2})
|
|
if !errors.Is(err, ErrLastSuperAdmin) {
|
|
t.Fatalf("update error = %v, want ErrLastSuperAdmin", err)
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestCreateUserAssignsMultipleEnabledRolesInTransaction(t *testing.T) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("open sql mock: %v", err)
|
|
}
|
|
t.Cleanup(func() { database.DB = nil; db.Close() })
|
|
database.DB = db
|
|
|
|
mock.ExpectBegin()
|
|
mock.ExpectExec(regexp.QuoteMeta(`INSERT INTO users (username, password, description) VALUES (?, ?, ?)`)).
|
|
WithArgs("zhangsan", "hash", "测试用户").
|
|
WillReturnResult(sqlmock.NewResult(7, 1))
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM roles WHERE enabled = TRUE AND id IN (?, ?)`)).
|
|
WithArgs(int64(2), int64(3)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(2))
|
|
mock.ExpectExec(regexp.QuoteMeta(`INSERT INTO user_roles (user_id, role_id) VALUES (?, ?), (?, ?)`)).
|
|
WithArgs(int64(7), int64(2), int64(7), int64(3)).
|
|
WillReturnResult(sqlmock.NewResult(0, 2))
|
|
mock.ExpectCommit()
|
|
|
|
user := &model.User{Username: "zhangsan", Password: "hash", Description: "测试用户"}
|
|
if err := NewUserRepository().Create(user, []int64{2, 3}); err != nil {
|
|
t.Fatalf("create user: %v", err)
|
|
}
|
|
if user.ID != 7 {
|
|
t.Fatalf("expected user id 7, got %d", user.ID)
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|