Files
Stirling-PDF/testing/cucumber/features/payg/README.md
T
2026-06-16 16:48:30 +01:00

59 lines
2.5 KiB
Markdown

# PAYG cucumber scenarios
End-to-end coverage for the PAYG shadow charging engine (PR #6519 / PR-S3
in `notes/PAYG_DESIGN.md` §7.5).
## Running locally
```bash
./testing/test-payg.sh
```
That script:
1. Boots `testing/compose/docker-compose-saas.yml` (Stirling-PDF with
`STIRLING_FLAVOR=saas` + a Postgres holding the `stirling_pdf` schema)
2. Waits for backend health
3. Pipes `testing/compose/payg/saas-seed.sql` into the test postgres,
creating a `payg-cucumber-team` flipped to `wallet_policy.engine =
'PAYG_SHADOW'` and a test user with API key `payg-cucumber-key`
4. Runs `python -m behave features/payg`
5. Tears the stack down
## What's covered (automated, run by `docker-compose-tests-saas.yml` on CI)
| Scenario | Validates |
|---|---|
| First tool call writes a CHARGED row | Filter + interceptor fire end-to-end; shadow row written |
| Lineage join — second call on output | `JobService.joinOrOpen` lineage matching; no new shadow row |
| First-step 5xx refunds + closes the process | `markFirstStepFailed` flips row to REFUNDED, job to CLOSED |
| 4xx leaves the row CHARGED | "customer paid for the attempt" semantics |
| ZIP-returning tool records per-PDF OUTPUT | `PaygOutputExtractor` unpacks + records signatures |
| Multi-file input writes a single shadow row | Multi-input group sizing |
| `X-Stirling-Automation` sets PIPELINE source | Header → `JobSource` detection |
The 5xx scenario drives the refund path through `PaygCucumberThrowController`
— a `@Profile("payg-cucumber")` stub in `app/saas/.../payg/test/` that always
throws. The profile is activated by `docker-compose-saas.yml`'s
`SPRING_PROFILES_ACTIVE=saas,payg-cucumber` and is never set in production.
## Manual-only scenarios
One part of the shadow engine can't reasonably be driven from this suite
and is verified by hand each time its code path changes. The procedure
lives in `notes/PAYG_DESIGN.md` §7.5.2 "PAYG cucumber: manual-only
scenarios".
- **Kill-switch (`PAYG_FILTER_ENABLED=false`).** Needs a docker-container
restart mid-suite; orchestrating that in behave is more harness fragility
than it's worth for a flag that's only flipped during incident response.
## Fixtures
The scenarios reuse `testing/cucumber/exampleFiles/`:
- `ghost1.pdf` — single-page reference PDF
- `tables.pdf` — multi-page input for split / ZIP scenarios
If those filenames change in the main cucumber harness, update
`features/steps/payg_step_definitions.py` SINGLE_PAGE_PDF / THREE_PAGE_PDF
constants to match.