- Add Go modules with required dependencies (Gin, UUID, JWT, etc.) - Implement main web server with landing page endpoint - Add comprehensive API endpoints for health and status - Include proper error handling and request validation - Set up CORS middleware and security headers
294 lines
7.7 KiB
Go
294 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestDomainValidation(t *testing.T) {
|
|
tests := []struct {
|
|
domain string
|
|
valid bool
|
|
reason string
|
|
}{
|
|
{"example.com", true, "Valid domain"},
|
|
{"sub.example.com", true, "Valid subdomain"},
|
|
{"test.co.uk", true, "Valid domain with multiple TLDs"},
|
|
{"", false, "Empty domain"},
|
|
{"invalid", false, "No TLD"},
|
|
{".com", false, "Starts with dot"},
|
|
{"com.", false, "Ends with dot"},
|
|
{"..double.com", false, "Double dots"},
|
|
{"toolong" + string(make([]byte, 300)) + ".com", false, "Too long domain"},
|
|
{"valid-domain.com", true, "Valid domain with hyphen"},
|
|
{"-invalid.com", false, "Starts with hyphen"},
|
|
{"invalid-.com", false, "Ends with hyphen"},
|
|
{"valid123.com", true, "Valid domain with numbers"},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.reason, func(t *testing.T) {
|
|
// Simple domain validation logic
|
|
valid := isValidDomain(test.domain)
|
|
assert.Equal(t, test.valid, valid, "Domain: %s", test.domain)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEmailValidation(t *testing.T) {
|
|
tests := []struct {
|
|
email string
|
|
valid bool
|
|
reason string
|
|
}{
|
|
{"test@example.com", true, "Valid email"},
|
|
{"user.name@domain.co.uk", true, "Valid email with subdomain"},
|
|
{"user+tag@example.org", true, "Valid email with plus tag"},
|
|
{"", false, "Empty email"},
|
|
{"invalid", false, "No @ symbol"},
|
|
{"@domain.com", false, "No local part"},
|
|
{"user@", false, "No domain part"},
|
|
{"user..name@example.com", false, "Double dots in local part"},
|
|
{"user@.com", false, "Domain starts with dot"},
|
|
{"user@com.", false, "Domain ends with dot"},
|
|
{"user@toolong" + string(make([]byte, 300)) + ".com", false, "Too long email"},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.reason, func(t *testing.T) {
|
|
// Simple email validation logic
|
|
valid := isValidEmail(test.email)
|
|
assert.Equal(t, test.valid, valid, "Email: %s", test.email)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCreditCardValidation(t *testing.T) {
|
|
tests := []struct {
|
|
cardNumber string
|
|
valid bool
|
|
reason string
|
|
}{
|
|
{"4242424242424242", true, "Valid Visa test card"},
|
|
{"5555555555554444", true, "Valid Mastercard test card"},
|
|
{"378282246310005", true, "Valid Amex test card"},
|
|
{"", false, "Empty card number"},
|
|
{"4111", false, "Too short"},
|
|
{"42424242424242424242", false, "Too long"},
|
|
{"abcdabcdabcdabcd", false, "Non-numeric"},
|
|
{"4242-4242-4242-4242", false, "Contains dashes"},
|
|
{"4242 4242 4242 4242", false, "Contains spaces"},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.reason, func(t *testing.T) {
|
|
// Simple credit card validation logic
|
|
valid := isValidCreditCard(test.cardNumber)
|
|
assert.Equal(t, test.valid, valid, "Card: %s", test.cardNumber)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBusinessLogic(t *testing.T) {
|
|
t.Run("Customer ID generation", func(t *testing.T) {
|
|
// Test that customer IDs are unique
|
|
id1 := generateCustomerID()
|
|
id2 := generateCustomerID()
|
|
|
|
assert.NotEmpty(t, id1)
|
|
assert.NotEmpty(t, id2)
|
|
assert.NotEqual(t, id1, id2)
|
|
})
|
|
|
|
t.Run("Pricing calculation", func(t *testing.T) {
|
|
// Test pricing logic
|
|
assert.Equal(t, 250.0, calculateMonthlyPrice())
|
|
assert.Equal(t, 3000.0, calculateYearlyPrice())
|
|
})
|
|
|
|
t.Run("Provisioning steps", func(t *testing.T) {
|
|
// Test provisioning workflow
|
|
steps := getProvisioningSteps()
|
|
|
|
expectedSteps := []string{
|
|
"Domain Registration",
|
|
"VPS Provisioning",
|
|
"Cloudron Installation",
|
|
"DNS Configuration",
|
|
"Business Setup",
|
|
}
|
|
|
|
assert.Equal(t, len(expectedSteps), len(steps))
|
|
|
|
for i, expected := range expectedSteps {
|
|
assert.Equal(t, expected, steps[i].Name)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestProvisioningProgress(t *testing.T) {
|
|
t.Run("Initial progress", func(t *testing.T) {
|
|
progress := calculateProgress(0) // No steps completed
|
|
assert.Equal(t, 0, progress)
|
|
})
|
|
|
|
t.Run("Partial progress", func(t *testing.T) {
|
|
progress := calculateProgress(2) // 2 of 5 steps completed
|
|
assert.Equal(t, 40, progress)
|
|
})
|
|
|
|
t.Run("Complete progress", func(t *testing.T) {
|
|
progress := calculateProgress(5) // All 5 steps completed
|
|
assert.Equal(t, 100, progress)
|
|
})
|
|
|
|
t.Run("Invalid progress", func(t *testing.T) {
|
|
progress := calculateProgress(10) // More than total steps
|
|
assert.Equal(t, 100, progress) // Should cap at 100
|
|
})
|
|
}
|
|
|
|
func TestErrorHandling(t *testing.T) {
|
|
t.Run("Empty request validation", func(t *testing.T) {
|
|
err := validateLaunchRequest("", "", "")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "required")
|
|
})
|
|
|
|
t.Run("Valid request", func(t *testing.T) {
|
|
err := validateLaunchRequest("example.com", "test@example.com", "4242424242424242")
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Invalid domain", func(t *testing.T) {
|
|
err := validateLaunchRequest("invalid", "test@example.com", "4242424242424242")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Invalid email", func(t *testing.T) {
|
|
err := validateLaunchRequest("example.com", "invalid", "4242424242424242")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Invalid card", func(t *testing.T) {
|
|
err := validateLaunchRequest("example.com", "test@example.com", "invalid")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
// Helper functions for testing
|
|
|
|
func isValidDomain(domain string) bool {
|
|
if domain == "" || len(domain) > 253 {
|
|
return false
|
|
}
|
|
// Simple validation - in production, use more robust validation
|
|
return len(domain) > 3 && contains(domain, ".")
|
|
}
|
|
|
|
func isValidEmail(email string) bool {
|
|
if email == "" || len(email) > 254 {
|
|
return false
|
|
}
|
|
// Simple validation - in production, use more robust validation
|
|
return contains(email, "@") && contains(email, ".")
|
|
}
|
|
|
|
func isValidCreditCard(cardNumber string) bool {
|
|
if cardNumber == "" {
|
|
return false
|
|
}
|
|
// Simple validation - in production, use Luhn algorithm and proper card validation
|
|
return len(cardNumber) >= 13 && len(cardNumber) <= 19 && isNumeric(cardNumber)
|
|
}
|
|
|
|
func contains(s, substr string) bool {
|
|
return len(s) >= len(substr) && s[len(s)-len(substr):] == substr ||
|
|
(len(s) > len(substr) && s[:len(substr)] == substr) ||
|
|
(len(s) > len(substr) && findInString(s, substr))
|
|
}
|
|
|
|
func findInString(s, substr string) bool {
|
|
for i := 0; i <= len(s)-len(substr); i++ {
|
|
if s[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isNumeric(s string) bool {
|
|
for _, c := range s {
|
|
if c < '0' || c > '9' {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func generateCustomerID() string {
|
|
// Mock implementation
|
|
return "cust_" + string(rune(len("test") * 1000))
|
|
}
|
|
|
|
func calculateMonthlyPrice() float64 {
|
|
return 250.0
|
|
}
|
|
|
|
func calculateYearlyPrice() float64 {
|
|
return calculateMonthlyPrice() * 12
|
|
}
|
|
|
|
type ProvisioningStep struct {
|
|
Name string
|
|
Status string
|
|
}
|
|
|
|
func getProvisioningSteps() []ProvisioningStep {
|
|
return []ProvisioningStep{
|
|
{Name: "Domain Registration", Status: "pending"},
|
|
{Name: "VPS Provisioning", Status: "pending"},
|
|
{Name: "Cloudron Installation", Status: "pending"},
|
|
{Name: "DNS Configuration", Status: "pending"},
|
|
{Name: "Business Setup", Status: "pending"},
|
|
}
|
|
}
|
|
|
|
func calculateProgress(completedSteps int) int {
|
|
totalSteps := len(getProvisioningSteps())
|
|
if completedSteps >= totalSteps {
|
|
return 100
|
|
}
|
|
return (completedSteps * 100) / totalSteps
|
|
}
|
|
|
|
func validateLaunchRequest(domain, email, cardNumber string) error {
|
|
if domain == "" {
|
|
return &ValidationError{Message: "domain is required"}
|
|
}
|
|
if email == "" {
|
|
return &ValidationError{Message: "email is required"}
|
|
}
|
|
if cardNumber == "" {
|
|
return &ValidationError{Message: "card number is required"}
|
|
}
|
|
if !isValidDomain(domain) {
|
|
return &ValidationError{Message: "invalid domain"}
|
|
}
|
|
if !isValidEmail(email) {
|
|
return &ValidationError{Message: "invalid email"}
|
|
}
|
|
if !isValidCreditCard(cardNumber) {
|
|
return &ValidationError{Message: "invalid credit card"}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type ValidationError struct {
|
|
Message string
|
|
}
|
|
|
|
func (e *ValidationError) Error() string {
|
|
return e.Message
|
|
} |