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

2.5 KiB

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

./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.