Skip to main content

max / makenotwork

5.1 KB · 109 lines History Blame Raw
1 # MNW Server Tests
2
3 ## Prerequisites
4
5 - PostgreSQL running locally (default: `postgres://localhost/postgres`)
6 - Set `TEST_DATABASE_URL` if using a non-default admin connection
7
8 ## Test Types
9
10 ### Unit Tests (`cargo test --lib`)
11
12 Pure logic: pricing, validation, formatting, enums, error handling, CSRF, RSS, file scanning, import parsing. No database required.
13
14 ### Integration Tests (`cargo test --test integration`)
15
16 Workflow modules under `tests/workflows/`. Each test gets an isolated PostgreSQL database cloned from a shared template (migrations applied once, then reused across runs while migration-current). Run with `--test-threads=8`; full parallelism overwhelms PostgreSQL.
17
18 **Harness features:**
19 - In-process Axum app (no network, uses `tower::ServiceExt::oneshot`)
20 - Cookie-aware HTTP client with automatic CSRF token management
21 - Mock Stripe (`MockPaymentProvider`), captures checkout sessions, supports webhook signing
22 - Mock email (`MockEmailTransport`), captures all sent emails for assertion
23 - Mock S3 (`InMemoryStorage`), in-memory file storage
24 - Direct SQL helpers for test setup (`grant_creator`, `grant_tier`, `connect_stripe`, etc.)
25
26 **Harness constructors:**
27 - `TestHarness::new()`: DB only (fastest, for auth/CRUD tests)
28 - `with_storage()`: adds in-memory S3
29 - `with_mocks()`: mock Stripe + email (for payment flow tests)
30 - `with_stripe()`: real Stripe SDK with test keys
31 - `with_admin()`: pre-created admin user
32 - `with_storage_and_scanner()`: file scanning pipeline
33 - `with_git_repos(path)`: git repository support
34 - `with_admin_storage_and_scanner()`: admin user + in-memory S3 + scanner
35 - `with_synckit_storage()`: SyncKit in-memory bucket (OTA tests)
36 - `with_creator_tier_checkout()`: mock Stripe + a configured Everything-tier price
37 - `with_postmark()`: Postmark webhook tokens configured
38
39 Anything not covered by a constructor goes through `TestHarness::build(BuildOptions { .. })`
40 directly; add a documented `BuildOptions` field rather than a constructor per calling test.
41
42 **Seeding:** `harness/seed.rs` provides `seed_user` and `seed_project` for the
43 `db_*_layer.rs` contract tests, which run against a bare `TestDb` with no router
44 and so cannot use `signup`. Prefer the harness methods (`signup`, `create_creator`,
45 `create_creator_with_item`) anywhere a session or HTTP flow is in play.
46
47 ### Seal Tests
48
49 Ratchets over the repo itself, each its own binary. No database.
50
51 - `assumptions.rs`: the business assumptions TOML parses, validates, and still resolves every marker in the site-docs corpus.
52 - `migration_hygiene.rs`: new migrations use `CONCURRENTLY` / `IF NOT EXISTS` and opt out of the per-migration transaction correctly.
53 - `frontend_globals.rs`: the `window.*` global count only goes down.
54 - `test_hygiene.rs`: test-suite conventions: doc headers, `#[ignore]` reasons, and `HIGH_WATER` counts for loose status assertions, `test_` prefixes, and oversized modules.
55 - `workflows/enum_drift.rs`: every domain enum's variants match its Postgres `CHECK` list (needs a DB; runs inside the integration binary).
56
57 ### Load Tests (`cargo test --test load -- --ignored --nocapture`)
58
59 Multi-scenario virtual user simulation. Requires `--ignored` flag. Configurable via env vars:
60 - `LOAD_VUS`: virtual users (default: 20)
61 - `LOAD_DURATION_SECS`: duration (default: 30)
62 - `LOAD_RAMP_SECS`: ramp-up (default: 5)
63 - `LOAD_MIX`: scenario shares, e.g. `anon:25,buyer:15,creator:10,dash:50`. Must sum to 100.
64 - `QUASI_SCREENS`: which screens serve from the description layer (`*` for all).
65 - `LOAD_MT_LATENCY_MS`: how long the stub Multithreaded sleeps before answering (default: 0).
66 - `LOAD_MT_MEMBERSHIPS`: rows the stub answers with (default: 8).
67 - `LOAD_PROBE_MS`: blocking-pool probe interval (default: 50).
68
69 The report carries two things beyond the endpoint table:
70
71 - **`Rej`**, 4xx other than 429. Read it first. A rejected request is fast, so a
72 route quietly answering 403 or 404 wins a latency comparison it never ran.
73 - **Blocking-pool dispatch delay.** How long a fresh `spawn_blocking` waits to
74 start, sampled through the run. The description layer's whole runtime cost is
75 that quasi's router is sync, so every described request holds a pool thread;
76 this is whether that pool still has headroom. `RuntimeMetrics` would say it
77 directly but is behind `tokio_unstable`, which this tree does not build with.
78 Read it with the `POST /join/step/account` mean, which is argon2 and the same
79 fact from the other end.
80
81 For comparing the description layer against Askama, use
82 `scripts/load-conversion-ab.sh` rather than driving `QUASI_SCREENS` by hand: it
83 runs the alternating-pairs protocol (Askama / described / described / Askama) at
84 one fixed mix, so the four runs stay comparable.
85
86 ### Health Tests (`cargo test --test health`)
87
88 External HTTP tests against a running server at `http://localhost:3000`. Skips gracefully if server is not running.
89
90 ## Running
91
92 ```bash
93 # Unit tests only (fast, no DB)
94 cargo test --lib
95
96 # Integration tests (requires PostgreSQL)
97 cargo test --test integration
98
99 # Specific workflow
100 cargo test --test integration sandbox
101
102 # All tests
103 cargo test
104 ```
105
106 ## Fixtures
107
108 Test media files in `tests/fixtures/`: `.mp3`, `.mp4`, `.flac`, `.webm`, `.ogg`, `.wav`, `.m4a`
109