package integration import ( "bytes" "encoding/json" "fmt" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" ) // Integration Test Suite type IntegrationTestSuite struct { suite.Suite baseURL string httpClient *http.Client authToken string testUserID string } func (suite *IntegrationTestSuite) SetupSuite() { // Configuration for integration tests suite.baseURL = "http://localhost:8080" suite.httpClient = &http.Client{ Timeout: 30 * time.Second, } // Wait for the application to be ready suite.waitForApplication() } func (suite *IntegrationTestSuite) TearDownSuite() { // Cleanup if needed } func (suite *IntegrationTestSuite) waitForApplication() { maxAttempts := 30 attempt := 0 for attempt < maxAttempts { resp, err := suite.httpClient.Get(suite.baseURL + "/health") if err == nil && resp.StatusCode == http.StatusOK { resp.Body.Close() return } if resp != nil { resp.Body.Close() } attempt++ time.Sleep(2 * time.Second) } suite.T().Fatal("Application not ready after timeout") } func (suite *IntegrationTestSuite) makeRequest(method, endpoint string, body interface{}, headers map[string]string) (*http.Response, error) { var reqBody *bytes.Buffer if body != nil { jsonBody, err := json.Marshal(body) if err != nil { return nil, err } reqBody = bytes.NewBuffer(jsonBody) } else { reqBody = bytes.NewBuffer(nil) } req, err := http.NewRequest(method, suite.baseURL+endpoint, reqBody) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") if suite.authToken != "" { req.Header.Set("Authorization", "Bearer "+suite.authToken) } for key, value := range headers { req.Header.Set(key, value) } return suite.httpClient.Do(req) } func (suite *IntegrationTestSuite) TestApplicationHealth() { resp, err := suite.makeRequest("GET", "/health", nil, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) var health map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&health) resp.Body.Close() suite.NoError(err) suite.Equal("healthy", health["status"]) } func (suite *IntegrationTestSuite) TestUserRegistrationAndLogin() { // Test user registration userData := map[string]interface{}{ "email": "testuser@example.com", "first_name": "Test", "last_name": "User", "password": "testpassword123", } resp, err := suite.makeRequest("POST", "/api/v1/register", userData, nil) suite.NoError(err) suite.Equal(http.StatusCreated, resp.StatusCode) var registerResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(®isterResponse) resp.Body.Close() suite.NoError(err) suite.Equal("User created successfully", registerResponse["message"]) // Test user login loginData := map[string]interface{}{ "email": "testuser@example.com", "password": "testpassword123", } resp, err = suite.makeRequest("POST", "/api/v1/login", loginData, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) var loginResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&loginResponse) resp.Body.Close() suite.NoError(err) suite.NotEmpty(loginResponse["token"]) suite.authToken = loginResponse["token"].(string) } func (suite *IntegrationTestSuite) TestProtectedEndpoints() { // First, login to get auth token suite.TestUserRegistrationAndLogin() // Test getting user profile resp, err := suite.makeRequest("GET", "/api/v1/profile", nil, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) var profileResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&profileResponse) resp.Body.Close() suite.NoError(err) suite.NotNil(profileResponse["user"]) user := profileResponse["user"].(map[string]interface{}) suite.Equal("testuser@example.com", user["email"]) suite.Equal("Test", user["first_name"]) suite.Equal("User", user["last_name"]) } func (suite *IntegrationTestSuite) TestPricingEndpoint() { resp, err := suite.makeRequest("GET", "/api/v1/pricing", nil, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) var pricingResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&pricingResponse) resp.Body.Close() suite.NoError(err) suite.NotNil(pricingResponse["plans"]) plans := pricingResponse["plans"].([]interface{}) suite.Len(plans, 1) plan := plans[0].(map[string]interface{}) suite.Equal("Sovereign Hosting", plan["name"]) suite.Equal(float64(25000), plan["price"]) // $250.00 in cents suite.Equal("usd", plan["currency"]) } func (suite *IntegrationTestSuite) TestCheckoutSession() { // Test creating a checkout session checkoutData := map[string]interface{}{ "domain_name": "testdomain.com", "email": "customer@example.com", } resp, err := suite.makeRequest("POST", "/api/v1/checkout", checkoutData, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) var checkoutResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&checkoutResponse) resp.Body.Close() suite.NoError(err) suite.NotNil(checkoutResponse["checkout_url"]) suite.Contains(checkoutResponse["checkout_url"].(string), "checkout.stripe.com") } func (suite *IntegrationTestSuite) TestErrorHandling() { // Test invalid registration data invalidUserData := map[string]interface{}{ "email": "invalid-email", "first_name": "", "last_name": "", "password": "123", // Too short } resp, err := suite.makeRequest("POST", "/api/v1/register", invalidUserData, nil) suite.NoError(err) suite.Equal(http.StatusBadRequest, resp.StatusCode) var errorResponse map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&errorResponse) resp.Body.Close() suite.NoError(err) suite.NotNil(errorResponse["error"]) // Test invalid login credentials invalidLoginData := map[string]interface{}{ "email": "nonexistent@example.com", "password": "wrongpassword", } resp, err = suite.makeRequest("POST", "/api/v1/login", invalidLoginData, nil) suite.NoError(err) suite.Equal(http.StatusUnauthorized, resp.StatusCode) // Test protected endpoint without auth resp, err = suite.makeRequest("GET", "/api/v1/profile", nil, nil) suite.NoError(err) suite.Equal(http.StatusUnauthorized, resp.StatusCode) } func (suite *IntegrationTestSuite) TestRateLimiting() { // This test would require configuring rate limits for testing // For now, we'll just make multiple requests to ensure basic functionality for i := 0; i < 5; i++ { resp, err := suite.makeRequest("GET", "/api/v1/pricing", nil, nil) suite.NoError(err) suite.Equal(http.StatusOK, resp.StatusCode) resp.Body.Close() } } func (suite *IntegrationTestSuite) TestCORSEnabled() { // Test CORS headers headers := map[string]string{ "Origin": "http://localhost:3000", } resp, err := suite.makeRequest("OPTIONS", "/api/v1/pricing", nil, headers) suite.NoError(err) suite.True(resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNoContent) // Check CORS headers assert.Equal(suite.T(), "http://localhost:3000", resp.Header.Get("Access-Control-Allow-Origin")) assert.Contains(suite.T(), resp.Header.Get("Access-Control-Allow-Methods"), "GET") assert.Contains(suite.T(), resp.Header.Get("Access-Control-Allow-Headers"), "Content-Type") resp.Body.Close() } // Run the integration test suite func TestIntegrationSuite(t *testing.T) { if testing.Short() { t.Skip("Skipping integration tests in short mode") } suite.Run(t, new(IntegrationTestSuite)) }