Repository navigation
Give CoreModule injectable side-effect ports - #78
Merged
Merged
Conversation
Inject ports so built-in commands are testable without CNContactStore, FileManager, or real timing: - ContactNameService (/name) + CNContactNameService adapter — no try! on contact ops; create-or-update behind one method - Clock — async sleep port; /send delays instant under test - SendRateLimiter — per-handle concurrency, deterministic (no async games) Remove dead FileManager.createDirectory try! from init; barf try! -> try?. Extract performSend for an awaitable send loop. Adds CoreModuleTests + SendRateLimiterTests (21 tests): every command happy path via JaredMock, /send validation + concurrency limit + delivery, /name auth/validation/create/update/throw, init no-filesystem. Built TDD, one behavior per cycle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Skeyelab
added a commit
that referenced
this pull request
Aug 23, 2026
Inject ports so built-in commands are testable without CNContactStore, FileManager, or real timing: - ContactNameService (/name) + CNContactNameService adapter — no try! on contact ops; create-or-update behind one method - Clock — async sleep port; /send delays instant under test - SendRateLimiter — per-handle concurrency, deterministic (no async games) Remove dead FileManager.createDirectory try! from init; barf try! -> try?. Extract performSend for an awaitable send loop. Adds CoreModuleTests + SendRateLimiterTests (21 tests): every command happy path via JaredMock, /send validation + concurrency limit + delivery, /name auth/validation/create/update/throw, init no-filesystem. Built TDD, one behavior per cycle. Co-authored-by: Eric Dahl <edahl@nd.edu> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #71
Summary
CoreModulewas the largest untested built-inRoutingModule(0% coverage, 173 lines) with fourtry!s on FileManager/Contacts/JSON. This injects side-effect ports so every command is testable, and removes thetry!s.ContactNameServiceport +CNContactNameServiceadapter —/nameno longer reachesCNContactStoredirectly. Adapter does authorization check + search + create-or-update behind onesetGivenName(_:forHandle:)that throws instead oftry!. Fakeable in tests.Clockport (RealClock) —/send's inter-message delay is an injected async sleep, so the send loop runs instantly and deterministically under test.SendRateLimiter— per-handle concurrency bookkeeping pulled out of/sendinto a sync, deterministic unit (replaces the inlinecurrentSendsdict +MAXIMUM_CONCURRENT_SENDS).FileManager.createDirectorytry!ininit(theappsupportURL was never used) — init now does no filesystem work and can't crash.barftry!→try?+"nil"fallback.performSend(_:text:times:delay:)for an awaitable send loop.Built with TDD
One behavior per cycle. Simple commands locked as characterization tests first, then new ports driven red→green:
SendRateLimiter(acquire/release/per-handle) →/senddelivery + concurrency rejection (fakeClock+ pre-filled limiter) →ContactNameService(/nameauth/validation/create/update/throw) → init no-filesystem.Test plan
bash ./.github/scripts/test-macos.sh— 146 tests, all pass (was 125)CoreModuleTests—/ping /version /whoami(named + unknown)/barfthanks;/sendvalidation (type/count/delay/text) + delivery + concurrency limit;/namenot-authorized / missing-arg / non-text / create+confirm / save-throws; init registers routes with no filesystem side effectsSendRateLimiterTests— acquire up to max, reject, release frees slot, per-handle quotaAcceptance criteria
JaredMock/sendconcurrency limit tested with injectable clock (+SendRateLimiter)/nametested without real Contacts permissiontry!on contact operations in production path (and removed the existing ones)🤖 Generated with Claude Code