340 lines
9.2 KiB
Go
340 lines
9.2 KiB
Go
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)
|
|
}
|
|
}
|