package router import ( "bytes" "log" "net/http/httptest" "strings" "testing" "affiliate_dash/internal/handler" "affiliate_dash/internal/pkg/applog" "affiliate_dash/internal/pkg/jwt" "affiliate_dash/internal/pkg/openlog" "affiliate_dash/internal/service" "affiliate_dash/internal/testdb" "github.com/gin-gonic/gin" ) func TestSetupDoesNotPanic(t *testing.T) { gin.SetMode(gin.TestMode) db := testdb.New(t) codec, err := service.NewSecretCodec("test-master-key") if err != nil { t.Fatalf("codec: %v", err) } tenantSvc := service.NewTenantService(db) authSvc := service.NewAuthService(db, jwt.NewManager("test-jwt"), tenantSvc) userSvc := service.NewUserService(db, tenantSvc) callbackSvc := service.NewCallbackService(db, codec) fulfillmentSvc := service.NewFulfillmentService(db, callbackSvc) merchantSvc := service.NewMerchantService(db, codec, tenantSvc) rechargeSvc := service.NewRechargeService(db, fulfillmentSvc, "") deliverySvc := service.NewDeliveryService(fulfillmentSvc, "", "", "", "", 0) defer func() { if recovered := recover(); recovered != nil { t.Fatalf("setup should not panic: %v", recovered) } }() _ = Setup(&Handlers{ Auth: handler.NewAuthHandler(authSvc), Dashboard: handler.NewDashboardHandler(fulfillmentSvc), User: handler.NewUserHandler(userSvc), Open: handler.NewOpenV1Handler(merchantSvc, fulfillmentSvc, deliverySvc), SourceOpen: handler.NewOpenHandler(fulfillmentSvc), Merchant: handler.NewMerchantHandler(merchantSvc, fulfillmentSvc, callbackSvc, deliverySvc, rechargeSvc), Recharge: handler.NewRechargeHandler(rechargeSvc), JWT: jwt.NewManager("test-jwt"), Tenant: tenantSvc, OpenDB: db, SecretCodec: codec, OpenAPIKey: "source-key", OpenAPISecret: "source-secret", OpenSignSkew: 300, }) } func TestIsPollingEndpoint(t *testing.T) { tests := []struct { method string path string expected bool }{ {"GET", "/health", true}, {"GET", "/api/delivery/v1/orders/FO123/bind-result", true}, {"GET", "/api/delivery/v1/orders/FO123", true}, {"GET", "/api/client/v1/orders/FO123", true}, {"GET", "/api/client/v1/wallet", true}, {"GET", "/api/open/v1/orders/FO123", true}, {"POST", "/api/client/v1/orders", false}, {"POST", "/api/delivery/v1/orders/FO123/submit", false}, {"POST", "/api/client/v1/orders/FO123/cancel", false}, {"GET", "/api/dashboard", false}, } for _, tc := range tests { got := isPollingEndpoint(tc.method, tc.path) if got != tc.expected { t.Errorf("isPollingEndpoint(%s, %s) = %v, expected %v", tc.method, tc.path, got, tc.expected) } } } func TestRequestLoggerGeneratesAndPassesReqID(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(requestLogger()) r.GET("/test", func(c *gin.Context) { reqID := openlog.GetReqID(c) if reqID == "" || reqID == "-" { t.Errorf("expected req_id in context, got empty") } c.String(200, "ok") }) req := httptest.NewRequest("GET", "/test", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) respReqID := w.Header().Get("X-Request-ID") if respReqID == "" { t.Errorf("expected X-Request-ID in response header") } } func TestRequestLoggerSuppressesPollingOnInfo(t *testing.T) { gin.SetMode(gin.TestMode) var buf bytes.Buffer log.SetOutput(&buf) defer log.SetOutput(log.Writer()) applog.SetLevel("info") r := gin.New() r.Use(requestLogger()) r.GET("/health", func(c *gin.Context) { c.String(200, "ok") }) r.GET("/api/client/v1/orders/:id", func(c *gin.Context) { c.String(200, "ok") }) // 1. In INFO level, polling requests with 200 should be silenced buf.Reset() req := httptest.NewRequest("GET", "/health", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if buf.Len() > 0 { t.Errorf("expected /health 200 to be silenced in INFO mode, got: %s", buf.String()) } buf.Reset() req = httptest.NewRequest("GET", "/api/client/v1/orders/FO12345", nil) w = httptest.NewRecorder() r.ServeHTTP(w, req) if buf.Len() > 0 { t.Errorf("expected GET order 200 to be silenced in INFO mode, got: %s", buf.String()) } // 2. In DEBUG level, polling requests should appear as [DEBUG] applog.SetLevel("debug") buf.Reset() req = httptest.NewRequest("GET", "/api/client/v1/orders/FO12345", nil) w = httptest.NewRecorder() r.ServeHTTP(w, req) if !strings.Contains(buf.String(), "[DEBUG] [HTTP] 200 GET /api/client/v1/orders/FO12345") { t.Errorf("expected GET order to appear as [DEBUG] in DEBUG mode, got: %s", buf.String()) } }