45 lines
2.0 KiB
Markdown
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`.
|