Add NoOp email service, /docs shortcut and fix streak timezone bug
Replace nil email service pattern with NoOpEmailService (Null Object) to eliminate nil pointer panics across all handlers. Add /docs route as a shortcut to Swagger UI. Fix streak calculation returning 0 when server timezone differs from UTC — CreatedAt was not converted to UTC before date extraction.
This commit is contained in:
1 parent
67fc508384
commit
a07d033e93
10 files changed
+42
-16
No files matched your search
@@ -73,7 +73,7 @@ func (h *RegisterUserHandler) Handle(ctx context.Context, cmd RegisterUserComman
|
||||
user := entities.NewUser(cmd.Email, hashedPassword)
|
||||
|
||||
emailVerificationRequired := false
|
||||
if h.emailService != nil {
|
||||
if h.emailService.IsEnabled() {
|
||||
token, err := h.generateVerificationToken()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate verification token: %w", err)
|
||||
|
||||
@@ -2,6 +2,7 @@ package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/domain/services"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"errors"
|
||||
@@ -71,7 +72,7 @@ func TestRegisterUserHandler_Success(t *testing.T) {
|
||||
},
|
||||
}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
cmd := RegisterUserCommand{
|
||||
Email: "test@example.com",
|
||||
@@ -88,7 +89,7 @@ func TestRegisterUserHandler_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
if result.EmailVerificationRequired {
|
||||
t.Error("expected email verification to not be required when emailService is nil")
|
||||
t.Error("expected email verification to not be required when email is disabled")
|
||||
}
|
||||
|
||||
if createdUser == nil {
|
||||
@@ -103,7 +104,7 @@ func TestRegisterUserHandler_Success(t *testing.T) {
|
||||
func TestRegisterUserHandler_InvalidEmail(t *testing.T) {
|
||||
repo := &mockUserRepo{}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -135,7 +136,7 @@ func TestRegisterUserHandler_InvalidEmail(t *testing.T) {
|
||||
func TestRegisterUserHandler_InvalidPassword(t *testing.T) {
|
||||
repo := &mockUserRepo{}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -174,7 +175,7 @@ func TestRegisterUserHandler_EmailAlreadyExists(t *testing.T) {
|
||||
},
|
||||
}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
cmd := RegisterUserCommand{
|
||||
Email: "test@example.com",
|
||||
@@ -195,7 +196,7 @@ func TestRegisterUserHandler_PasswordHashingError(t *testing.T) {
|
||||
return "", expectedErr
|
||||
},
|
||||
}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
cmd := RegisterUserCommand{
|
||||
Email: "test@example.com",
|
||||
@@ -216,7 +217,7 @@ func TestRegisterUserHandler_RepositoryError(t *testing.T) {
|
||||
},
|
||||
}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
cmd := RegisterUserCommand{
|
||||
Email: "test@example.com",
|
||||
@@ -232,7 +233,7 @@ func TestRegisterUserHandler_RepositoryError(t *testing.T) {
|
||||
func TestRegisterUserHandler_EdgeCases(t *testing.T) {
|
||||
repo := &mockUserRepo{}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "open", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "open", false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -285,7 +286,7 @@ func TestRegisterUserHandler_EdgeCases(t *testing.T) {
|
||||
func TestRegisterUserHandler_ClosedRegistration(t *testing.T) {
|
||||
repo := &mockUserRepo{}
|
||||
hasher := &mockPasswordHasher{}
|
||||
handler := NewRegisterUserHandler(repo, hasher, nil, "", "closed", false)
|
||||
handler := NewRegisterUserHandler(repo, hasher, &services.NoOpEmailService{}, "", "closed", false)
|
||||
|
||||
cmd := RegisterUserCommand{
|
||||
Email: "test@example.com",
|
||||
|
||||
@@ -89,6 +89,10 @@ func (m *mockRequestResetEmailService) HealthCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockRequestResetEmailService) IsEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func TestRequestPasswordResetHandler_Success(t *testing.T) {
|
||||
user := entities.NewUser("test@example.com", "hash")
|
||||
user.ID = "user-123"
|
||||
|
||||
@@ -69,6 +69,10 @@ func (m *mockEmailService) HealthCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockEmailService) IsEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func TestVerifyEmailHandler_Success(t *testing.T) {
|
||||
token := "valid-token"
|
||||
expiry := time.Now().Add(24 * time.Hour)
|
||||
|
||||
Reference in new issue
Block a user