Files

45 lines
2.0 KiB
Markdown

# Tests
The first automated tests for JQC. Kept deliberately small and targeted at the
places where a bug is **catastrophic and non-obvious** — the money path
(Stripe webhooks), the SLA state machine, and the multi-tenant routing
invariant.
## Running
```bash
pip install -r requirements-dev.txt
pytest
```
No MySQL, Redis, or Stripe account is required. `tests/conftest.py` sets
throwaway `SECRET_KEY` / `DATABASE_URL` (in-memory SQLite) at import time so the
`app` package imports cleanly, and every test either exercises pure functions or
uses the in-memory engine.
## What's covered
| File | Scope | Infra needed |
|---|---|---|
| `test_sla.py` | SLA thresholds + `ok`/`at_risk`/`breached`/`None` boundaries | none |
| `test_billing_webhooks.py` | `_ts_to_dt`, status normalization, `handle_event` dispatch + error-swallowing | none |
| `test_tenant_routing.py` | Routing is inert with no tenant; resolved `g.tenant_engine` wins | in-memory SQLite |
## Not yet covered (needs a live control DB + ≥2 tenant DBs)
These are the highest-value **integration** tests to add next. They require a
throwaway MySQL control DB plus two provisioned tenant DBs, so they live outside
this fast unit suite for now:
1. **Cross-tenant isolation** — resolve tenant A, write a row, resolve tenant B,
assert the row is invisible. Proves `RoutingSession` never leaks across
tenants. This is the single most important test the project can have.
2. **Webhook handlers end-to-end**`_on_payment_failed` sets `past_due_since`
and `subscription_status='past_due'`; `_on_payment_succeeded` clears the
dunning columns. Assert against a real `Tenant` row.
3. **`bootstrap_tenant` vs `upgrade_tenant`** — a freshly bootstrapped tenant DB
ends stamped at chain head with the full schema (the logic
`scripts/scratch_bootstrap_test.py` proves manually today).
4. **Billing gate state machine** — trial-expired redirects to
`/billing/subscribe`; `cancelled` redirects to `/billing/suspended`.