Skip to content

test: raise line coverage from 66% to 96% - #63

Merged
hjemmel merged 1 commit into
masterfrom
test/improve-coverage
Aug 11, 2026
Merged

hjemmel merged 1 commit into
masterfrom
test/improve-coverage

Conversation

@hjemmel

@hjemmel hjemmel commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

Tests only — no production code was changed (git diff master --stat touches nothing under src/).

Metric Before After
Classes 38.88% (7/18) 77.77% (14/18)
Methods 62.96% (34/54) 92.59% (50/54)
Lines 66.66% (156/234) 95.72% (224/234)
Tests 38 84
Assertions 100 195

What's newly covered

HttpErrorHandler 0% → 100% — all six HttpException subtypes via a data provider, the generic-exception path, and both displayErrorDetails branches. Includes an assertion that internal details never leak when the flag is off.

DatabaseWrapper 0% → 100% — this is the class I'd previously said would need the Firebase emulator. That was wrong. Reference and ApiClient are final and unmockable, but ApiClient's constructor takes Guzzle's ClientInterface, and Kreait\Firebase\Database is publicly constructible. So the tests drive the real SDK stack against a Guzzle MockHandler with canned HTTP responses — no emulator, no live database, fully deterministic, and it runs in CI. Covers the HTTP verb and request body for each operation plus the null-key guard in push().

ShutdownHandler 0% → 89%, ResponseEmitter 0% → 100% — message formatting per error type, asserted through the emitted JSON body, plus the buffer-discard path that stops stray output reaching the client. Each runs #[RunInSeparateProcess] since they touch process globals.

Action 80% → 100%resolveArg's rejection path and the domain-exception-to-HTTP-404 translation, via a minimal concrete subclass.

ActionPayload, ActionError, SessionMiddleware — all to 100%.

The ten lines still uncovered

Each has a concrete reason rather than being an oversight:

Location Why
ShutdownHandler:57-59 The E_USER_ERROR branch. trigger_error() with E_USER_ERROR halts the process, which would kill the test run.
JsonBodyParserMiddleware:23 Reads php://input directly, always empty under the CLI SAPI.
FirebaseTodoRepository:20-24 The Factory branch needs real Firebase credentials.
InMemoryTodoRepository:33 Xdebug line-attribution artifact — the closing ]; of a multi-line array literal is marked executable but never recorded as hit. Lines 27–32 are covered, so the default array is genuinely constructed. No test can reach it.

Suggested follow-up (not done here)

JsonBodyParserMiddleware reads php://input directly instead of $request->getBody(). Switching to the PSR-7 body would be equivalent in production — Slim populates the request body from php://input anyway — and would make the JSON-parsing path testable. I left it alone since it's a behaviour change to production code and this PR is deliberately tests-only.

🤖 Generated with Claude Code

Adds tests only - no production code was changed.

  Classes  38.88% -> 77.77%  (7/18  -> 14/18)
  Methods  62.96% -> 92.59%  (34/54 -> 50/54)
  Lines    66.66% -> 95.72%  (156   -> 224 of 234)
  Tests    38 -> 84, assertions 100 -> 195

New coverage:
- HttpErrorHandler (0% -> 100%): all six HttpException subtypes via a data
  provider, plus the generic-exception path and both displayErrorDetails
  branches, asserting details never leak when the flag is off.
- DatabaseWrapper (0% -> 100%): Kreait's Reference and ApiClient are final and
  cannot be mocked, but ApiClient accepts a Guzzle ClientInterface. So the real
  SDK stack runs against a Guzzle MockHandler with canned responses - no
  emulator, no live database, deterministic in CI. Covers the HTTP verb and
  body for each operation and the null-key guard in push().
- ShutdownHandler / ResponseEmitter (0% -> 89% / 100%): message formatting per
  error type, asserted through the emitted JSON body, plus the buffer-discard
  path that keeps stray output from reaching the client.
- Action (80% -> 100%): resolveArg's rejection path and the domain-to-HTTP
  404 translation.
- ActionPayload, ActionError, SessionMiddleware: 100%.

Ten lines remain uncovered, each for a concrete reason:
- ShutdownHandler 57-59: the E_USER_ERROR branch. trigger_error() with
  E_USER_ERROR halts the process, which would kill the test run.
- JsonBodyParserMiddleware 23: reads php://input directly, always empty under
  the CLI SAPI. Reading $request->getBody() instead would make it testable.
- FirebaseTodoRepository 20-24: the Factory branch needs real credentials.
- InMemoryTodoRepository 33: an Xdebug line-attribution artifact - the closing
  bracket of a multi-line array literal is marked executable but never
  recorded as hit. Lines 27-32 are covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hjemmel
hjemmel merged commit 20f10d3 into master Aug 11, 2026
2 checks passed
@github-actions
github-actions Bot deleted the test/improve-coverage branch August 11, 2026 12:17
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