# Unit Test Book — nimsforeststripe

Automated tests covering all connector layers. No Stripe API keys required — all tests
use httptest mock servers.

## Test Suites

### 1. Stripe Client (`internal/stripe/client_test.go`)
- **TestHealthy** — balance endpoint reachable → Healthy() returns true
- **TestHealthy_Unreachable** — unreachable server → Healthy() returns false
- **TestListCustomers** — GET /customers with limit param, decode response
- **TestGetCustomer** — GET /customers/{id}, decode single customer
- **TestCreateCustomer** — POST /customers with form-encoded body
- **TestListCharges** — GET /charges, decode list response
- **TestCreateCharge** — POST /charges with amount/currency params
- **TestGetBalance** — GET /balance, decode available/pending amounts
- **TestAPIError** — 401 response parsed into structured APIError
- **TestCreatePaymentIntent** — POST /payment_intents, verify client_secret returned
- **TestListEvents** — GET /events with created[gte] filter

### 2. HTTP API Server (`internal/api/server_test.go`)
- **TestHealthEndpoint** — /api/v1/health returns ok + stripe_healthy
- **TestHealthEndpoint_StripeDown** — health reports stripe_unreachable when Stripe is down
- **TestAuthRequired** — protected endpoints return 401 without token
- **TestAuthWrongToken** — wrong Bearer token → 401
- **TestListCustomersEndpoint** — authenticated GET /api/v1/customers returns list
- **TestGetCustomerEndpoint** — GET /api/v1/customers/{id} returns single customer
- **TestCreateCustomerEndpoint** — POST /api/v1/customers returns 201
- **TestCreateChargeEndpoint_Validation** — missing amount/currency → 400
- **TestCreateChargeEndpoint** — valid charge → 201
- **TestCreatePaymentIntentEndpoint_Validation** — missing fields → 400
- **TestListChargesEndpoint** — GET /api/v1/charges returns list
- **TestGetBalanceEndpoint** — GET /api/v1/balance returns balance object

### 3. Webhook Verification (`internal/api/webhook_test.go`)
- **TestWebhookValidSignature** — correctly signed webhook → 200
- **TestWebhookInvalidSignature** — wrong signature → 401
- **TestWebhookMissingSignature** — no Stripe-Signature header → 401
- **TestWebhookNoSecretConfigured** — no secret → accepts all webhooks (dev mode)
- **TestWebhookInvalidJSON** — malformed body → 400
- **TestVerifyStripeSignature** — HMAC-SHA256 verification passes with correct secret
- **TestVerifyStripeSignature_OldTimestamp** — replay attack rejected (>5min)
- **TestVerifyStripeSignature_EmptyHeader** — empty header rejected
- **TestVerifyStripeSignature_WrongSecret** — wrong secret → mismatch

### 4. Config (`internal/config/config_test.go`)
- **TestDefaultConfig** — defaults: port 8096, NATS URL, 5m sync
- **TestLoadMissingFile** — missing config returns defaults without error
- **TestLoadValidConfig** — full YAML parsed correctly
- **TestLoadInvalidYAML** — malformed YAML returns error
- **TestLoadPartialConfig** — partial override preserves defaults

## Running

```bash
cd /home/claude-user/nimsforeststripe
go test ./... -v
```
