Commit Graph
3 Commits
Author SHA1 Message Date
rune a053d4a983 Phase 2: tests for the provider layer and other exposed pure helpers
66 new tests across 8 files (93 total in the suite now):

- GitSyncServiceTests: convertToSSH/injectCredentials/sanitizeFilename/
  detectSecretsInText, including a below-threshold false-positive check
  on the secret regex.
- ChatViewModelPureLogicTests: detectGoodbyePhrase, inferProvider,
  calculateCost -- including the cache-read (0.1x) / cache-write (1.25x)
  pricing multipliers, which is real billing-affecting logic.
- EmbeddingServiceTests / ContextSelectionServiceTests: embedding
  (de)serialization round-trip, importance-score weighting, and the
  token-estimate fallback (content.count / 4) when no real count exists.
- OpenRouterProviderTests / OllamaProviderTests / OpenAIProviderTests /
  AnthropicProviderTests: request-building (attachments, online mode,
  cache_control breakpoints, o1/o3 temperature omission, tool schema
  conversion) and response-parsing (text, tool_use blocks, empty-choices
  fallback behavior) for all four providers, with no network involved.

Also marks calculateCost/inferProvider/detectGoodbyePhrase (ChatViewModel)
and serializeEmbedding/deserializeEmbedding (EmbeddingService) as
`nonisolated` -- discovered via the actual test failures, not
speculation: the project's `SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor`
setting isolates the classes that carry an explicit `@MainActor`
(ChatViewModel), so calling their static members from a plain
synchronous @Test needs the pure ones marked `nonisolated`. Matches
the existing convention already used elsewhere in EmbeddingService
(cosineSimilarity was already nonisolated before this change).

Phase 2 of the test-suite rollout plan (peaceful-baking-kurzweil).
2026-07-23 14:11:50 +02:00
rune 1f4a2caf67 Phase 1: pure-logic tests requiring zero production code changes
27 tests across 4 files, all targeting code that was already testable
the moment the target existed -- no visibility bumps, no refactors:

- GitignoreParserTests: MCPService.GitignoreParser's glob-to-regex
  matching (wildcards, **, directory anchors, negation, comments).
- OpenRouterModelsTests: the string-vs-content-block-array decoders
  on both the request side (APIMessage.MessageContent/ContentItem)
  and response side (Choice.MessageContent, StreamChoice.Delta),
  including image extraction from content blocks.
- AIProviderTests: ChatResponse/Usage decoding, with an explicit
  regression guard that Usage.rawCostUSD always decodes to nil (it's
  only ever set programmatically, never from API JSON).
- MessageCodableTests: confirms Message's transient fields
  (isStreaming, isStarred, generatedImages, toolCalls,
  thinkingContent) don't survive an encode/decode round-trip, and
  documents that its custom == deliberately ignores role/timestamp/
  attachments/modelId -- a real but non-obvious behavior worth
  locking in with a test.

Removed the placeholder oAITests.swift example test now that there's
real coverage. Phase 1 of the test-suite rollout plan
(peaceful-baking-kurzweil).
2026-07-23 13:37:49 +02:00
rune 8c7fb59d41 Add real oAITests target; remove disconnected SPM test scaffold
The old Tests/oAITests/oAITests.swift + root Package.swift/Sources/
were a swift package init stub that @testable imported a fake empty
oAI module, completely disconnected from the real ~31K-line app
(built only via oAI.xcodeproj). Running `swift test` there would
have silently "passed" while testing nothing.

oAITests is a proper Unit Testing Bundle target added via Xcode's
target editor, wired into the app's scheme (TestAction references
oAITests.xctest). Verified with `xcodebuild test` before and after
removing the dead scaffold.

First phase of the test-suite rollout plan (peaceful-baking-kurzweil).
2026-07-23 13:30:45 +02:00