.vbw-planning/milestones/03-coverage-analysis-quick-wins-critical-path-test-co/phases/02-critical-path-test-coverage/PLAN-01.md
Close the coverage gap in lib/source_monitor/fetching/feed_fetcher.rb (currently 245 uncovered lines out of 627). The existing test file covers basic RSS/Atom/JSON fetching, 304 handling, timeout/HTTP/parsing failures, and adaptive interval mechanics. This plan targets the remaining uncovered branches: retry strategy application, circuit breaker state transitions, connection error wrapping, last_modified header handling, entry processing edge cases, jitter computation, and private helper methods.
Decomposition rationale: FeedFetcher is the single largest coverage gap (245 lines). It is tested in isolation from ItemCreator (which has its own plan). The uncovered code falls into distinct categories that can each be addressed as a focused task: (1) retry/circuit breaker logic, (2) Faraday error wrapping and connection failures, (3) header and metadata management, (4) entry processing edge cases, (5) jitter and interval helpers. Each task adds test methods to the existing test file.
Trade-offs considered:
What constrains the structure:
jitter: ->(_) { 0 } pattern from existing tests should be reused to make interval assertions deterministictravel_to for time-sensitive assertions
</context>
test/lib/source_monitor/fetching/feed_fetcher_test.rbbin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb -n /retry|circuit/ exits 0test/lib/source_monitor/fetching/feed_fetcher_test.rbto_raise for each error type. Assert the result.error class, message, and original_error.bin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb -n /connection|ssl|client_error|unexpected|faraday/i exits 0test/lib/source_monitor/fetching/feed_fetcher_test.rb.with(headers: {...}) and return specific response headers.bin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb -n /last_modified|custom_header|if_modified/i exits 0test/lib/source_monitor/fetching/feed_fetcher_test.rbbin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb -n /entry_processing|item_processor|normalize_error|safe_entry/i exits 0test/lib/source_monitor/fetching/feed_fetcher_test.rbcall method by configuring specific fetching settings and verifying the resulting source state. Alternatively, use send for the pure-function helpers.bin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb -n /jitter|body_digest|metadata|configured_|extract_numeric/i exits 0bin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb exits 0COVERAGE=1 bin/rails test test/lib/source_monitor/fetching/feed_fetcher_test.rb shows feed_fetcher.rb with >80% branch coveragebin/rails test exits 0 (no regressions)