Skip to content

Adds Invoke.Handler conformance case - #216

Merged
johnnyt merged 1 commit into
mainfrom
st-718j-handler-conformance-case
Aug 22, 2026
Merged

Adds Invoke.Handler conformance case#216
johnnyt merged 1 commit into
mainfrom
st-718j-handler-conformance-case

Conversation

@johnnyt

@johnnyt johnnyt commented Aug 22, 2026

Copy link
Copy Markdown
Member

Why

The Statifier.Invoke.Handler contract (ADR-0051 decision 4, docs/extending.md) binds downstream implementations only as prose: planning callbacks must be pure, perform/2 must be idempotent on invoke_id, cancel of an unknown invocation must not raise, {:error, _} from start/2 becomes error.execution, and exceptions are never rescued by the library. st-718j asks for a mechanical pin any handler implementation can run against itself, so every host handler gets contract coverage from day one and the contract stays pinned by tests rather than docs alone.

What

  • Statifier.Testing.HandlerCase (new, ADR-0065): used alongside the host's own use ExUnit.Case with handler: and type: options, it generates seven conformance tests. Every check is also a public assertion function for suites that want them individually; fixtures (conformance_invoke/0, conformance_ctx/0, conformance_event/0) are overridable.
  • Idempotency is judged against an implementor-declared observation point (observed_effects/1); a handler that routes work to perform/2 with none declared flunks naming the override to write (fail-not-skip, ADR-0053), never passes silently.
  • The two library-half pins (error.execution surfacing via a minimal driving chart, exception propagation) run with case-internal probe handlers registered under the implementor's own type string, so they execute in every downstream suite.
  • Docs: new "Testing your handler" section in docs/extending.md; ADR-0065 records the shape decisions (split-use over a second CaseTemplate, probe pins, observation-point discipline).
  • Changelog fragment changelog.d/st-718j.md - a published testing module is public API.

Notes

  • Independent of Adds caller_context per ADR-0063 #215 (caller_context); ADR-0065 records caller-context-aware conformance assertions as a follow-up once that lands, not a rider here.
  • Every new literal test carries a verified sabotage note; the seven generated tests have no literal test blocks in the test file, so the two chart-driven library pins were sabotage-verified against Statifier.Session.Effects.plan_invoke/3 and the mutations are documented in a comment above the use site.
  • Gate: full mix quality green (2,497 tests, 96.3% coverage) and mix quality --profile merge green including the ADR judge. Skips were not-applicable only (gettext).

Closes: st-718j

Publishes Statifier.Testing.HandlerCase (ADR-0065), a reusable
conformance case any Statifier.Invoke.Handler implementation runs
against itself alongside its own `use ExUnit.Case`:

- start/2, cancel/2, and forward/3 are checked deterministic and
  observably effect-free; cancel of an unknown invoke_id must be a
  no-op, never a raise.
- perform/2 is checked idempotent on invoke_id against an
  implementor-declared observation point (observed_effects/1); a
  handler that performs with no observation point declared flunks
  naming the override to write, never passes silently.
- The library-half pins run with case-internal probe handlers under
  the implementor's own type string: {:error, _} from start/2
  surfaces as error.execution in a minimal driving chart, and
  handler exceptions propagate un-rescued.

Every check is also a public function for suites that want them one
at a time; fixtures (invoke, ctx, event) are overridable. Documents
the case in docs/extending.md and adds a changelog fragment - a
published testing module is public API.

Refs: st-718j
@johnnyt
johnnyt merged commit 19eac3d into main Aug 22, 2026
1 check passed
@johnnyt
johnnyt deleted the st-718j-handler-conformance-case branch August 22, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant