Add tests for Square client hardening and GDPR deletion

Covers DeleteCustomer (success + NOT_FOUND no-op), doJSON truncation (oversized bodies + rune-safe capBody), validCardID rejection without leaking the token, paymentFromSquare empty-card consistency, and mock-side customer-ID redaction in logs.
This commit is contained in:
2026-08-22 00:34:49 +01:00
parent f0099714ff
commit 8ff77bc39b
2 changed files with 347 additions and 2 deletions
@@ -797,6 +797,58 @@ func TestDevClient_CreateCustomer_EmptyEmail(t *testing.T) {
assert.Contains(t, err.Error(), "email")
}
func TestDevClient_DeleteCustomer(t *testing.T) {
client := NewDevClient().(*MockClient)
ctx := context.Background()
cust, err := client.CreateCustomer(ctx, "Jane Doe", "jane@example.com")
require.NoError(t, err)
err = client.DeleteCustomer(ctx, cust.ID)
require.NoError(t, err)
client.mu.RLock()
defer client.mu.RUnlock()
assert.Len(t, client.customers, 0, "deleted customer must be removed from the mock store")
}
func TestDevClient_DeleteCustomer_NotFoundIsNoop(t *testing.T) {
client := NewDevClient().(*MockClient)
ctx := context.Background()
// Deleting a customer the mock never created mirrors Square's NOT_FOUND —
// idempotent re-deletion must return nil (GDPR re-runs are safe).
err := client.DeleteCustomer(ctx, "cus_missing")
require.NoError(t, err)
}
// TestDevClient_CustomerID_RedactedInLogs verifies the mock never logs a full
// customer ID (S-2 convention): DeleteCustomer's entry/success lines and
// CreateCustomer's dedup-hit/created lines all use the tokenPrefix redaction,
// mirroring how prod redacts ccof: tokens.
func TestDevClient_CustomerID_RedactedInLogs(t *testing.T) {
client := NewDevClient().(*MockClient)
ctx := context.Background()
cust, err := client.CreateCustomer(ctx, "Jane Doe", "jane@example.com")
require.NoError(t, err)
var buf bytes.Buffer
log.SetOutput(&buf)
defer log.SetOutput(os.Stderr)
err = client.DeleteCustomer(ctx, cust.ID)
require.NoError(t, err)
logs := buf.String()
if strings.Contains(logs, cust.ID) {
t.Errorf("full customer id %q leaked into mock logs: %q", cust.ID, logs)
}
if !strings.Contains(logs, tokenPrefix(cust.ID)) {
t.Errorf("expected redacted customer id %q in logs, got %q", tokenPrefix(cust.ID), logs)
}
}
func TestDevClient_CancelCheckout_CancelsPending(t *testing.T) {
client := NewDevClient().(*MockClient)
client.HoldCheckouts = true