package api import ( "testing" ) // MockUser 模擬用戶結構 type MockUser struct { ID int Email string OTPSecret string OTPVerified bool } // TestOTPRefetchLogic 測試 OTP 重新獲取邏輯 func TestOTPRefetchLogic(t *testing.T) { tests := []struct { name string existingUser *MockUser userExists bool expectedAction string // "allow_refetch", "reject_duplicate", "create_new" expectedMessage string }{ { name: "新用戶註冊_郵箱不存在", existingUser: nil, userExists: false, expectedAction: "create_new", expectedMessage: "創建新用戶", }, { name: "未完成OTP驗證_允許重新獲取", existingUser: &MockUser{ ID: 1, Email: "test@example.com", OTPSecret: "SECRET123", OTPVerified: false, }, userExists: true, expectedAction: "allow_refetch", expectedMessage: "检测到未完成的注册,请继续完成OTP设置", }, { name: "已完成OTP驗證_拒絕重複註冊", existingUser: &MockUser{ ID: 2, Email: "verified@example.com", OTPSecret: "SECRET456", OTPVerified: true, }, userExists: true, expectedAction: "reject_duplicate", expectedMessage: "邮箱已被注册", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 模擬邏輯處理流程 var actualAction string var actualMessage string if !tt.userExists { // 用戶不存在,創建新用戶 actualAction = "create_new" actualMessage = "創建新用戶" } else { // 用戶已存在,檢查 OTP 驗證狀態 if !tt.existingUser.OTPVerified { // 未完成 OTP 驗證,允許重新獲取 actualAction = "allow_refetch" actualMessage = "检测到未完成的注册,请继续完成OTP设置" } else { // 已完成驗證,拒絕重複註冊 actualAction = "reject_duplicate" actualMessage = "邮箱已被注册" } } // 驗證結果 if actualAction != tt.expectedAction { t.Errorf("Action 不符: got %s, want %s", actualAction, tt.expectedAction) } if actualMessage != tt.expectedMessage { t.Errorf("Message 不符: got %s, want %s", actualMessage, tt.expectedMessage) } }) } } // TestOTPVerificationStates 測試 OTP 驗證狀態判斷 func TestOTPVerificationStates(t *testing.T) { tests := []struct { name string otpVerified bool shouldAllowRefetch bool }{ { name: "OTP已驗證_不允許重新獲取", otpVerified: true, shouldAllowRefetch: false, }, { name: "OTP未驗證_允許重新獲取", otpVerified: false, shouldAllowRefetch: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 模擬驗證邏輯 allowRefetch := !tt.otpVerified if allowRefetch != tt.shouldAllowRefetch { t.Errorf("Refetch logic error: OTPVerified=%v, allowRefetch=%v, expected=%v", tt.otpVerified, allowRefetch, tt.shouldAllowRefetch) } }) } } // TestRegistrationFlow 測試完整註冊流程的邏輯分支 func TestRegistrationFlow(t *testing.T) { tests := []struct { name string scenario string userExists bool otpVerified bool expectHTTPCode int // 模擬的 HTTP 狀態碼 expectResponse string }{ { name: "場景1_新用戶首次註冊", scenario: "新用戶首次訪問註冊接口", userExists: false, otpVerified: false, expectHTTPCode: 200, expectResponse: "創建用戶並返回 OTP 設置信息", }, { name: "場景2_用戶中斷註冊後重新訪問", scenario: "用戶之前註冊但未完成 OTP 設置,現在重新訪問", userExists: true, otpVerified: false, expectHTTPCode: 200, expectResponse: "返回現有用戶的 OTP 信息,允許繼續完成", }, { name: "場景3_已註冊用戶嘗試重複註冊", scenario: "用戶已完成註冊,嘗試用同一郵箱再次註冊", userExists: true, otpVerified: true, expectHTTPCode: 409, // Conflict expectResponse: "邮箱已被注册", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 模擬註冊流程邏輯 var actualHTTPCode int var actualResponse string if !tt.userExists { // 新用戶,創建並返回 OTP 信息 actualHTTPCode = 200 actualResponse = "創建用戶並返回 OTP 設置信息" } else { // 用戶已存在 if !tt.otpVerified { // 未完成 OTP 驗證,允許重新獲取 actualHTTPCode = 200 actualResponse = "返回現有用戶的 OTP 信息,允許繼續完成" } else { // 已完成驗證,拒絕重複註冊 actualHTTPCode = 409 actualResponse = "邮箱已被注册" } } // 驗證 if actualHTTPCode != tt.expectHTTPCode { t.Errorf("HTTP code 不符: got %d, want %d (scenario: %s)", actualHTTPCode, tt.expectHTTPCode, tt.scenario) } if actualResponse != tt.expectResponse { t.Errorf("Response 不符: got %s, want %s (scenario: %s)", actualResponse, tt.expectResponse, tt.scenario) } t.Logf("✓ %s: HTTP %d, %s", tt.scenario, actualHTTPCode, actualResponse) }) } } // TestEdgeCases 測試邊界情況 func TestEdgeCases(t *testing.T) { tests := []struct { name string user *MockUser expectAllow bool description string }{ { name: "用戶ID為0_視為新用戶", user: &MockUser{ ID: 0, Email: "new@example.com", OTPVerified: false, }, expectAllow: true, description: "ID為0通常表示用戶還未創建", }, { name: "OTPSecret為空_仍可重新獲取", user: &MockUser{ ID: 1, Email: "test@example.com", OTPSecret: "", OTPVerified: false, }, expectAllow: true, description: "即使 OTPSecret 為空,只要未驗證就允許重新獲取", }, { name: "OTPSecret存在但已驗證_不允許", user: &MockUser{ ID: 2, Email: "verified@example.com", OTPSecret: "SECRET789", OTPVerified: true, }, expectAllow: false, description: "OTP 已驗證的用戶不能重新獲取", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 核心邏輯:只要 OTPVerified 為 false,就允許重新獲取 allowRefetch := !tt.user.OTPVerified if allowRefetch != tt.expectAllow { t.Errorf("Edge case failed: %s\nUser: ID=%d, OTPVerified=%v\nExpected allow=%v, got=%v", tt.description, tt.user.ID, tt.user.OTPVerified, tt.expectAllow, allowRefetch) } t.Logf("✓ %s", tt.description) }) } }