refactor: [shitty claude AI first try] restructure server and user services, add new test cases, and improve error handling

This commit is contained in:
2025-08-10 21:40:15 +03:00
parent 588576b82f
commit f503e45be1
23 changed files with 2568 additions and 134 deletions

View File

@ -0,0 +1,293 @@
package handler
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// MockAuthService implements service.AuthService
type MockAuthService struct {
mock.Mock
}
func (m *MockAuthService) OtpRequest(ctx context.Context, phoneNumber string) error {
args := m.Called(ctx, phoneNumber)
return args.Error(0)
}
func (m *MockAuthService) OtpVerify(ctx context.Context, phoneNumber, code string, loginChallenge string) (string, error) {
args := m.Called(ctx, phoneNumber, code, loginChallenge)
return args.String(0), args.Error(1)
}
func (m *MockAuthService) AcceptConsent(ctx context.Context, phoneNumber string, challenge string) (string, error) {
args := m.Called(ctx, phoneNumber, challenge)
return args.String(0), args.Error(1)
}
func TestNewAuthHandler(t *testing.T) {
mockService := &MockAuthService{}
handler := NewAuthHandler(mockService)
assert.NotNil(t, handler)
assert.Equal(t, mockService, handler.service)
assert.Implements(t, (*StrictServerInterface)(nil), handler)
}
func TestAuthHandler_PostAuthOtpRequest(t *testing.T) {
tests := []struct {
name string
phoneNumber string
setupMock func(*MockAuthService)
expectedStatus int
expectedOk bool
expectedMsg string
}{
{
name: "successful otp request",
phoneNumber: "+79161234567",
setupMock: func(m *MockAuthService) {
m.On("OtpRequest", mock.Anything, "+79161234567").Return(nil).Once()
},
expectedStatus: 200,
expectedOk: true,
expectedMsg: "OTP request successful",
},
{
name: "service error",
phoneNumber: "invalid",
setupMock: func(m *MockAuthService) {
m.On("OtpRequest", mock.Anything, "invalid").Return(assert.AnError).Once()
},
expectedStatus: 400,
expectedOk: false,
expectedMsg: assert.AnError.Error(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockService := &MockAuthService{}
handler := &AuthHandler{service: mockService}
ctx := context.Background()
tt.setupMock(mockService)
request := PostAuthOtpRequestRequestObject{
Body: &PostAuthOtpRequestJSONRequestBody{
PhoneNumber: tt.phoneNumber,
},
}
result, err := handler.PostAuthOtpRequest(ctx, request)
assert.NoError(t, err) // Handler should not return errors, only response objects
if tt.expectedStatus == 200 {
response, ok := result.(PostAuthOtpRequest200JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
} else {
response, ok := result.(PostAuthOtpRequest400JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
}
mockService.AssertExpectations(t)
})
}
}
func TestAuthHandler_PostAuthOtpVerify(t *testing.T) {
tests := []struct {
name string
phoneNumber string
otp string
loginChallenge string
setupMock func(*MockAuthService)
expectedStatus int
expectedOk bool
expectedMsg string
expectedRedirect string
}{
{
name: "successful otp verification",
phoneNumber: "+79161234567",
otp: "123456",
loginChallenge: "challenge123",
setupMock: func(m *MockAuthService) {
m.On("OtpVerify", mock.Anything, "+79161234567", "123456", "challenge123").
Return("https://example.com/callback", nil).Once()
},
expectedStatus: 200,
expectedOk: true,
expectedMsg: "OTP verification successful",
expectedRedirect: "https://example.com/callback",
},
{
name: "service error",
phoneNumber: "+79161234567",
otp: "wrong",
loginChallenge: "challenge123",
setupMock: func(m *MockAuthService) {
m.On("OtpVerify", mock.Anything, "+79161234567", "wrong", "challenge123").
Return("", assert.AnError).Once()
},
expectedStatus: 400,
expectedOk: false,
expectedMsg: assert.AnError.Error(),
expectedRedirect: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockService := &MockAuthService{}
handler := &AuthHandler{service: mockService}
ctx := context.Background()
tt.setupMock(mockService)
request := PostAuthOtpVerifyRequestObject{
Body: &PostAuthOtpVerifyJSONRequestBody{
PhoneNumber: tt.phoneNumber,
Otp: tt.otp,
LoginChallenge: tt.loginChallenge,
},
}
result, err := handler.PostAuthOtpVerify(ctx, request)
assert.NoError(t, err)
if tt.expectedStatus == 200 {
response, ok := result.(PostAuthOtpVerify200JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
assert.Equal(t, tt.expectedRedirect, response.RedirectUrl)
} else {
response, ok := result.(PostAuthOtpVerify400JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
assert.Equal(t, tt.expectedRedirect, response.RedirectUrl)
}
mockService.AssertExpectations(t)
})
}
}
func TestAuthHandler_PostAuthConsentAccept(t *testing.T) {
tests := []struct {
name string
phoneNumber string
consentChallenge string
setupMock func(*MockAuthService)
expectedStatus int
expectedOk bool
expectedMsg string
expectedRedirect string
}{
{
name: "successful consent accept",
phoneNumber: "+79161234567",
consentChallenge: "consent123",
setupMock: func(m *MockAuthService) {
m.On("AcceptConsent", mock.Anything, "+79161234567", "consent123").
Return("https://example.com/callback", nil).Once()
},
expectedStatus: 200,
expectedOk: true,
expectedMsg: "Consent accepted successfully",
expectedRedirect: "https://example.com/callback",
},
{
name: "service error",
phoneNumber: "+79161234567",
consentChallenge: "invalid",
setupMock: func(m *MockAuthService) {
m.On("AcceptConsent", mock.Anything, "+79161234567", "invalid").
Return("", assert.AnError).Once()
},
expectedStatus: 400,
expectedOk: false,
expectedMsg: assert.AnError.Error(),
expectedRedirect: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockService := &MockAuthService{}
handler := &AuthHandler{service: mockService}
ctx := context.Background()
tt.setupMock(mockService)
request := PostAuthConsentAcceptRequestObject{
Body: &PostAuthConsentAcceptJSONRequestBody{
PhoneNumber: tt.phoneNumber,
ConsentChallenge: tt.consentChallenge,
},
}
result, err := handler.PostAuthConsentAccept(ctx, request)
assert.NoError(t, err)
if tt.expectedStatus == 200 {
response, ok := result.(PostAuthConsentAccept200JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
assert.Equal(t, tt.expectedRedirect, response.RedirectUrl)
} else {
response, ok := result.(PostAuthConsentAccept400JSONResponse)
assert.True(t, ok)
assert.Equal(t, tt.expectedOk, response.Ok)
assert.Equal(t, tt.expectedMsg, response.Message)
assert.Equal(t, tt.expectedRedirect, response.RedirectUrl)
}
mockService.AssertExpectations(t)
})
}
}
func TestAuthHandler_EdgeCases(t *testing.T) {
t.Run("nil request body should not panic", func(t *testing.T) {
mockService := &MockAuthService{}
handler := &AuthHandler{service: mockService}
ctx := context.Background()
// Test with nil body - this should be handled by the generated code
// but we test that our handler doesn't panic
defer func() {
if r := recover(); r != nil {
t.Errorf("Handler panicked with nil body: %v", r)
}
}()
request := PostAuthOtpRequestRequestObject{
Body: &PostAuthOtpRequestJSONRequestBody{
PhoneNumber: "",
},
}
mockService.On("OtpRequest", mock.Anything, "").Return(assert.AnError).Once()
result, err := handler.PostAuthOtpRequest(ctx, request)
assert.NoError(t, err)
assert.NotNil(t, result)
mockService.AssertExpectations(t)
})
}