Files
bank/compliance_test.go
zeekayandHanzo Dev d7d595d210 bank: in-process HTTP integration harness — coverage 8% -> 58%
Adds a real test harness (harness_test.go): a live bank app on temp
SQLite with every collection ensured and every hook + route registered
exactly as cmd/bankd wires them, plus a seeded principal and bearer
token. Tests drive the actual ledger and the real HTTP handlers via
base's ApiScenario — not mocks.

Coverage of the surfaces that matter, end to end:
- money movement: transfers, outbound payments, beneficiary lifecycle
  (all 75-100%), the balance hold/settle chain (updateBalance 81%,
  payments hooks 88%), overdraw rejection, provision 84%
- crypto: faucet, send (valid + bad-address), wallet, prices
- exchange: quote + execute (exchangeRate 100%)
- cards: issue + freeze/unfreeze; per-account reads; sandbox login
- compliance: AML gate both ways (fail-open with no service; blocked
  via a mock compliance server); fees scoped to payment/conversion

Total statement coverage across ./... rises from ~8% to 58.4%, with
the critical-path handlers and the hook chain all exercised. Full Go
suite + 12 Playwright e2e green locally.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-22 14:57:56 -07:00

50 lines
1.7 KiB
Go

package bank
import (
"net/http"
"net/http/httptest"
"testing"
)
// A transaction above the AML threshold ($10k) with no compliance service
// configured passes (fail-open dev mode) — and exercises the AML branch.
func TestAMLFailOpenWithoutService(t *testing.T) {
t.Setenv("COMPLIANCE_SERVICE_URL", "")
app := newBankApp(t)
id, _ := seedPrincipal(t, app)
acct := primaryAccount(app, id)
if err := setBalance(app, acct.Id, "USD", 50_000_00); err != nil {
t.Fatalf("set balance: %v", err)
}
if _, err := newTx(app, map[string]any{
"account": acct.Id, "type": "payment", "direction": "debit",
"amount": 20_000_00, "currency": "USD", "status": "pending", "reference": "big",
}); err != nil {
t.Errorf("expected fail-open AML to allow the transaction, got %v", err)
}
}
// With a compliance service that blocks, an above-threshold transaction is
// refused — covering callComplianceService and the block branch.
func TestAMLBlocksWhenServiceBlocks(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"result":"blocked"}`))
}))
defer srv.Close()
t.Setenv("COMPLIANCE_SERVICE_URL", srv.URL)
app := newBankApp(t)
id, _ := seedPrincipal(t, app)
acct := primaryAccount(app, id)
if err := setBalance(app, acct.Id, "USD", 50_000_00); err != nil {
t.Fatalf("set balance: %v", err)
}
if _, err := newTx(app, map[string]any{
"account": acct.Id, "type": "payment", "direction": "debit",
"amount": 20_000_00, "currency": "USD", "status": "pending", "reference": "big",
}); err == nil {
t.Error("expected AML screening to block the above-threshold transaction")
}
}