test(contract): 21 public endpoints that no test had ever called - #456
Conversation
gate-25 (contract-coverage) FAIL 25 — twenty-five public endpoints reachable through appinfo/routes.php with nothing asserting their contract. Ten new PHPUnit controller tests close twenty-one of them. WHAT WAS ACTUALLY MISSING Not obscure corners. `transcription#transcribe`, `#realign`, `#attach`, `#sources`; the whole `motionCoauthor` surface (add, remove, updateText, history); `boardEvaluation#respond`; `liveMeeting#recordLiveDecision`; `integration#getOutcome` and `#subscribe`; `participation#submitAnonymousReaction`; plus the framework endpoints (`api#preflight`, `ori#preflight*`, `dashboard#page`/`#catchAll`, `health#statusOptions`, `actionItem#destroy`). The tests assert the CONTRACT, not that a method exists: status codes on the happy path, the shape of the JSON body, and the refusal paths — 422 without consent, 503 without a provider, 404 for an unknown id, and the authorisation denial for a non-staff caller. Roughly half the assertions are refusals, which is the half an endpoint written without tests usually gets wrong. NO WAIVERS Zero `@contract exclude` in this change. Every one of the twenty-one is closed by a test that runs. That includes the endpoints where an exclude would have been easy to argue — the CORS preflights get real tests asserting their headers and 204, because "it is only a preflight" is a claim about behaviour and behaviour is testable. THE TESTS RUN, WHICH IS THE ONLY THING THAT MAKES THEM COVERAGE ./vendor/bin/phpunit tests/Unit/Controller/<the ten new files> OK (72 tests, 176 assertions) <- 0 skipped Whole directory, to show nothing else moved: Tests: 250, Assertions: 662, Skipped: 1 The single skip is pre-existing and unrelated — `DecisionControllerTest::testPublishSucceedsReturns200`, already parked against decidesk#90. No test in this change is skipped, incomplete, or risky. MEASURED (gate package ConductionNL/.github @ b8c7eade, full scope, rebased onto 012f96b): before 19=984 25=25 26=5 54=2 63=2 53 PASS, skips 24/29/33/47/48/61 after 19=984 25=4 26=5 54=2 63=2 53 PASS, skips 24/29/33/47/48/61 Skip set byte-identical; no other gate moved. PASS is unchanged because gate-25 is still red — which is the honest outcome, not a rounding-up. WHAT REMAINS, DELIBERATELY UNCLOSED Four endpoints, named rather than waved at: participationBudget#castAdvisoryVote /api/participation/proposals/{id}/vote participationBudget#publishBudgetResults /api/participation/budgets/{id}/publish settings#getPublicationConfig /api/settings/publication-config settings#setPublicationConfig /api/settings/publication-config They are not excluded and not annotated. gate-25 stays red until they have real tests, which is the correct signal.
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 548/548 | |||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 09:47 UTC
Download the full PDF report from the workflow artifacts.
|
Merging with evidence — the two red checks are provably not this change. quality / E2E Tests (Playwright) — identical to the base:
quality / Quality Report is a pure aggregator of the above. The checks that actually exercise this change are green:
gate-25 goes 25 -> 4 with zero |
gate-25 (contract-coverage) FAIL 25 — twenty-five public endpoints reachable
through appinfo/routes.php with nothing asserting their contract. Ten new
PHPUnit controller tests close twenty-one of them.
WHAT WAS ACTUALLY MISSING
Not obscure corners.
transcription#transcribe,#realign,#attach,#sources; the wholemotionCoauthorsurface (add, remove, updateText,history);
boardEvaluation#respond;liveMeeting#recordLiveDecision;integration#getOutcomeand#subscribe;participation#submitAnonymousReaction; plus the framework endpoints(
api#preflight,ori#preflight*,dashboard#page/#catchAll,health#statusOptions,actionItem#destroy).The tests assert the CONTRACT, not that a method exists: status codes on the
happy path, the shape of the JSON body, and the refusal paths — 422 without
consent, 503 without a provider, 404 for an unknown id, and the authorisation
denial for a non-staff caller. Roughly half the assertions are refusals, which is
the half an endpoint written without tests usually gets wrong.
NO WAIVERS
Zero
@contract excludein this change. Every one of the twenty-one is closed bya test that runs. That includes the endpoints where an exclude would have been
easy to argue — the CORS preflights get real tests asserting their headers and
204, because "it is only a preflight" is a claim about behaviour and behaviour is
testable.
THE TESTS RUN, WHICH IS THE ONLY THING THAT MAKES THEM COVERAGE
./vendor/bin/phpunit tests/Unit/Controller/
OK (72 tests, 176 assertions) <- 0 skipped
Whole directory, to show nothing else moved:
Tests: 250, Assertions: 662, Skipped: 1
The single skip is pre-existing and unrelated —
DecisionControllerTest::testPublishSucceedsReturns200, already parked againstdecidesk#90. No test in this change is skipped, incomplete, or risky.
MEASURED (gate package ConductionNL/.github @ b8c7eade, full scope, rebased onto
012f96b):
before 19=984 25=25 26=5 54=2 63=2 53 PASS, skips 24/29/33/47/48/61
after 19=984 25=4 26=5 54=2 63=2 53 PASS, skips 24/29/33/47/48/61
Skip set byte-identical; no other gate moved. PASS is unchanged because gate-25
is still red — which is the honest outcome, not a rounding-up.
WHAT REMAINS, DELIBERATELY UNCLOSED
Four endpoints, named rather than waved at:
participationBudget#castAdvisoryVote /api/participation/proposals/{id}/vote
participationBudget#publishBudgetResults /api/participation/budgets/{id}/publish
settings#getPublicationConfig /api/settings/publication-config
settings#setPublicationConfig /api/settings/publication-config
They are not excluded and not annotated. gate-25 stays red until they have real
tests, which is the correct signal.
🤖 Generated with Claude Code