Files
member-console/internal/server/stripe_webhook_test.go

121 lines
3.4 KiB
Go

package server
import (
"encoding/json"
"testing"
)
func TestScrubPII(t *testing.T) {
input := map[string]interface{}{
"id": "evt_123",
"type": "customer.created",
"email": "user@example.com",
"name": "Alice",
"amount": float64(2000),
"object": map[string]interface{}{
"id": "cus_123",
"email": "nested@example.com",
"phone": "+15551234567",
"address": map[string]interface{}{"city": "Portland"},
"shipping": map[string]interface{}{"name": "Bob"},
"billing_details": map[string]interface{}{"email": "billing@x.com"},
"metadata": map[string]interface{}{"internal_id": "abc"},
},
"items": []interface{}{
map[string]interface{}{
"id": "ii_123",
"email": "item@example.com",
},
},
}
result := ScrubPII(input).(map[string]interface{})
// Top-level PII should be redacted
if result["email"] != "[REDACTED]" {
t.Errorf("expected email redacted, got %v", result["email"])
}
if result["name"] != "[REDACTED]" {
t.Errorf("expected name redacted, got %v", result["name"])
}
// Non-PII should be preserved
if result["id"] != "evt_123" {
t.Errorf("expected id preserved, got %v", result["id"])
}
if result["amount"] != float64(2000) {
t.Errorf("expected amount preserved, got %v", result["amount"])
}
// Nested PII should be redacted
obj := result["object"].(map[string]interface{})
if obj["email"] != "[REDACTED]" {
t.Errorf("expected nested email redacted, got %v", obj["email"])
}
if obj["phone"] != "[REDACTED]" {
t.Errorf("expected nested phone redacted, got %v", obj["phone"])
}
if obj["address"] != "[REDACTED]" {
t.Errorf("expected address redacted, got %v", obj["address"])
}
if obj["shipping"] != "[REDACTED]" {
t.Errorf("expected shipping redacted, got %v", obj["shipping"])
}
if obj["billing_details"] != "[REDACTED]" {
t.Errorf("expected billing_details redacted, got %v", obj["billing_details"])
}
// Nested non-PII preserved
if obj["id"] != "cus_123" {
t.Errorf("expected nested id preserved, got %v", obj["id"])
}
meta := obj["metadata"].(map[string]interface{})
if meta["internal_id"] != "abc" {
t.Errorf("expected metadata preserved, got %v", meta["internal_id"])
}
// Array items scrubbed
items := result["items"].([]interface{})
item := items[0].(map[string]interface{})
if item["email"] != "[REDACTED]" {
t.Errorf("expected array item email redacted, got %v", item["email"])
}
if item["id"] != "ii_123" {
t.Errorf("expected array item id preserved, got %v", item["id"])
}
}
func TestScrubPII_PreservesJSONShape(t *testing.T) {
// Verify the scrubbed output is valid JSON
input := map[string]interface{}{
"customer": map[string]interface{}{
"id": "cus_abc",
"email": "test@test.com",
"name": "Test User",
"metadata": map[string]interface{}{
"plan": "pro",
},
},
}
result := ScrubPII(input)
data, err := json.Marshal(result)
if err != nil {
t.Fatalf("scrubbed result should marshal to JSON: %v", err)
}
// Verify it round-trips
var parsed map[string]interface{}
if err := json.Unmarshal(data, &parsed); err != nil {
t.Fatalf("scrubbed JSON should parse: %v", err)
}
customer := parsed["customer"].(map[string]interface{})
if customer["id"] != "cus_abc" {
t.Error("id should be preserved through round-trip")
}
if customer["email"] != "[REDACTED]" {
t.Error("email should be redacted through round-trip")
}
}