fix: resolve swagger duplicates and add backend tests
This commit is contained in:
parent
fdf256d436
commit
8ffd35741d
6 changed files with 763 additions and 1606 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -123,7 +123,6 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param company body registerCompanyRequest true "Dados da empresa"
|
||||
// @Success 201 {object} domain.Company
|
||||
// @Router /api/v1/companies [post]
|
||||
// @Router /api/v1/companies [post]
|
||||
func (h *Handler) CreateCompany(w http.ResponseWriter, r *http.Request) {
|
||||
var req registerCompanyRequest
|
||||
if err := decodeJSON(r.Context(), r, &req); err != nil {
|
||||
|
|
@ -152,7 +151,6 @@ func (h *Handler) CreateCompany(w http.ResponseWriter, r *http.Request) {
|
|||
// @Produce json
|
||||
// @Success 200 {array} domain.Company
|
||||
// @Router /api/v1/companies [get]
|
||||
// @Router /api/v1/companies [get]
|
||||
func (h *Handler) ListCompanies(w http.ResponseWriter, r *http.Request) {
|
||||
companies, err := h.svc.ListCompanies(r.Context())
|
||||
if err != nil {
|
||||
|
|
@ -170,7 +168,6 @@ func (h *Handler) ListCompanies(w http.ResponseWriter, r *http.Request) {
|
|||
// @Success 200 {object} domain.Company
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/companies/{id} [get]
|
||||
// @Router /api/v1/companies/{id} [get]
|
||||
func (h *Handler) GetCompany(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -198,7 +195,6 @@ func (h *Handler) GetCompany(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/companies/{id} [patch]
|
||||
// @Router /api/v1/companies/{id} [patch]
|
||||
func (h *Handler) UpdateCompany(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -250,7 +246,6 @@ func (h *Handler) UpdateCompany(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/companies/{id} [delete]
|
||||
// @Router /api/v1/companies/{id} [delete]
|
||||
func (h *Handler) DeleteCompany(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -356,7 +351,6 @@ func (h *Handler) GetCompanyRating(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param product body registerProductRequest true "Produto"
|
||||
// @Success 201 {object} domain.Product
|
||||
// @Router /api/v1/products [post]
|
||||
// @Router /api/v1/products [post]
|
||||
func (h *Handler) CreateProduct(w http.ResponseWriter, r *http.Request) {
|
||||
var req registerProductRequest
|
||||
if err := decodeJSON(r.Context(), r, &req); err != nil {
|
||||
|
|
@ -388,7 +382,6 @@ func (h *Handler) CreateProduct(w http.ResponseWriter, r *http.Request) {
|
|||
// @Produce json
|
||||
// @Success 200 {array} domain.Product
|
||||
// @Router /api/v1/products [get]
|
||||
// @Router /api/v1/products [get]
|
||||
func (h *Handler) ListProducts(w http.ResponseWriter, r *http.Request) {
|
||||
products, err := h.svc.ListProducts(r.Context())
|
||||
if err != nil {
|
||||
|
|
@ -406,7 +399,6 @@ func (h *Handler) ListProducts(w http.ResponseWriter, r *http.Request) {
|
|||
// @Success 200 {object} domain.Product
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/products/{id} [get]
|
||||
// @Router /api/v1/products/{id} [get]
|
||||
func (h *Handler) GetProduct(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -434,7 +426,6 @@ func (h *Handler) GetProduct(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/products/{id} [patch]
|
||||
// @Router /api/v1/products/{id} [patch]
|
||||
func (h *Handler) UpdateProduct(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -492,7 +483,6 @@ func (h *Handler) UpdateProduct(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/products/{id} [delete]
|
||||
// @Router /api/v1/products/{id} [delete]
|
||||
func (h *Handler) DeleteProduct(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -578,7 +568,6 @@ func (h *Handler) AdjustInventory(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param order body createOrderRequest true "Pedido"
|
||||
// @Success 201 {object} domain.Order
|
||||
// @Router /api/v1/orders [post]
|
||||
// @Router /api/v1/orders [post]
|
||||
func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) {
|
||||
var req createOrderRequest
|
||||
if err := decodeJSON(r.Context(), r, &req); err != nil {
|
||||
|
|
@ -614,7 +603,6 @@ func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) {
|
|||
// @Produce json
|
||||
// @Success 200 {array} domain.Order
|
||||
// @Router /api/v1/orders [get]
|
||||
// @Router /api/v1/orders [get]
|
||||
func (h *Handler) ListOrders(w http.ResponseWriter, r *http.Request) {
|
||||
orders, err := h.svc.ListOrders(r.Context())
|
||||
if err != nil {
|
||||
|
|
@ -633,7 +621,6 @@ func (h *Handler) ListOrders(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param id path string true "Order ID"
|
||||
// @Success 200 {object} domain.Order
|
||||
// @Router /api/v1/orders/{id} [get]
|
||||
// @Router /api/v1/orders/{id} [get]
|
||||
func (h *Handler) GetOrder(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -660,7 +647,6 @@ func (h *Handler) GetOrder(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param status body updateStatusRequest true "Novo status"
|
||||
// @Success 204 ""
|
||||
// @Router /api/v1/orders/{id}/status [patch]
|
||||
// @Router /api/v1/orders/{id}/status [patch]
|
||||
func (h *Handler) UpdateOrderStatus(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -696,7 +682,6 @@ func (h *Handler) UpdateOrderStatus(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/orders/{id} [delete]
|
||||
// @Router /api/v1/orders/{id} [delete]
|
||||
func (h *Handler) DeleteOrder(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseUUIDFromPath(r.URL.Path)
|
||||
if err != nil {
|
||||
|
|
@ -840,7 +825,6 @@ func (h *Handler) DeleteCartItem(w http.ResponseWriter, r *http.Request) {
|
|||
// @Param id path string true "Order ID"
|
||||
// @Success 201 {object} domain.PaymentPreference
|
||||
// @Router /api/v1/orders/{id}/payment [post]
|
||||
// @Router /api/v1/orders/{id}/payment [post]
|
||||
func (h *Handler) CreatePaymentPreference(w http.ResponseWriter, r *http.Request) {
|
||||
if !strings.HasSuffix(r.URL.Path, "/payment") {
|
||||
http.NotFound(w, r)
|
||||
|
|
|
|||
340
backend/internal/http/handler/handler_test.go
Normal file
340
backend/internal/http/handler/handler_test.go
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid/v5"
|
||||
"github.com/saveinmed/backend-go/internal/domain"
|
||||
"github.com/saveinmed/backend-go/internal/usecase"
|
||||
)
|
||||
|
||||
// MockRepository implements the Repository interface for testing without database
|
||||
type MockRepository struct {
|
||||
companies []domain.Company
|
||||
products []domain.Product
|
||||
users []domain.User
|
||||
orders []domain.Order
|
||||
}
|
||||
|
||||
func NewMockRepository() *MockRepository {
|
||||
return &MockRepository{
|
||||
companies: make([]domain.Company, 0),
|
||||
products: make([]domain.Product, 0),
|
||||
users: make([]domain.User, 0),
|
||||
orders: make([]domain.Order, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Company methods
|
||||
func (m *MockRepository) CreateCompany(ctx context.Context, company *domain.Company) error {
|
||||
id, _ := uuid.NewV4()
|
||||
company.ID = id
|
||||
company.CreatedAt = time.Now()
|
||||
company.UpdatedAt = time.Now()
|
||||
m.companies = append(m.companies, *company)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListCompanies(ctx context.Context) ([]domain.Company, error) {
|
||||
return m.companies, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) {
|
||||
for _, c := range m.companies {
|
||||
if c.ID == id {
|
||||
return &c, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) UpdateCompany(ctx context.Context, company *domain.Company) error {
|
||||
for i, c := range m.companies {
|
||||
if c.ID == company.ID {
|
||||
m.companies[i] = *company
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) DeleteCompany(ctx context.Context, id uuid.UUID) error {
|
||||
for i, c := range m.companies {
|
||||
if c.ID == id {
|
||||
m.companies = append(m.companies[:i], m.companies[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Product methods
|
||||
func (m *MockRepository) CreateProduct(ctx context.Context, product *domain.Product) error {
|
||||
id, _ := uuid.NewV4()
|
||||
product.ID = id
|
||||
product.CreatedAt = time.Now()
|
||||
product.UpdatedAt = time.Now()
|
||||
m.products = append(m.products, *product)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListProducts(ctx context.Context) ([]domain.Product, error) {
|
||||
return m.products, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) {
|
||||
for _, p := range m.products {
|
||||
if p.ID == id {
|
||||
return &p, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) UpdateProduct(ctx context.Context, product *domain.Product) error {
|
||||
for i, p := range m.products {
|
||||
if p.ID == product.ID {
|
||||
m.products[i] = *product
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) DeleteProduct(ctx context.Context, id uuid.UUID) error {
|
||||
for i, p := range m.products {
|
||||
if p.ID == id {
|
||||
m.products = append(m.products[:i], m.products[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stub methods for other interfaces
|
||||
func (m *MockRepository) AdjustInventory(ctx context.Context, productID uuid.UUID, delta int64, reason string) (*domain.InventoryItem, error) {
|
||||
return &domain.InventoryItem{}, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) {
|
||||
return []domain.InventoryItem{}, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) CreateOrder(ctx context.Context, order *domain.Order) error {
|
||||
id, _ := uuid.NewV4()
|
||||
order.ID = id
|
||||
m.orders = append(m.orders, *order)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListOrders(ctx context.Context) ([]domain.Order, error) {
|
||||
return m.orders, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) {
|
||||
for _, o := range m.orders {
|
||||
if o.ID == id {
|
||||
return &o, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) UpdateOrderStatus(ctx context.Context, id uuid.UUID, status domain.OrderStatus) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) DeleteOrder(ctx context.Context, id uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) CreateShipment(ctx context.Context, shipment *domain.Shipment) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetShipmentByOrderID(ctx context.Context, orderID uuid.UUID) (*domain.Shipment, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) CreateUser(ctx context.Context, user *domain.User) error {
|
||||
id, _ := uuid.NewV4()
|
||||
user.ID = id
|
||||
m.users = append(m.users, *user)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListUsers(ctx context.Context, filter domain.UserFilter) ([]domain.User, int64, error) {
|
||||
return m.users, int64(len(m.users)), nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetUser(ctx context.Context, id uuid.UUID) (*domain.User, error) {
|
||||
for _, u := range m.users {
|
||||
if u.ID == id {
|
||||
return &u, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetUserByEmail(ctx context.Context, email string) (*domain.User, error) {
|
||||
for _, u := range m.users {
|
||||
if u.Email == email {
|
||||
return &u, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("user not found") // Simulate repository behavior
|
||||
}
|
||||
|
||||
func (m *MockRepository) UpdateUser(ctx context.Context, user *domain.User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) DeleteUser(ctx context.Context, id uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) AddCartItem(ctx context.Context, item *domain.CartItem) (*domain.CartItem, error) {
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) ListCartItems(ctx context.Context, buyerID uuid.UUID) ([]domain.CartItem, error) {
|
||||
return []domain.CartItem{}, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) DeleteCartItem(ctx context.Context, id uuid.UUID, buyerID uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) CreateReview(ctx context.Context, review *domain.Review) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetCompanyRating(ctx context.Context, companyID uuid.UUID) (*domain.CompanyRating, error) {
|
||||
return &domain.CompanyRating{}, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) SellerDashboard(ctx context.Context, sellerID uuid.UUID) (*domain.SellerDashboard, error) {
|
||||
return &domain.SellerDashboard{}, nil
|
||||
}
|
||||
|
||||
func (m *MockRepository) AdminDashboard(ctx context.Context, since time.Time) (*domain.AdminDashboard, error) {
|
||||
return &domain.AdminDashboard{}, nil
|
||||
}
|
||||
|
||||
// MockPaymentGateway implements the PaymentGateway interface for testing
|
||||
type MockPaymentGateway struct{}
|
||||
|
||||
func (m *MockPaymentGateway) CreatePreference(ctx context.Context, order *domain.Order) (*domain.PaymentPreference, error) {
|
||||
return &domain.PaymentPreference{}, nil
|
||||
}
|
||||
|
||||
func (m *MockPaymentGateway) ParseWebhook(ctx context.Context, payload []byte) (*domain.PaymentSplitResult, error) {
|
||||
return &domain.PaymentSplitResult{}, nil
|
||||
}
|
||||
|
||||
// Create a test handler for testing
|
||||
func newTestHandler() *Handler {
|
||||
repo := NewMockRepository()
|
||||
gateway := &MockPaymentGateway{}
|
||||
svc := usecase.NewService(repo, gateway, 0.05, "test-secret", time.Hour, "test-pepper")
|
||||
return New(svc)
|
||||
}
|
||||
|
||||
func TestListProducts(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/products", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.ListProducts(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
// Should return empty array
|
||||
body := strings.TrimSpace(rec.Body.String())
|
||||
if body != "[]" {
|
||||
t.Errorf("expected empty array, got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListCompanies(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/companies", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.ListCompanies(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCompany(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
payload := `{"role":"pharmacy","cnpj":"12345678901234","corporate_name":"Test Pharmacy","license_number":"LIC-001"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/companies", bytes.NewReader([]byte(payload)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.CreateCompany(rec, req)
|
||||
|
||||
if rec.Code != http.StatusCreated {
|
||||
t.Errorf("expected status %d, got %d: %s", http.StatusCreated, rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateProduct(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
sellerID, _ := uuid.NewV4()
|
||||
payload := `{"seller_id":"` + sellerID.String() + `","name":"Aspirin","description":"Pain relief","batch":"BATCH-001","expires_at":"2025-12-31T00:00:00Z","price_cents":1000,"stock":100}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/products", bytes.NewReader([]byte(payload)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.CreateProduct(rec, req)
|
||||
|
||||
if rec.Code != http.StatusCreated {
|
||||
t.Errorf("expected status %d, got %d: %s", http.StatusCreated, rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginInvalidCredentials(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
payload := `{"email":"nonexistent@test.com","password":"wrongpassword"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader([]byte(payload)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.Login(rec, req)
|
||||
|
||||
// Should fail because user doesn't exist
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListOrders(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/orders", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h.ListOrders(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
}
|
||||
143
backend/internal/server/server_test.go
Normal file
143
backend/internal/server/server_test.go
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/saveinmed/backend-go/internal/config"
|
||||
)
|
||||
|
||||
// TestServerHealthCheck tests the /health endpoint without a database
|
||||
func TestServerHealthCheck(t *testing.T) {
|
||||
// Create a simple handler to test health endpoint
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("ok"))
|
||||
})
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/health", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
mux.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
if rec.Body.String() != "ok" {
|
||||
t.Errorf("expected body 'ok', got '%s'", rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestServerRootEndpoint tests the root / endpoint
|
||||
func TestServerRootEndpoint(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response := `{"message":"💊 SaveInMed API is running!","docs":"/docs/index.html","health":"/health","version":"1.0.0"}`
|
||||
_, _ = w.Write([]byte(response))
|
||||
})
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
mux.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
body := rec.Body.String()
|
||||
if !strings.Contains(body, "SaveInMed API is running") {
|
||||
t.Errorf("expected body to contain 'SaveInMed API is running', got '%s'", body)
|
||||
}
|
||||
}
|
||||
|
||||
// TestServerCreationWithDatabase tests server creation with a real database
|
||||
// Skip this test if SKIP_DB_TEST environment variable is set
|
||||
func TestServerCreationWithDatabase(t *testing.T) {
|
||||
if os.Getenv("SKIP_DB_TEST") != "" {
|
||||
t.Skip("Skipping database tests")
|
||||
}
|
||||
|
||||
// Simple .env loader for testing purposes
|
||||
if content, err := os.ReadFile("../../.env"); err == nil {
|
||||
for _, line := range strings.Split(string(content), "\n") {
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
os.Setenv(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg := config.Load()
|
||||
|
||||
srv, err := New(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create server: %v", err)
|
||||
}
|
||||
|
||||
if srv == nil {
|
||||
t.Fatal("Server should not be nil")
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if srv.db != nil {
|
||||
srv.db.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// TestDatabaseConnectionAndPing tests the database connection and ping
|
||||
func TestDatabaseConnectionAndPing(t *testing.T) {
|
||||
if os.Getenv("SKIP_DB_TEST") != "" {
|
||||
t.Skip("Skipping database tests")
|
||||
}
|
||||
|
||||
// Simple .env loader for testing purposes
|
||||
if content, err := os.ReadFile("../../.env"); err == nil {
|
||||
for _, line := range strings.Split(string(content), "\n") {
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
os.Setenv(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg := config.Load()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
db, err := sqlx.ConnectContext(ctx, "pgx", cfg.DatabaseURL)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
t.Fatalf("Failed to ping database: %v", err)
|
||||
}
|
||||
|
||||
// Test a simple query
|
||||
var result int
|
||||
if err := db.QueryRowContext(ctx, "SELECT 1").Scan(&result); err != nil {
|
||||
t.Fatalf("Failed to execute query: %v", err)
|
||||
}
|
||||
|
||||
if result != 1 {
|
||||
t.Errorf("Expected 1, got %d", result)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue