Files
sonr/cmd/motr/integration_test.go
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

* fix: Commenht
2025-10-03 14:45:52 -04:00

406 lines
10 KiB
Go

//go:build js && wasm
// +build js,wasm
package main
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
)
// TestHealthEndpoint tests the health check endpoint
func TestHealthEndpoint(t *testing.T) {
req := httptest.NewRequest("GET", "/health", nil)
w := httptest.NewRecorder()
handleHealth(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["status"] != "healthy" {
t.Errorf("Expected status healthy, got %v", response["status"])
}
}
// TestPaymentInstruments tests getting payment instruments
func TestPaymentInstruments(t *testing.T) {
req := httptest.NewRequest("GET", "/payment/instruments", nil)
w := httptest.NewRecorder()
handlePaymentInstruments(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var instruments []map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&instruments); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if len(instruments) == 0 {
t.Error("Expected at least one payment instrument")
}
}
// TestCanMakePayment tests payment capability check
func TestCanMakePayment(t *testing.T) {
payload := map[string]interface{}{
"origin": "https://localhost:3000",
"methodData": []map[string]interface{}{
{
"supportedMethods": "https://motor.sonr.io/pay",
},
},
}
body, _ := json.Marshal(payload)
req := httptest.NewRequest("POST", "/payment/canmakepayment", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
handleCanMakePayment(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["canMakePayment"] != true {
t.Errorf("Expected canMakePayment to be true")
}
}
// TestProcessPayment tests payment processing with security
func TestProcessPayment(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
payload := map[string]interface{}{
"origin": "https://localhost:3000",
"topOrigin": "https://localhost:3000",
"paymentRequestId": "test-request-123",
"methodData": []map[string]interface{}{
{
"supportedMethods": "https://motor.sonr.io/pay",
},
},
"details": map[string]interface{}{
"total": map[string]interface{}{
"label": "Test Payment",
"amount": map[string]interface{}{
"currency": "USD",
"value": "100.00",
},
},
},
}
body, _ := json.Marshal(payload)
req := httptest.NewRequest("POST", "/api/payment/process", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Origin", "https://localhost:3000")
w := httptest.NewRecorder()
handleProcessPayment(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["paymentId"] == "" {
t.Error("Expected payment ID in response")
}
if response["status"] != "pending" {
t.Errorf("Expected status pending, got %v", response["status"])
}
}
// TestCardTokenization tests PCI-compliant card tokenization
func TestCardTokenization(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
// Test valid card
token, err := TokenizeCard("4111111111111111", "123", 12, 2025)
if err != nil {
t.Fatalf("Failed to tokenize valid card: %v", err)
}
if token == "" {
t.Error("Expected token to be generated")
}
// Test invalid card number
_, err = TokenizeCard("1234567890123456", "123", 12, 2025)
if err == nil {
t.Error("Expected error for invalid card number")
}
// Test expired card
_, err = TokenizeCard("4111111111111111", "123", 1, 2020)
if err == nil {
t.Error("Expected error for expired card")
}
}
// TestTransactionSigning tests transaction signature verification
func TestTransactionSigning(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
txData := map[string]interface{}{
"id": "test-tx-123",
"amount": "100.00",
"currency": "USD",
"method": "card",
"timestamp": time.Now().Unix(),
}
// Sign transaction
signature, err := SignTransaction(txData)
if err != nil {
t.Fatalf("Failed to sign transaction: %v", err)
}
if signature == "" {
t.Error("Expected signature to be generated")
}
// Verify signature
valid := VerifyTransactionSignature(txData, signature)
if !valid {
t.Error("Expected signature to be valid")
}
// Test invalid signature
invalid := VerifyTransactionSignature(txData, "invalid-signature")
if invalid {
t.Error("Expected invalid signature to fail verification")
}
}
// TestOIDCDiscovery tests OIDC discovery endpoint
func TestOIDCDiscovery(t *testing.T) {
req := httptest.NewRequest("GET", "/.well-known/openid-configuration", nil)
w := httptest.NewRecorder()
handleOIDCDiscovery(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var config map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&config); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
// Check required OIDC fields
requiredFields := []string{
"issuer",
"authorization_endpoint",
"token_endpoint",
"userinfo_endpoint",
"jwks_uri",
}
for _, field := range requiredFields {
if _, exists := config[field]; !exists {
t.Errorf("Missing required OIDC field: %s", field)
}
}
}
// TestJWKS tests JWKS endpoint
func TestJWKS(t *testing.T) {
req := httptest.NewRequest("GET", "/.well-known/jwks.json", nil)
w := httptest.NewRecorder()
handleJWKS(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var jwks map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&jwks); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
keys, ok := jwks["keys"].([]interface{})
if !ok || len(keys) == 0 {
t.Error("Expected at least one key in JWKS")
}
}
// TestRateLimiting tests rate limiting functionality
func TestRateLimiting(t *testing.T) {
// Initialize with low rate limit for testing
securityConfig.RateLimit = 5
securityConfig.RateWindow = time.Second
rateLimiter = NewRateLimiter(5, time.Second)
// Make requests up to the limit
for i := 0; i < 5; i++ {
req := httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusOK {
t.Errorf("Request %d: Expected status 200, got %d", i+1, w.Code)
}
}
// Next request should be rate limited
req := httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusTooManyRequests {
t.Errorf("Expected rate limit (429), got %d", w.Code)
}
// Wait for rate limit window to reset
time.Sleep(time.Second + 100*time.Millisecond)
// Should work again
req = httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w = httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusOK {
t.Errorf("After reset: Expected status 200, got %d", w.Code)
}
}
// TestSecurityHeaders tests security headers are properly set
func TestSecurityHeaders(t *testing.T) {
req := httptest.NewRequest("GET", "/health", nil)
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
// Check security headers
headers := map[string]string{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Referrer-Policy": "strict-origin-when-cross-origin",
}
for header, expected := range headers {
actual := w.Header().Get(header)
if actual != expected {
t.Errorf("Header %s: expected %s, got %s", header, expected, actual)
}
}
// Check CSP is present
csp := w.Header().Get("Content-Security-Policy")
if csp == "" {
t.Error("Expected Content-Security-Policy header")
}
}
// TestPCICompliance tests PCI compliance audit logging
func TestPCICompliance(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
// Log some actions
pciCompliance.LogAction("TEST_ACTION", "user123", "resource456", "SUCCESS", "127.0.0.1")
// Get audit log
logs := pciCompliance.GetAuditLog(10)
if len(logs) == 0 {
t.Error("Expected audit log entries")
}
// Check last entry
lastLog := logs[len(logs)-1]
if lastLog.Action != "TEST_ACTION" {
t.Errorf("Expected action TEST_ACTION, got %s", lastLog.Action)
}
if lastLog.UserID != "user123" {
t.Errorf("Expected user ID user123, got %s", lastLog.UserID)
}
}
// TestDataEncryption tests sensitive data encryption
func TestDataEncryption(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
sensitiveData := "4111-1111-1111-1111"
// Encrypt data
encrypted, err := EncryptSensitiveData(sensitiveData)
if err != nil {
t.Fatalf("Failed to encrypt data: %v", err)
}
if encrypted == sensitiveData {
t.Error("Encrypted data should not match plaintext")
}
// Decrypt data
decrypted, err := DecryptSensitiveData(encrypted)
if err != nil {
t.Fatalf("Failed to decrypt data: %v", err)
}
if decrypted != sensitiveData {
t.Errorf("Decrypted data doesn't match original: got %s, want %s", decrypted, sensitiveData)
}
}
// TestCardMasking tests card number masking
func TestCardMasking(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{"4111111111111111", "**** **** **** 1111"},
{"5500000000000004", "**** **** **** 0004"},
{"340000000000009", "********** 00009"},
{"123", "123"}, // Too short to mask
}
for _, tc := range testCases {
masked := MaskCardNumber(tc.input)
if masked != tc.expected {
t.Errorf("MaskCardNumber(%s): got %s, want %s", tc.input, masked, tc.expected)
}
}
}