package domain import ( "testing" "time" ) func TestToken_AccessTokenExpires(t *testing.T) { tests := []struct { name string expiresIn int want time.Duration }{ {"zero expiration", 0, 0}, {"1 second expiration", 1, time.Second}, {"60 seconds expiration", 60, time.Minute}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{ExpiresIn: tt.expiresIn} if got := token.AccessTokenExpires(); got != tt.want { t.Errorf("AccessTokenExpires() = %v, want %v", got, tt.want) } }) } } func TestToken_RefreshTokenExpires(t *testing.T) { tests := []struct { name string refreshExpires int want time.Duration }{ {"zero expiration", 0, 0}, {"1 second expiration", 1, time.Second}, {"90 seconds expiration", 90, 90 * time.Second}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{RefreshExpiresIn: tt.refreshExpires} if got := token.RefreshTokenExpires(); got != tt.want { t.Errorf("RefreshTokenExpires() = %v, want %v", got, tt.want) } }) } } func TestToken_RefreshTokenExpiresUnix(t *testing.T) { tests := []struct { name string refreshExpires int }{ {"zero expiration", 0}, {"10 seconds expiration", 10}, {"60 seconds expiration", 60}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{RefreshExpiresIn: tt.refreshExpires} got := token.RefreshTokenExpiresUnix() want := time.Now().Add(time.Duration(tt.refreshExpires) * time.Second).UnixNano() // 確保計算的時間戳在合理範圍內 if got < want-1e9 || got > want+1e9 { t.Errorf("RefreshTokenExpiresUnix() = %v, want %v (±1 second tolerance)", got, want) } }) } } func TestToken_IsExpires(t *testing.T) { now := time.Now() tests := []struct { name string accessCreateAt time.Time expiresIn int want bool }{ {"not expired", now.Add(-5 * time.Minute), 600, false}, // 10-minute expiry, created 5 minutes ago {"just expired", now.Add(-10 * time.Minute), 600, true}, // 10-minute expiry, created 10 minutes ago {"already expired", now.Add(-15 * time.Minute), 600, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{AccessCreateAt: tt.accessCreateAt, ExpiresIn: tt.expiresIn} if got := token.IsExpires(); got != tt.want { t.Errorf("IsExpires() = %v, want %v", got, tt.want) } }) } } func TestToken_RedisExpiredSec(t *testing.T) { now := time.Now().Unix() tests := []struct { name string expiresIn int }{ {"zero expiration", 0}, {"future expiration", int(now + 3600)}, // Expires in 1 hour } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{ExpiresIn: tt.expiresIn} got := token.RedisExpiredSec() want := time.Unix(int64(tt.expiresIn), 0).Sub(time.Now().UTC()).Seconds() if float64(got) < want-1 || float64(got) > want+1 { t.Errorf("RedisExpiredSec() = %v, want ~%v (±1 second tolerance)", got, int64(want)) } }) } } func TestToken_RedisRefreshExpiredSec(t *testing.T) { now := time.Now().Unix() tests := []struct { name string refreshExpires int }{ {"zero refresh expiration", 0}, {"future refresh expiration", int(now + 7200)}, // Expires in 2 hours } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { token := Token{RefreshExpiresIn: tt.refreshExpires} got := token.RedisRefreshExpiredSec() want := time.Unix(int64(tt.refreshExpires), 0).Sub(time.Now().UTC()).Seconds() if float64(got) < want-1 || float64(got) > want+1 { t.Errorf("RedisRefreshExpiredSec() = %v, want ~%v (±1 second tolerance)", got, int64(want)) } }) } }