package auth import ( "strings" "testing" "time" ) func TestGenerateAccessToken(t *testing.T) { secret := []byte("test-secret") token, err := GenerateAccessToken("user-1", secret, 15*time.Minute) if err != nil { t.Fatalf("GenerateAccessToken = %v", err) } if token == "" { t.Fatal("token is empty") } if !strings.Contains(token, ".") { t.Fatal("token does not look like a JWT") } } func TestParseTokenValid(t *testing.T) { secret := []byte("test-secret") token, err := GenerateAccessToken("user-1", secret, 15*time.Minute) if err != nil { t.Fatalf("GenerateAccessToken = %v", err) } claims, err := ParseToken(token, secret) if err != nil { t.Fatalf("ParseToken = %v", err) } if claims.UserID != "user-1" { t.Errorf("UserID = %q, want %q", claims.UserID, "user-1") } if claims.Type != TokenAccess { t.Errorf("Type = %q, want %q", claims.Type, TokenAccess) } } func TestParseTokenWrongSecret(t *testing.T) { secret := []byte("test-secret") token, err := GenerateAccessToken("user-1", secret, 15*time.Minute) if err != nil { t.Fatalf("GenerateAccessToken = %v", err) } _, err = ParseToken(token, []byte("wrong-secret")) if err == nil { t.Fatal("expected error for wrong secret, got nil") } } func TestParseTokenExpired(t *testing.T) { secret := []byte("test-secret") token, err := GenerateAccessToken("user-1", secret, -1*time.Minute) if err != nil { t.Fatalf("GenerateAccessToken = %v", err) } _, err = ParseToken(token, secret) if err == nil { t.Fatal("expected error for expired token, got nil") } } func TestParseTokenInvalidFormat(t *testing.T) { _, err := ParseToken("not-a-jwt", []byte("secret")) if err == nil { t.Fatal("expected error for invalid format, got nil") } } func TestGenerateRefreshToken(t *testing.T) { secret := []byte("test-secret") token, err := GenerateRefreshToken("user-1", secret, 7*24*time.Hour) if err != nil { t.Fatalf("GenerateRefreshToken = %v", err) } if token == "" { t.Fatal("token is empty") } if !strings.Contains(token, ".") { t.Fatal("token does not look like a JWT") } claims, err := ParseToken(token, secret) if err != nil { t.Fatalf("ParseToken = %v", err) } if claims.Type != TokenRefresh { t.Errorf("Type = %q, want %q", claims.Type, TokenRefresh) } } func TestTokenUserIDCarried(t *testing.T) { secret := []byte("test-secret") token, _ := GenerateAccessToken("alice-42", secret, 15*time.Minute) claims, err := ParseToken(token, secret) if err != nil { t.Fatalf("ParseToken = %v", err) } if claims.UserID != "alice-42" { t.Errorf("UserID = %q, want %q", claims.UserID, "alice-42") } } func TestRefreshTokenRejectedByMiddleware(t *testing.T) { secret := []byte("test-secret") token, err := GenerateRefreshToken("user-1", secret, 7*24*time.Hour) if err != nil { t.Fatalf("GenerateRefreshToken = %v", err) } // Simulate what the middleware does: parse + check type claims, err := ParseToken(token, secret) if err != nil { t.Fatalf("ParseToken = %v", err) } if claims.Type != TokenRefresh { t.Fatalf("expected refresh token type, got %q", claims.Type) } // The actual middleware rejection is tested in middleware/auth_test.go }