To gitea and beyond, let's go(-yco)
This commit is contained in:
414
internal/repositories/refresh_token_repository_test.go
Normal file
414
internal/repositories/refresh_token_repository_test.go
Normal file
@@ -0,0 +1,414 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"goyco/internal/database"
|
||||
)
|
||||
|
||||
func TestRefreshTokenRepository_Create(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("successful creation", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-123",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if token.ID == 0 {
|
||||
t.Error("Expected token ID to be assigned")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("token with invalid user", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: 999,
|
||||
TokenHash: "token-hash-123",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for invalid user (SQLite allows this): %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("duplicate token hash", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token1 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "duplicate-token",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token1)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error for first token, got %v", err)
|
||||
}
|
||||
|
||||
token2 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "duplicate-token",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err = suite.RefreshTokenRepo.Create(token2)
|
||||
if err == nil {
|
||||
t.Error("Expected error for duplicate token hash")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_GetByTokenHash(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("existing token", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-123",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create token: %v", err)
|
||||
}
|
||||
|
||||
retrieved, err := suite.RefreshTokenRepo.GetByTokenHash("token-hash-123")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if retrieved == nil {
|
||||
t.Fatal("Expected token, got nil")
|
||||
}
|
||||
|
||||
if retrieved.TokenHash != "token-hash-123" {
|
||||
t.Errorf("Expected token hash 'token-hash-123', got %s", retrieved.TokenHash)
|
||||
}
|
||||
if retrieved.UserID != user.ID {
|
||||
t.Errorf("Expected user ID %d, got %d", user.ID, retrieved.UserID)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-existing token", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
_, err := suite.RefreshTokenRepo.GetByTokenHash("nonexistent-token")
|
||||
if err == nil {
|
||||
t.Error("Expected error for non-existing token")
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
t.Errorf("Expected ErrRecordNotFound, got %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_DeleteByUserID(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("successful delete", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token1 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-1",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
token2 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-2",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
suite.RefreshTokenRepo.Create(token1)
|
||||
suite.RefreshTokenRepo.Create(token2)
|
||||
|
||||
err := suite.RefreshTokenRepo.DeleteByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
_, err = suite.RefreshTokenRepo.GetByTokenHash("token-hash-1")
|
||||
if err == nil {
|
||||
t.Error("Expected error for deleted token")
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
t.Errorf("Expected ErrRecordNotFound, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("delete for user without tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
err := suite.RefreshTokenRepo.DeleteByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Delete should succeed even for user without tokens (GORM behavior)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_DeleteExpired(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("delete expired tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
expiredToken := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "expired-token",
|
||||
ExpiresAt: time.Now().Add(-1 * time.Hour),
|
||||
}
|
||||
|
||||
validToken := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "valid-token",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
suite.RefreshTokenRepo.Create(expiredToken)
|
||||
suite.RefreshTokenRepo.Create(validToken)
|
||||
|
||||
err := suite.RefreshTokenRepo.DeleteExpired()
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
_, err = suite.RefreshTokenRepo.GetByTokenHash("expired-token")
|
||||
if err == nil {
|
||||
t.Error("Expected error for deleted expired token")
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
t.Errorf("Expected ErrRecordNotFound, got %v", err)
|
||||
}
|
||||
|
||||
_, err = suite.RefreshTokenRepo.GetByTokenHash("valid-token")
|
||||
if err != nil {
|
||||
t.Errorf("Expected valid token to still exist, got error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_DeleteByID(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("successful delete", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-123",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create token: %v", err)
|
||||
}
|
||||
|
||||
err = suite.RefreshTokenRepo.DeleteByID(token.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
_, err = suite.RefreshTokenRepo.GetByTokenHash("token-hash-123")
|
||||
if err == nil {
|
||||
t.Error("Expected error for deleted token")
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
t.Errorf("Expected ErrRecordNotFound, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("delete non-existing token", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
err := suite.RefreshTokenRepo.DeleteByID(999)
|
||||
if err != nil {
|
||||
t.Fatalf("Delete should succeed even for non-existing token (GORM behavior)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_GetByUserID(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("user with tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token1 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-1",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
token2 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-2",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
suite.RefreshTokenRepo.Create(token1)
|
||||
suite.RefreshTokenRepo.Create(token2)
|
||||
|
||||
tokens, err := suite.RefreshTokenRepo.GetByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if len(tokens) != 2 {
|
||||
t.Errorf("Expected 2 tokens, got %d", len(tokens))
|
||||
}
|
||||
|
||||
for _, token := range tokens {
|
||||
if token.UserID != user.ID {
|
||||
t.Errorf("Expected user ID %d, got %d", user.ID, token.UserID)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("user without tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
tokens, err := suite.RefreshTokenRepo.GetByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if len(tokens) != 0 {
|
||||
t.Errorf("Expected 0 tokens, got %d", len(tokens))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_CountByUserID(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("user with tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token1 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-1",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
token2 := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "token-hash-2",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
suite.RefreshTokenRepo.Create(token1)
|
||||
suite.RefreshTokenRepo.Create(token2)
|
||||
|
||||
count, err := suite.RefreshTokenRepo.CountByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if count != 2 {
|
||||
t.Errorf("Expected 2 tokens, got %d", count)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("user without tokens", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
count, err := suite.RefreshTokenRepo.CountByUserID(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Errorf("Expected 0 tokens, got %d", count)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefreshTokenRepository_EdgeCases(t *testing.T) {
|
||||
suite := NewTestSuite(t)
|
||||
|
||||
t.Run("empty token hash", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: "",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for empty token hash: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("zero user ID", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
token := &database.RefreshToken{
|
||||
UserID: 0,
|
||||
TokenHash: "token-hash-123",
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for zero user ID: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("very long token hash", func(t *testing.T) {
|
||||
suite.Reset()
|
||||
|
||||
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
|
||||
|
||||
longToken := strings.Repeat("a", 300)
|
||||
token := &database.RefreshToken{
|
||||
UserID: user.ID,
|
||||
TokenHash: longToken,
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
err := suite.RefreshTokenRepo.Create(token)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for long token hash: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user