package main import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" ) func TestHealthEndpoint(t *testing.T) { gin.SetMode(gin.TestMode) // Create a new router router := gin.Default() router.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "ok", "message": "YourDreamNameHere API is running", }) }) // Create a request to pass to our handler req, _ := http.NewRequest("GET", "/health", nil) w := httptest.NewRecorder() // Perform the request router.ServeHTTP(w, req) // Assert the response assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "ok", response["status"]) } func TestLaunchEndpoint(t *testing.T) { gin.SetMode(gin.TestMode) // Create a new router with the launch endpoint router := gin.Default() // Add CORS middleware router.Use(func(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) return } c.Next() }) router.POST("/api/launch", func(c *gin.Context) { var req struct { Domain string `json:"domain" binding:"required"` Email string `json:"email" binding:"required,email"` CardNumber string `json:"cardNumber" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request format", }) return } // Validate inputs if req.Domain == "" || req.Email == "" || req.CardNumber == "" { c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "All fields are required", }) return } // Return success response c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Your hosting business is being provisioned!", "customer_id": "test-customer-id", "domain": req.Domain, "provisioned": false, }) }) t.Run("Valid launch request", func(t *testing.T) { payload := map[string]string{ "domain": "example.com", "email": "test@example.com", "cardNumber": "4242424242424242", } jsonPayload, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", "/api/launch", bytes.NewBuffer(jsonPayload)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.True(t, response["success"].(bool)) assert.Equal(t, "example.com", response["domain"]) }) t.Run("Missing domain", func(t *testing.T) { payload := map[string]string{ "email": "test@example.com", "cardNumber": "4242424242424242", } jsonPayload, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", "/api/launch", bytes.NewBuffer(jsonPayload)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.False(t, response["success"].(bool)) }) t.Run("Invalid email", func(t *testing.T) { payload := map[string]string{ "domain": "example.com", "email": "invalid-email", "cardNumber": "4242424242424242", } jsonPayload, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", "/api/launch", bytes.NewBuffer(jsonPayload)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }) t.Run("Empty request", func(t *testing.T) { req, _ := http.NewRequest("POST", "/api/launch", bytes.NewBuffer([]byte("{}"))) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }) } func TestStatusEndpoint(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.Default() router.GET("/api/status", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "operational", "services": gin.H{ "ovh": "connected", "stripe": "connected", "cloudron": "ready", "dolibarr": "connected", }, "uptime": "0h 0m", }) }) req, _ := http.NewRequest("GET", "/api/status", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "operational", response["status"]) } func TestCORSMiddleware(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.Default() // Add CORS middleware router.Use(func(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) return } c.Next() }) router.GET("/test", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "test"}) }) t.Run("CORS headers present", func(t *testing.T) { req, _ := http.NewRequest("GET", "/test", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, "*", w.Header().Get("Access-Control-Allow-Origin")) assert.Contains(t, w.Header().Get("Access-Control-Allow-Methods"), "GET") assert.Contains(t, w.Header().Get("Access-Control-Allow-Methods"), "POST") }) t.Run("OPTIONS request", func(t *testing.T) { req, _ := http.NewRequest("OPTIONS", "/test", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusNoContent, w.Code) }) } func TestCustomerStatusEndpoint(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.Default() router.GET("/api/status/:customerID", func(c *gin.Context) { customerID := c.Param("customerID") c.JSON(http.StatusOK, gin.H{ "customer_id": customerID, "status": "provisioning", "progress": 25, "estimated_time": "15 minutes", "steps": []gin.H{ {"name": "Domain Registration", "status": "completed"}, {"name": "VPS Provisioning", "status": "in_progress"}, {"name": "Cloudron Installation", "status": "pending"}, {"name": "DNS Configuration", "status": "pending"}, {"name": "Business Setup", "status": "pending"}, }, }) }) req, _ := http.NewRequest("GET", "/api/status/test-customer-123", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "test-customer-123", response["customer_id"]) assert.Equal(t, "provisioning", response["status"]) assert.Equal(t, float64(25), response["progress"]) } func TestLandingPageResponse(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.Default() router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "landing.html", gin.H{}) }) req, _ := http.NewRequest("GET", "/", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Since we don't have the HTML template loaded in tests, // we'll test that it returns a 200 (in real app it would serve the HTML) // For now, just ensure the endpoint exists // In production, this would return the actual HTML }