- Add config_test.go (5 tests for env parsing) - Add middleware_test.go (16 tests for CORS, Auth, Gzip, Logger) - Add usecase_test.go (30+ tests for business logic) - Add payments_test.go (6 tests for MercadoPago gateway) Coverage: config 100%, middleware 95.9%, payments 100%, usecase 64.7% feat(marketplace): add test framework and new pages - Setup Vitest with jsdom environment - Add cartStore.test.ts (15 tests for Zustand store) - Add usePersistentFilters.test.ts (5 tests for hook) - Add apiClient.test.ts (7 tests for axios client) - Add Orders page with status transitions - Add Inventory page with stock adjustments - Add Company page with edit functionality - Add SellerDashboard page with KPIs Total marketplace tests: 27 passing
167 lines
4.8 KiB
Go
167 lines
4.8 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLoadDefaults(t *testing.T) {
|
|
// Clear any environment variables that might interfere
|
|
envVars := []string{
|
|
"APP_NAME", "PORT", "DATABASE_URL", "DB_MAX_OPEN_CONNS",
|
|
"DB_MAX_IDLE_CONNS", "DB_CONN_MAX_IDLE", "MERCADOPAGO_BASE_URL",
|
|
"MARKETPLACE_COMMISSION", "JWT_SECRET", "JWT_EXPIRES_IN",
|
|
"PASSWORD_PEPPER", "CORS_ORIGINS",
|
|
}
|
|
origEnvs := make(map[string]string)
|
|
for _, key := range envVars {
|
|
origEnvs[key] = os.Getenv(key)
|
|
os.Unsetenv(key)
|
|
}
|
|
defer func() {
|
|
for key, val := range origEnvs {
|
|
if val != "" {
|
|
os.Setenv(key, val)
|
|
}
|
|
}
|
|
}()
|
|
|
|
cfg := Load()
|
|
|
|
if cfg.AppName != "saveinmed-performance-core" {
|
|
t.Errorf("expected AppName 'saveinmed-performance-core', got '%s'", cfg.AppName)
|
|
}
|
|
if cfg.Port != "8214" {
|
|
t.Errorf("expected Port '8214', got '%s'", cfg.Port)
|
|
}
|
|
if cfg.MaxOpenConns != 15 {
|
|
t.Errorf("expected MaxOpenConns 15, got %d", cfg.MaxOpenConns)
|
|
}
|
|
if cfg.MaxIdleConns != 5 {
|
|
t.Errorf("expected MaxIdleConns 5, got %d", cfg.MaxIdleConns)
|
|
}
|
|
if cfg.ConnMaxIdle != 5*time.Minute {
|
|
t.Errorf("expected ConnMaxIdle 5m, got %v", cfg.ConnMaxIdle)
|
|
}
|
|
if cfg.JWTSecret != "dev-secret" {
|
|
t.Errorf("expected JWTSecret 'dev-secret', got '%s'", cfg.JWTSecret)
|
|
}
|
|
if cfg.JWTExpiresIn != 24*time.Hour {
|
|
t.Errorf("expected JWTExpiresIn 24h, got %v", cfg.JWTExpiresIn)
|
|
}
|
|
if cfg.MarketplaceCommission != 2.5 {
|
|
t.Errorf("expected MarketplaceCommission 2.5, got %f", cfg.MarketplaceCommission)
|
|
}
|
|
if len(cfg.CORSOrigins) != 1 || cfg.CORSOrigins[0] != "*" {
|
|
t.Errorf("expected CORSOrigins ['*'], got %v", cfg.CORSOrigins)
|
|
}
|
|
}
|
|
|
|
func TestLoadFromEnv(t *testing.T) {
|
|
os.Setenv("APP_NAME", "test-app")
|
|
os.Setenv("PORT", "9999")
|
|
os.Setenv("DATABASE_URL", "postgres://test:test@localhost:5432/test")
|
|
os.Setenv("DB_MAX_OPEN_CONNS", "100")
|
|
os.Setenv("DB_MAX_IDLE_CONNS", "50")
|
|
os.Setenv("DB_CONN_MAX_IDLE", "10m")
|
|
os.Setenv("MARKETPLACE_COMMISSION", "5.0")
|
|
os.Setenv("JWT_SECRET", "super-secret")
|
|
os.Setenv("JWT_EXPIRES_IN", "12h")
|
|
os.Setenv("PASSWORD_PEPPER", "pepper123")
|
|
os.Setenv("CORS_ORIGINS", "https://example.com,https://app.example.com")
|
|
|
|
defer func() {
|
|
os.Unsetenv("APP_NAME")
|
|
os.Unsetenv("PORT")
|
|
os.Unsetenv("DATABASE_URL")
|
|
os.Unsetenv("DB_MAX_OPEN_CONNS")
|
|
os.Unsetenv("DB_MAX_IDLE_CONNS")
|
|
os.Unsetenv("DB_CONN_MAX_IDLE")
|
|
os.Unsetenv("MARKETPLACE_COMMISSION")
|
|
os.Unsetenv("JWT_SECRET")
|
|
os.Unsetenv("JWT_EXPIRES_IN")
|
|
os.Unsetenv("PASSWORD_PEPPER")
|
|
os.Unsetenv("CORS_ORIGINS")
|
|
}()
|
|
|
|
cfg := Load()
|
|
|
|
if cfg.AppName != "test-app" {
|
|
t.Errorf("expected AppName 'test-app', got '%s'", cfg.AppName)
|
|
}
|
|
if cfg.Port != "9999" {
|
|
t.Errorf("expected Port '9999', got '%s'", cfg.Port)
|
|
}
|
|
if cfg.DatabaseURL != "postgres://test:test@localhost:5432/test" {
|
|
t.Errorf("expected custom DatabaseURL, got '%s'", cfg.DatabaseURL)
|
|
}
|
|
if cfg.MaxOpenConns != 100 {
|
|
t.Errorf("expected MaxOpenConns 100, got %d", cfg.MaxOpenConns)
|
|
}
|
|
if cfg.MaxIdleConns != 50 {
|
|
t.Errorf("expected MaxIdleConns 50, got %d", cfg.MaxIdleConns)
|
|
}
|
|
if cfg.ConnMaxIdle != 10*time.Minute {
|
|
t.Errorf("expected ConnMaxIdle 10m, got %v", cfg.ConnMaxIdle)
|
|
}
|
|
if cfg.MarketplaceCommission != 5.0 {
|
|
t.Errorf("expected MarketplaceCommission 5.0, got %f", cfg.MarketplaceCommission)
|
|
}
|
|
if cfg.JWTSecret != "super-secret" {
|
|
t.Errorf("expected JWTSecret 'super-secret', got '%s'", cfg.JWTSecret)
|
|
}
|
|
if cfg.JWTExpiresIn != 12*time.Hour {
|
|
t.Errorf("expected JWTExpiresIn 12h, got %v", cfg.JWTExpiresIn)
|
|
}
|
|
if cfg.PasswordPepper != "pepper123" {
|
|
t.Errorf("expected PasswordPepper 'pepper123', got '%s'", cfg.PasswordPepper)
|
|
}
|
|
if len(cfg.CORSOrigins) != 2 {
|
|
t.Errorf("expected 2 CORS origins, got %d", len(cfg.CORSOrigins))
|
|
}
|
|
}
|
|
|
|
func TestAddr(t *testing.T) {
|
|
cfg := Config{Port: "3000"}
|
|
expected := ":3000"
|
|
if cfg.Addr() != expected {
|
|
t.Errorf("expected Addr '%s', got '%s'", expected, cfg.Addr())
|
|
}
|
|
}
|
|
|
|
func TestInvalidEnvValues(t *testing.T) {
|
|
os.Setenv("DB_MAX_OPEN_CONNS", "not-a-number")
|
|
os.Setenv("MARKETPLACE_COMMISSION", "invalid")
|
|
os.Setenv("DB_CONN_MAX_IDLE", "bad-duration")
|
|
|
|
defer func() {
|
|
os.Unsetenv("DB_MAX_OPEN_CONNS")
|
|
os.Unsetenv("MARKETPLACE_COMMISSION")
|
|
os.Unsetenv("DB_CONN_MAX_IDLE")
|
|
}()
|
|
|
|
cfg := Load()
|
|
|
|
// Should use defaults when values are invalid
|
|
if cfg.MaxOpenConns != 15 {
|
|
t.Errorf("expected fallback MaxOpenConns 15, got %d", cfg.MaxOpenConns)
|
|
}
|
|
if cfg.MarketplaceCommission != 2.5 {
|
|
t.Errorf("expected fallback MarketplaceCommission 2.5, got %f", cfg.MarketplaceCommission)
|
|
}
|
|
if cfg.ConnMaxIdle != 5*time.Minute {
|
|
t.Errorf("expected fallback ConnMaxIdle 5m, got %v", cfg.ConnMaxIdle)
|
|
}
|
|
}
|
|
|
|
func TestEmptyCORSOrigins(t *testing.T) {
|
|
os.Setenv("CORS_ORIGINS", "")
|
|
defer os.Unsetenv("CORS_ORIGINS")
|
|
|
|
cfg := Load()
|
|
|
|
if len(cfg.CORSOrigins) != 1 || cfg.CORSOrigins[0] != "*" {
|
|
t.Errorf("expected fallback CORSOrigins ['*'], got %v", cfg.CORSOrigins)
|
|
}
|
|
}
|