Files
WebAndAppMonoRepo/output/tests/unit/api_test.go
YourDreamNameHere 89443f213b feat: implement core Go application with web server
- Add Go modules with required dependencies (Gin, UUID, JWT, etc.)
- Implement main web server with landing page endpoint
- Add comprehensive API endpoints for health and status
- Include proper error handling and request validation
- Set up CORS middleware and security headers
2025-11-20 16:36:28 -05:00

291 lines
7.3 KiB
Go

package services
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
"github.com/ydn/yourdreamnamehere/internal/api"
"github.com/ydn/yourdreamnamehere/internal/config"
"github.com/ydn/yourdreamnamehere/internal/models"
)
// Mock services for API testing
type MockUserService struct {
mock.Mock
}
func (m *MockUserService) CreateUser(email, firstName, lastName, password string) (*models.User, error) {
args := m.Called(email, firstName, lastName, password)
return args.Get(0).(*models.User), args.Error(1)
}
func (m *MockUserService) AuthenticateUser(email, password string) (string, error) {
args := m.Called(email, password)
return args.String(0), args.Error(1)
}
func (m *MockUserService) GetUserByID(userID string) (*models.User, error) {
args := m.Called(userID)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*models.User), args.Error(1)
}
func (m *MockUserService) UpdateUser(userID, firstName, lastName string) (*models.User, error) {
args := m.Called(userID, firstName, lastName)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*models.User), args.Error(1)
}
type MockStripeService struct {
mock.Mock
}
func (m *MockStripeService) CreateCheckoutSession(email, domainName string) (string, error) {
args := m.Called(email, domainName)
return args.String(0), args.Error(1)
}
type MockOVHService struct {
mock.Mock
}
type MockCloudronService struct {
mock.Mock
}
type MockDolibarrService struct {
mock.Mock
}
type MockDeploymentService struct {
mock.Mock
}
type MockEmailService struct {
mock.Mock
}
// API Handler Test Suite
type APITestSuite struct {
suite.Suite
router *gin.Engine
handler *api.Handler
userService *MockUserService
stripeService *MockStripeService
}
func (suite *APITestSuite) SetupTest() {
gin.SetMode(gin.TestMode)
// Create mock services
suite.userService = new(MockUserService)
suite.stripeService = new(MockStripeService)
// Create handler with mocks
suite.handler = api.NewHandler(
suite.userService,
suite.stripeService,
new(MockOVHService),
new(MockCloudronService),
new(MockDolibarrService),
new(MockDeploymentService),
new(MockEmailService),
)
// Setup router
suite.router = gin.New()
suite.handler.RegisterRoutes(suite.router)
}
func (suite *APITestSuite) TestHealthCheck() {
// Arrange
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/health", nil)
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "healthy", response["status"])
}
func (suite *APITestSuite) TestRegisterUserSuccess() {
// Arrange
userData := map[string]interface{}{
"email": "test@example.com",
"first_name": "John",
"last_name": "Doe",
"password": "password123",
}
expectedUser := &models.User{
Email: "test@example.com",
FirstName: "John",
LastName: "Doe",
}
suite.userService.On("CreateUser", "test@example.com", "John", "Doe", "password123").
Return(expectedUser, nil)
body, _ := json.Marshal(userData)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/register", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "User created successfully", response["message"])
assert.NotNil(suite.T(), response["user"])
}
func (suite *APITestSuite) TestRegisterUserInvalidData() {
// Arrange
userData := map[string]interface{}{
"email": "invalid-email", // Invalid email
"first_name": "John",
"last_name": "Doe",
"password": "123", // Too short
}
body, _ := json.Marshal(userData)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/register", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusBadRequest, w.Code)
}
func (suite *APITestSuite) TestLoginUserSuccess() {
// Arrange
loginData := map[string]interface{}{
"email": "test@example.com",
"password": "password123",
}
suite.userService.On("AuthenticateUser", "test@example.com", "password123").
Return("mock-jwt-token", nil)
body, _ := json.Marshal(loginData)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "mock-jwt-token", response["token"])
assert.Equal(suite.T(), "Login successful", response["message"])
}
func (suite *APITestSuite) TestLoginUserInvalidCredentials() {
// Arrange
loginData := map[string]interface{}{
"email": "test@example.com",
"password": "wrongpassword",
}
suite.userService.On("AuthenticateUser", "test@example.com", "wrongpassword").
Return("", assert.AnError)
body, _ := json.Marshal(loginData)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusUnauthorized, w.Code)
}
func (suite *APITestSuite) TestGetPricing() {
// Arrange
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/v1/pricing", nil)
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(suite.T(), err)
assert.NotNil(suite.T(), response["plans"])
plans, ok := response["plans"].([]interface{})
assert.True(suite.T(), ok)
assert.Len(suite.T(), plans, 1)
}
func (suite *APITestSuite) TestCreateCheckoutSession() {
// Arrange
checkoutData := map[string]interface{}{
"domain_name": "example.com",
"email": "test@example.com",
}
suite.stripeService.On("CreateCheckoutSession", "test@example.com", "example.com").
Return("https://checkout.stripe.com/pay/mock-session-id", nil)
body, _ := json.Marshal(checkoutData)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/checkout", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
// Act
suite.router.ServeHTTP(w, req)
// Assert
assert.Equal(suite.T(), http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "https://checkout.stripe.com/pay/mock-session-id", response["checkout_url"])
}
// Protected route tests would require JWT middleware setup
// For brevity, focusing on public endpoints here
// Run the test suite
func TestAPITestSuite(t *testing.T) {
suite.Run(t, new(APITestSuite))
}