- Add new test files for auth, service, and handler modules - Improve test organization and coverage - Refactor code for better maintainability - Add captcha, settings, stats, and theme handler tests - Add auth module tests (CAS, OAuth, password, SSO, state) - Add service layer tests for auth, export, permissions, roles - All Go tests pass (exit code 0) - All frontend tests pass (325 tests in 59 files)
195 lines
4.7 KiB
Go
195 lines
4.7 KiB
Go
package service
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/user-management-system/internal/domain"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Export Helper Functions Tests
|
|
// =============================================================================
|
|
|
|
func TestGenderLabel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
gender domain.Gender
|
|
expected string
|
|
}{
|
|
{"male", domain.GenderMale, "男"},
|
|
{"female", domain.GenderFemale, "女"},
|
|
{"unknown", domain.GenderUnknown, "未知"},
|
|
{"other", domain.Gender(99), "未知"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := genderLabel(tt.gender)
|
|
if result != tt.expected {
|
|
t.Errorf("genderLabel(%v) = %q, want %q", tt.gender, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserStatusLabel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
status domain.UserStatus
|
|
expected string
|
|
}{
|
|
{"active", domain.UserStatusActive, "已激活"},
|
|
{"inactive", domain.UserStatusInactive, "未激活"},
|
|
{"locked", domain.UserStatusLocked, "已锁定"},
|
|
{"disabled", domain.UserStatusDisabled, "已禁用"},
|
|
{"unknown", domain.UserStatus(99), "未知"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := userStatusLabel(tt.status)
|
|
if result != tt.expected {
|
|
t.Errorf("userStatusLabel(%v) = %q, want %q", tt.status, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoolLabel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
value bool
|
|
expected string
|
|
}{
|
|
{"true", true, "是"},
|
|
{"false", false, "否"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := boolLabel(tt.value)
|
|
if result != tt.expected {
|
|
t.Errorf("boolLabel(%v) = %q, want %q", tt.value, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildColIndex(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
headers []string
|
|
expected map[string]int
|
|
}{
|
|
{
|
|
name: "empty headers",
|
|
headers: []string{},
|
|
expected: map[string]int{},
|
|
},
|
|
{
|
|
name: "single header",
|
|
headers: []string{"name"},
|
|
expected: map[string]int{"name": 0},
|
|
},
|
|
{
|
|
name: "multiple headers",
|
|
headers: []string{"name", "email", "phone"},
|
|
expected: map[string]int{"name": 0, "email": 1, "phone": 2},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := buildColIndex(tt.headers)
|
|
for k, v := range tt.expected {
|
|
if result[k] != v {
|
|
t.Errorf("buildColIndex(%v)[%q] = %d, want %d", tt.headers, k, result[k], v)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHashPassword(t *testing.T) {
|
|
t.Run("hash password success", func(t *testing.T) {
|
|
hash, err := hashPassword("testpassword123")
|
|
if err != nil {
|
|
t.Fatalf("hashPassword failed: %v", err)
|
|
}
|
|
if hash == "" {
|
|
t.Error("Expected non-empty hash")
|
|
}
|
|
if hash == "testpassword123" {
|
|
t.Error("Hash should not equal plaintext")
|
|
}
|
|
})
|
|
|
|
t.Run("hash different passwords produce different hashes", func(t *testing.T) {
|
|
hash1, _ := hashPassword("password1")
|
|
hash2, _ := hashPassword("password2")
|
|
if hash1 == hash2 {
|
|
t.Error("Different passwords should produce different hashes")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestResolveExportColumns(t *testing.T) {
|
|
t.Run("empty fields returns default columns", func(t *testing.T) {
|
|
columns, err := resolveExportColumns(nil)
|
|
if err != nil {
|
|
t.Fatalf("resolveExportColumns failed: %v", err)
|
|
}
|
|
if len(columns) == 0 {
|
|
t.Error("Expected default columns for empty input")
|
|
}
|
|
})
|
|
|
|
t.Run("empty slice returns default columns", func(t *testing.T) {
|
|
columns, err := resolveExportColumns([]string{})
|
|
if err != nil {
|
|
t.Fatalf("resolveExportColumns failed: %v", err)
|
|
}
|
|
if len(columns) == 0 {
|
|
t.Error("Expected default columns for empty slice")
|
|
}
|
|
})
|
|
|
|
t.Run("specific fields", func(t *testing.T) {
|
|
columns, err := resolveExportColumns([]string{"username", "email"})
|
|
if err != nil {
|
|
t.Fatalf("resolveExportColumns failed: %v", err)
|
|
}
|
|
if len(columns) != 2 {
|
|
t.Errorf("Expected 2 columns, got %d", len(columns))
|
|
}
|
|
})
|
|
|
|
t.Run("invalid field returns error", func(t *testing.T) {
|
|
_, err := resolveExportColumns([]string{"invalid_field_xyz"})
|
|
if err == nil {
|
|
t.Error("Expected error for invalid field")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestTimeLabel(t *testing.T) {
|
|
t.Run("nil time returns empty", func(t *testing.T) {
|
|
result := timeLabel(nil)
|
|
if result != "" {
|
|
t.Errorf("Expected empty string for nil time, got %q", result)
|
|
}
|
|
})
|
|
|
|
t.Run("valid time returns formatted string", func(t *testing.T) {
|
|
now := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
|
|
result := timeLabel(&now)
|
|
if result == "" {
|
|
t.Error("Expected formatted time string")
|
|
}
|
|
if len(result) < 10 {
|
|
t.Errorf("Expected longer time string, got %q", result)
|
|
}
|
|
})
|
|
}
|