121 lines
3.4 KiB
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")
|
|
}
|
|
}
|