package handlers import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func setupSupportTestRouter(t *testing.T) (*gin.Engine, *gorm.DB) { t.Helper() gin.SetMode(gin.TestMode) db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) // Create support_tickets table for SQLite require.NoError(t, db.Exec(` CREATE TABLE IF NOT EXISTS support_tickets ( id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), user_id TEXT, email TEXT NOT NULL, subject TEXT NOT NULL, message TEXT NOT NULL, category TEXT DEFAULT 'general', status TEXT DEFAULT 'open', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `).Error) router := gin.New() handler := NewSupportHandler(db, zap.NewNop()) router.POST("/api/v1/support/tickets", handler.SubmitTicket) return router, db } func TestSupportHandler_SubmitTicket_Success(t *testing.T) { router, db := setupSupportTestRouter(t) body, _ := json.Marshal(map[string]string{ "email": "user@example.com", "subject": "Payment issue", "message": "I have a problem with my payment for order #123. Please help.", "category": "payment", }) req := httptest.NewRequest(http.MethodPost, "/api/v1/support/tickets", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) var resp map[string]interface{} require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) data := resp["data"].(map[string]interface{}) assert.NotEmpty(t, data["ticket_id"]) assert.Contains(t, data["message"], "submitted") // Verify in DB var count int64 db.Table("support_tickets").Count(&count) assert.Equal(t, int64(1), count) } func TestSupportHandler_SubmitTicket_MissingFields(t *testing.T) { router, _ := setupSupportTestRouter(t) body, _ := json.Marshal(map[string]string{ "email": "user@example.com", // Missing subject and message }) req := httptest.NewRequest(http.MethodPost, "/api/v1/support/tickets", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.NotEqual(t, http.StatusCreated, w.Code) } func TestSupportHandler_SubmitTicket_InvalidEmail(t *testing.T) { router, _ := setupSupportTestRouter(t) body, _ := json.Marshal(map[string]string{ "email": "not-an-email", "subject": "Test subject", "message": "This is a test message with enough characters.", }) req := httptest.NewRequest(http.MethodPost, "/api/v1/support/tickets", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.NotEqual(t, http.StatusCreated, w.Code) } func TestSupportHandler_SubmitTicket_DefaultCategory(t *testing.T) { router, db := setupSupportTestRouter(t) body, _ := json.Marshal(map[string]string{ "email": "user@example.com", "subject": "General question", "message": "I have a question about the platform features.", }) req := httptest.NewRequest(http.MethodPost, "/api/v1/support/tickets", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) // Verify default category var ticket SupportTicket db.Table("support_tickets").First(&ticket) assert.Equal(t, "general", ticket.Category) }