mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 02:52:53 +00:00
- Update charmbracelet/colorprofile from v0.4.1 to v0.4.3 - Update charmbracelet/x/ansi from v0.11.6 to v0.11.7 - Update clipperhouse/displaywidth from v0.9.0 to v0.11.0 - Update clipperhouse/uax29/v2 from v2.5.0 to v2.7.0 - Update davecgh/go-spew to v1.1.2-0.20180830191138-d8f796af33cc - Update fsnotify/fsnotify from v1.7.0 to v1.9.0 - Update google/go-cmp from v0.5.9 to v0.7.0 - Update lucasb-eyer/go-colorful from v1.3.0 to v1.4
502 lines
11 KiB
Go
502 lines
11 KiB
Go
package tests
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/nutcas3/telecom-platform/apps/cli/internal/app"
|
|
"github.com/nutcas3/telecom-platform/apps/cli/internal/commands"
|
|
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
|
)
|
|
|
|
// IntegrationTestSuite runs comprehensive integration tests for the CLI
|
|
type IntegrationTestSuite struct {
|
|
suite.Suite
|
|
server *httptest.Server
|
|
configDir string
|
|
config *types.CLIConfig
|
|
cli *app.EnhancedCLI
|
|
}
|
|
|
|
// SetupSuite sets up the test environment
|
|
func (suite *IntegrationTestSuite) SetupSuite() {
|
|
// Create temporary config directory
|
|
tempDir, err := os.MkdirTemp("", "cli-test")
|
|
require.NoError(suite.T(), err)
|
|
suite.configDir = tempDir
|
|
|
|
// Create mock API server
|
|
suite.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
suite.handleMockAPI(w, r)
|
|
}))
|
|
|
|
// Create test configuration
|
|
suite.config = &types.CLIConfig{
|
|
APIEndpoint: suite.server.URL,
|
|
APIToken: "test-token",
|
|
Profile: "test",
|
|
NoColor: true,
|
|
Verbose: false,
|
|
Theme: "default",
|
|
}
|
|
|
|
// Create CLI instance
|
|
suite.cli = app.NewEnhancedCLI()
|
|
}
|
|
|
|
// TearDownSuite cleans up the test environment
|
|
func (suite *IntegrationTestSuite) TearDownSuite() {
|
|
if suite.server != nil {
|
|
suite.server.Close()
|
|
}
|
|
if suite.configDir != "" {
|
|
os.RemoveAll(suite.configDir)
|
|
}
|
|
}
|
|
|
|
// handleMockAPI handles mock API responses
|
|
func (suite *IntegrationTestSuite) handleMockAPI(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
switch r.URL.Path {
|
|
case "/api/v1/subscribers":
|
|
switch r.Method {
|
|
case "GET":
|
|
subscribers := []map[string]any{
|
|
{
|
|
"id": 1,
|
|
"name": "John Doe",
|
|
"email": "[email protected]",
|
|
"phone": "+1234567890",
|
|
"status": "active",
|
|
"balance": 100.50,
|
|
},
|
|
{
|
|
"id": 2,
|
|
"name": "Jane Smith",
|
|
"email": "[email protected]",
|
|
"phone": "+0987654321",
|
|
"status": "inactive",
|
|
"balance": 0.0,
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"subscribers": subscribers,
|
|
"total": len(subscribers),
|
|
})
|
|
case "POST":
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"id": 3,
|
|
"status": "created",
|
|
})
|
|
}
|
|
case "/api/v1/services":
|
|
services := []map[string]any{
|
|
{
|
|
"name": "api-server",
|
|
"status": "running",
|
|
"version": "v1.0.0",
|
|
"cpu": 45.2,
|
|
"memory": "256MB",
|
|
"uptime": "2h15m",
|
|
},
|
|
{
|
|
"name": "charging-engine",
|
|
"status": "running",
|
|
"version": "v1.0.0",
|
|
"cpu": 23.8,
|
|
"memory": "128MB",
|
|
"uptime": "2h15m",
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"services": services,
|
|
"total": len(services),
|
|
})
|
|
case "/api/v1/billing/invoices":
|
|
invoices := []map[string]any{
|
|
{
|
|
"id": "INV-001",
|
|
"customer": "John Doe",
|
|
"amount": 100.50,
|
|
"status": "paid",
|
|
"due_date": "2023-12-31",
|
|
"created_at": "2023-12-01",
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"invoices": invoices,
|
|
"total": len(invoices),
|
|
})
|
|
case "/api/v1/health":
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"status": "healthy",
|
|
"services": map[string]string{
|
|
"api-server": "healthy",
|
|
"charging-engine": "healthy",
|
|
"packet-gateway": "healthy",
|
|
},
|
|
})
|
|
default:
|
|
http.NotFound(w, r)
|
|
}
|
|
}
|
|
|
|
// TestSubscribersCommand tests the subscribers command
|
|
func (suite *IntegrationTestSuite) TestSubscribersCommand() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "list subscribers",
|
|
args: []string{"subscribers", "list"},
|
|
expected: "John Doe",
|
|
},
|
|
{
|
|
name: "list subscribers with format",
|
|
args: []string{"subscribers", "list", "--format", "json"},
|
|
expected: "John Doe",
|
|
},
|
|
{
|
|
name: "list enhanced subscribers",
|
|
args: []string{"subscribers", "list", "--enhanced"},
|
|
expected: "Telecom Platform",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
// Capture stdout
|
|
var buf bytes.Buffer
|
|
oldStdout := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Run command
|
|
err := commands.HandleSubscribersEnhanced(tt.args[1:], suite.config)
|
|
|
|
// Restore stdout
|
|
w.Close()
|
|
os.Stdout = oldStdout
|
|
io.Copy(&buf, r)
|
|
|
|
// Check results
|
|
assert.NoError(suite.T(), err)
|
|
assert.Contains(suite.T(), buf.String(), tt.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestServicesCommand tests the services command
|
|
func (suite *IntegrationTestSuite) TestServicesCommand() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "list services",
|
|
args: []string{"services", "list"},
|
|
expected: "api-server",
|
|
},
|
|
{
|
|
name: "list services with format",
|
|
args: []string{"services", "list", "--format", "json"},
|
|
expected: "api-server",
|
|
},
|
|
{
|
|
name: "list enhanced services",
|
|
args: []string{"services", "list", "--enhanced"},
|
|
expected: "Telecom Platform",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
// Capture stdout
|
|
var buf bytes.Buffer
|
|
oldStdout := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Run command
|
|
err := commands.HandleServicesEnhanced(tt.args[1:], suite.config)
|
|
|
|
// Restore stdout
|
|
w.Close()
|
|
os.Stdout = oldStdout
|
|
io.Copy(&buf, r)
|
|
|
|
// Check results
|
|
assert.NoError(suite.T(), err)
|
|
assert.Contains(suite.T(), buf.String(), tt.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestBillingCommand tests the billing command
|
|
func (suite *IntegrationTestSuite) TestBillingCommand() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "list invoices",
|
|
args: []string{"billing", "invoices"},
|
|
expected: "Billing command: invoices",
|
|
},
|
|
{
|
|
name: "list invoices with format",
|
|
args: []string{"billing", "invoices", "--format", "json"},
|
|
expected: "Billing command: invoices",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
// Capture stdout
|
|
var buf bytes.Buffer
|
|
oldStdout := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Run command
|
|
err := commands.HandleBillingEnhanced(tt.args[1:], suite.config)
|
|
|
|
// Restore stdout
|
|
w.Close()
|
|
os.Stdout = oldStdout
|
|
io.Copy(&buf, r)
|
|
|
|
// Check results
|
|
assert.NoError(suite.T(), err)
|
|
assert.Contains(suite.T(), buf.String(), tt.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestConfigCommand tests the config command
|
|
func (suite *IntegrationTestSuite) TestConfigCommand() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "show config",
|
|
args: []string{"config", "show"},
|
|
expected: "test",
|
|
},
|
|
{
|
|
name: "set config value",
|
|
args: []string{"config", "set", "timeout", "60"},
|
|
expected: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
// Capture stdout
|
|
var buf bytes.Buffer
|
|
oldStdout := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Run command
|
|
err := commands.HandleConfigEnhanced(tt.args[1:], suite.config)
|
|
|
|
// Restore stdout
|
|
w.Close()
|
|
os.Stdout = oldStdout
|
|
io.Copy(&buf, r)
|
|
|
|
// Check results
|
|
assert.NoError(suite.T(), err)
|
|
if tt.expected != "" {
|
|
assert.Contains(suite.T(), buf.String(), tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestErrorHandling tests error handling scenarios
|
|
func (suite *IntegrationTestSuite) TestErrorHandling() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "missing required argument",
|
|
args: []string{"subscribers", "create"},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "invalid command",
|
|
args: []string{"subscribers", "invalid-command"},
|
|
expectError: true, // This returns an error for unknown command
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
err := commands.HandleSubscribersEnhanced(tt.args[1:], suite.config)
|
|
if tt.expectError {
|
|
assert.Error(suite.T(), err)
|
|
} else {
|
|
assert.NoError(suite.T(), err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestConcurrency tests concurrent command execution
|
|
func (suite *IntegrationTestSuite) TestConcurrency() {
|
|
// Run multiple commands concurrently
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
results := make(chan error, 10)
|
|
commandList := [][]string{
|
|
{"subscribers", "list"},
|
|
{"services", "list"},
|
|
{"billing", "invoices"},
|
|
{"config", "show"},
|
|
}
|
|
|
|
for _, cmd := range commandList {
|
|
go func(args []string) {
|
|
var err error
|
|
switch args[0] {
|
|
case "subscribers":
|
|
err = commands.HandleSubscribersEnhanced(args[1:], suite.config)
|
|
case "services":
|
|
err = commands.HandleServicesEnhanced(args[1:], suite.config)
|
|
case "billing":
|
|
err = commands.HandleBillingEnhanced(args[1:], suite.config)
|
|
case "config":
|
|
err = commands.HandleConfigEnhanced(args[1:], suite.config)
|
|
}
|
|
|
|
select {
|
|
case results <- err:
|
|
case <-ctx.Done():
|
|
results <- ctx.Err()
|
|
}
|
|
}(cmd)
|
|
}
|
|
|
|
// Collect results
|
|
for range commandList {
|
|
select {
|
|
case err := <-results:
|
|
assert.NoError(suite.T(), err)
|
|
case <-ctx.Done():
|
|
suite.T().Fatal("Timeout waiting for concurrent commands")
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestPerformance tests command performance
|
|
func (suite *IntegrationTestSuite) TestPerformance() {
|
|
start := time.Now()
|
|
err := commands.HandleSubscribersEnhanced([]string{"list"}, suite.config)
|
|
duration := time.Since(start)
|
|
|
|
assert.NoError(suite.T(), err)
|
|
assert.Less(suite.T(), duration, 5*time.Second, "Command should complete within 5 seconds")
|
|
}
|
|
|
|
// TestCLIApp tests the CLI application
|
|
func (suite *IntegrationTestSuite) TestCLIApp() {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "run subscribers command",
|
|
args: []string{"cli", "subscribers", "list"},
|
|
expected: "Telecom Platform",
|
|
},
|
|
{
|
|
name: "run services command",
|
|
args: []string{"cli", "services", "list"},
|
|
expected: "Telecom Platform",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
suite.Run(tt.name, func() {
|
|
// Capture stdout
|
|
var buf bytes.Buffer
|
|
oldStdout := os.Stdout
|
|
r, w, _ := os.Pipe()
|
|
os.Stdout = w
|
|
|
|
// Run CLI command
|
|
err := suite.cli.Run(tt.args)
|
|
|
|
// Restore stdout
|
|
w.Close()
|
|
os.Stdout = oldStdout
|
|
io.Copy(&buf, r)
|
|
|
|
// Check results
|
|
assert.NoError(suite.T(), err)
|
|
assert.Contains(suite.T(), buf.String(), tt.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Run the integration test suite
|
|
func TestIntegrationSuite(t *testing.T) {
|
|
suite.Run(t, new(IntegrationTestSuite))
|
|
}
|
|
|
|
// BenchmarkCommands benchmarks command performance
|
|
func BenchmarkCommands(b *testing.B) {
|
|
tempDir, err := os.MkdirTemp("", "cli-bench")
|
|
require.NoError(b, err)
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]any{
|
|
"subscribers": []map[string]any{},
|
|
"total": 0,
|
|
})
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := &types.CLIConfig{
|
|
APIEndpoint: server.URL,
|
|
APIToken: "test-token",
|
|
Profile: "bench",
|
|
NoColor: true,
|
|
Verbose: false,
|
|
Theme: "default",
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
err := commands.HandleSubscribersEnhanced([]string{"list"}, cfg)
|
|
require.NoError(b, err)
|
|
}
|
|
}
|