mirror of
https://github.com/laoxong/nofx.git
synced 2026-06-04 01:48:22 +08:00
253 lines
6.9 KiB
Go
253 lines
6.9 KiB
Go
package api
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// MockUser Mock user structure
|
|
type MockUser struct {
|
|
ID int
|
|
Email string
|
|
OTPSecret string
|
|
OTPVerified bool
|
|
}
|
|
|
|
// TestOTPRefetchLogic Test OTP refetch logic
|
|
func TestOTPRefetchLogic(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
existingUser *MockUser
|
|
userExists bool
|
|
expectedAction string // "allow_refetch", "reject_duplicate", "create_new"
|
|
expectedMessage string
|
|
}{
|
|
{
|
|
name: "New user registration - email does not exist",
|
|
existingUser: nil,
|
|
userExists: false,
|
|
expectedAction: "create_new",
|
|
expectedMessage: "Create new user",
|
|
},
|
|
{
|
|
name: "Incomplete OTP verification - allow refetch",
|
|
existingUser: &MockUser{
|
|
ID: 1,
|
|
Email: "test@example.com",
|
|
OTPSecret: "SECRET123",
|
|
OTPVerified: false,
|
|
},
|
|
userExists: true,
|
|
expectedAction: "allow_refetch",
|
|
expectedMessage: "Incomplete registration detected, please continue OTP setup",
|
|
},
|
|
{
|
|
name: "Completed OTP verification - reject duplicate registration",
|
|
existingUser: &MockUser{
|
|
ID: 2,
|
|
Email: "verified@example.com",
|
|
OTPSecret: "SECRET456",
|
|
OTPVerified: true,
|
|
},
|
|
userExists: true,
|
|
expectedAction: "reject_duplicate",
|
|
expectedMessage: "Email already registered",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Simulate logic processing flow
|
|
var actualAction string
|
|
var actualMessage string
|
|
|
|
if !tt.userExists {
|
|
// User does not exist, create new user
|
|
actualAction = "create_new"
|
|
actualMessage = "Create new user"
|
|
} else {
|
|
// User exists, check OTP verification status
|
|
if !tt.existingUser.OTPVerified {
|
|
// OTP verification incomplete, allow refetch
|
|
actualAction = "allow_refetch"
|
|
actualMessage = "Incomplete registration detected, please continue OTP setup"
|
|
} else {
|
|
// Verification completed, reject duplicate registration
|
|
actualAction = "reject_duplicate"
|
|
actualMessage = "Email already registered"
|
|
}
|
|
}
|
|
|
|
// Verify results
|
|
if actualAction != tt.expectedAction {
|
|
t.Errorf("Action mismatch: got %s, want %s", actualAction, tt.expectedAction)
|
|
}
|
|
if actualMessage != tt.expectedMessage {
|
|
t.Errorf("Message mismatch: got %s, want %s", actualMessage, tt.expectedMessage)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestOTPVerificationStates Test OTP verification state determination
|
|
func TestOTPVerificationStates(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
otpVerified bool
|
|
shouldAllowRefetch bool
|
|
}{
|
|
{
|
|
name: "OTP verified - disallow refetch",
|
|
otpVerified: true,
|
|
shouldAllowRefetch: false,
|
|
},
|
|
{
|
|
name: "OTP not verified - allow refetch",
|
|
otpVerified: false,
|
|
shouldAllowRefetch: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Simulate verification logic
|
|
allowRefetch := !tt.otpVerified
|
|
|
|
if allowRefetch != tt.shouldAllowRefetch {
|
|
t.Errorf("Refetch logic error: OTPVerified=%v, allowRefetch=%v, expected=%v",
|
|
tt.otpVerified, allowRefetch, tt.shouldAllowRefetch)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestRegistrationFlow Test complete registration flow logic branches
|
|
func TestRegistrationFlow(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
scenario string
|
|
userExists bool
|
|
otpVerified bool
|
|
expectHTTPCode int // Simulated HTTP status code
|
|
expectResponse string
|
|
}{
|
|
{
|
|
name: "Scenario 1: New user first registration",
|
|
scenario: "New user first accesses registration endpoint",
|
|
userExists: false,
|
|
otpVerified: false,
|
|
expectHTTPCode: 200,
|
|
expectResponse: "Create user and return OTP setup information",
|
|
},
|
|
{
|
|
name: "Scenario 2: User re-accesses after interrupting registration",
|
|
scenario: "User registered previously but did not complete OTP setup, now re-accessing",
|
|
userExists: true,
|
|
otpVerified: false,
|
|
expectHTTPCode: 200,
|
|
expectResponse: "Return existing user's OTP information, allow continuation",
|
|
},
|
|
{
|
|
name: "Scenario 3: Registered user attempts duplicate registration",
|
|
scenario: "User already completed registration, attempts to register again with same email",
|
|
userExists: true,
|
|
otpVerified: true,
|
|
expectHTTPCode: 409, // Conflict
|
|
expectResponse: "Email already registered",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Simulate registration flow logic
|
|
var actualHTTPCode int
|
|
var actualResponse string
|
|
|
|
if !tt.userExists {
|
|
// New user, create and return OTP information
|
|
actualHTTPCode = 200
|
|
actualResponse = "Create user and return OTP setup information"
|
|
} else {
|
|
// User exists
|
|
if !tt.otpVerified {
|
|
// OTP verification incomplete, allow refetch
|
|
actualHTTPCode = 200
|
|
actualResponse = "Return existing user's OTP information, allow continuation"
|
|
} else {
|
|
// Verification completed, reject duplicate registration
|
|
actualHTTPCode = 409
|
|
actualResponse = "Email already registered"
|
|
}
|
|
}
|
|
|
|
// Verify
|
|
if actualHTTPCode != tt.expectHTTPCode {
|
|
t.Errorf("HTTP code mismatch: got %d, want %d (scenario: %s)",
|
|
actualHTTPCode, tt.expectHTTPCode, tt.scenario)
|
|
}
|
|
if actualResponse != tt.expectResponse {
|
|
t.Errorf("Response mismatch: got %s, want %s (scenario: %s)",
|
|
actualResponse, tt.expectResponse, tt.scenario)
|
|
}
|
|
|
|
t.Logf("✓ %s: HTTP %d, %s", tt.scenario, actualHTTPCode, actualResponse)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestEdgeCases Test edge cases
|
|
func TestEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
user *MockUser
|
|
expectAllow bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "User ID is 0 - treated as new user",
|
|
user: &MockUser{
|
|
ID: 0,
|
|
Email: "new@example.com",
|
|
OTPVerified: false,
|
|
},
|
|
expectAllow: true,
|
|
description: "ID of 0 usually indicates user has not been created yet",
|
|
},
|
|
{
|
|
name: "OTPSecret is empty - still can refetch",
|
|
user: &MockUser{
|
|
ID: 1,
|
|
Email: "test@example.com",
|
|
OTPSecret: "",
|
|
OTPVerified: false,
|
|
},
|
|
expectAllow: true,
|
|
description: "Even if OTPSecret is empty, as long as not verified, refetch is allowed",
|
|
},
|
|
{
|
|
name: "OTPSecret exists but already verified - not allowed",
|
|
user: &MockUser{
|
|
ID: 2,
|
|
Email: "verified@example.com",
|
|
OTPSecret: "SECRET789",
|
|
OTPVerified: true,
|
|
},
|
|
expectAllow: false,
|
|
description: "Users with verified OTP cannot refetch",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Core logic: as long as OTPVerified is false, refetch is allowed
|
|
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)
|
|
})
|
|
}
|
|
}
|