veza/veza-backend-api/internal/handlers/support_handler_test.go
senke 2281c91e8b feat(v0.13.5): polish marketplace & compliance — KYC, support, payout E2E
- Seller KYC via Stripe Identity (start verification, status check, webhook)
- Support ticket system (backend handler + frontend form page)
- E2E payout flow integration test (sale → payment → balance → payout)
- Migrations: seller_kyc columns, support_tickets table
- Frontend: SupportPage with SUMI design, lazy loading, routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:57:19 +01:00

128 lines
3.5 KiB
Go

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)
}