# Live Testing Guide
This guide covers end-to-end usage of the `examples/` programs against real Jortt accounts.
## Security and Credential Model
The repository never stores real credentials.
Use environment variables only:
- `JORTT_CLIENT_ID`
- `JORTT_CLIENT_SECRET`
- optional `JORTT_ACCESS_TOKEN`
When `JORTT_ACCESS_TOKEN` is set and non-empty, examples use it directly.
When it is absent, examples call OAuth client-credentials flow to obtain a token.
## Example Matrix
| `oauth_client_credentials` | Fetch and print token metadata from OAuth | No writes |
| `typed_live_workflow` | Typed customer/invoice flow validation | Read-only unless `JORTT_ALLOW_WRITES=true` |
| `full_openapi_smoke` | Full operation smoke by iterating generated catalog (`126`) | Read-only unless `JORTT_RUN_MUTATIONS=true` |
## Shared Environment Variables
| `JORTT_CLIENT_ID` | Yes (unless only using `JORTT_ACCESS_TOKEN`) | OAuth client id |
| `JORTT_CLIENT_SECRET` | Yes (unless only using `JORTT_ACCESS_TOKEN`) | OAuth client secret |
| `JORTT_ACCESS_TOKEN` | Optional | Direct bearer token override |
| `JORTT_BASE_URL` | Optional | API base URL override, defaults to `https://api.jortt.nl/` |
Starter templates:
- PowerShell: [`examples/env.template.ps1`](../examples/env.template.ps1)
- POSIX shell: [`examples/env.template.sh`](../examples/env.template.sh)
## Typed Workflow Variables
| `JORTT_PARAM_CUSTOMER_ID` | Optional | Enables `get_customer` check |
| `JORTT_PARAM_INVOICE_ID` | Optional | Enables `get_invoice` and PDF URL checks |
| `JORTT_ALLOW_WRITES` | Optional | `true`/`1` enables create customer + create invoice |
## Full OpenAPI Smoke Variables
| `JORTT_RUN_MUTATIONS` | Optional | `true`/`1` enables POST/PUT/PATCH/DELETE execution |
| `JORTT_PARAM_<NAME>` | Conditional | Supplies path parameter values for operations with `{name}` |
| `JORTT_QUERY_<METHOD>_<PATH_KEY>` | Optional | Query pairs as `k=v&k2=v2` |
| `JORTT_BODY_<METHOD>_<PATH_KEY>` | Optional | Raw JSON payload string |
| `JORTT_ACCEPT_<METHOD>_<PATH_KEY>` | Optional | Explicit `Accept` header override |
### Path Key Derivation
`<PATH_KEY>` is generated by:
1. taking the literal path template from the OpenAPI catalog
2. replacing non-alphanumeric characters with `_`
3. collapsing repeated `_`
4. uppercasing the result
Examples:
- `POST /v2/invoices` => `POST_V2_INVOICES`
- `GET /customers/{customer_id}` => `GET_CUSTOMERS_CUSTOMER_ID`
- `PUT /projects/{id}/line_items/{line_item_id}` => `PUT_PROJECTS_ID_LINE_ITEMS_LINE_ITEM_ID`
## Execution Steps
### 1) OAuth only
```bash
cargo run --example oauth_client_credentials
```
### 2) Typed workflow
```bash
cargo run --example typed_live_workflow
```
Enable writes explicitly:
```bash
set JORTT_ALLOW_WRITES=true
cargo run --example typed_live_workflow
```
### 3) Full operation smoke
```bash
cargo run --example full_openapi_smoke
```
Enable mutations:
```bash
set JORTT_RUN_MUTATIONS=true
cargo run --example full_openapi_smoke
```
## PowerShell Setup Example
```powershell
$env:JORTT_CLIENT_ID = "your-client-id"
$env:JORTT_CLIENT_SECRET = "your-client-secret"
$env:JORTT_PARAM_CUSTOMER_ID = "408d4652-b07a-4195-817e-0390bb0c9428"
$env:JORTT_PARAM_INVOICE_ID = "b3b0b7c4-9dab-4ca7-b1c0-16b0ebbb75f7"
cargo run --example typed_live_workflow
```
## Mutation Safety Notes
- Mutation examples are opt-in by environment flag.
- Use a sandbox/test organization whenever possible.
- For broad smoke runs, start read-only first, then enable mutations incrementally with scoped params/bodies.
- Failing operation lines are printed as `FAIL <METHOD> <PATH> -> <error>` and execution continues, so you can see complete coverage state in one run.
## Troubleshooting
### `access_token.invalid` or `invalid_client`
- Confirm `JORTT_CLIENT_ID` and `JORTT_CLIENT_SECRET` are valid for the target org.
- If supplying `JORTT_ACCESS_TOKEN`, ensure it is not expired and belongs to expected scopes.
### Frequent `SKIP ... missing path param env`
- Add required `JORTT_PARAM_<NAME>` variables matching each path placeholder.
- For common placeholders like `{id}`, set `JORTT_PARAM_ID`.
### `params.invalid`
- Supply required query/body fixtures for that operation:
- `JORTT_QUERY_<METHOD>_<PATH_KEY>`
- `JORTT_BODY_<METHOD>_<PATH_KEY>`
### PDF download endpoint failures
- Invoice PDF URLs can require already-sent invoices.
- Test against invoice records in a send-complete state.