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).
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// GitignoreParserTests.swift
|
||||
// oAITests
|
||||
//
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
// Copyright (C) 2026 Rune Olsen
|
||||
|
||||
import Testing
|
||||
@testable import oAI
|
||||
|
||||
@Suite("GitignoreParser")
|
||||
struct GitignoreParserTests {
|
||||
|
||||
private func parser(for content: String) -> GitignoreParser {
|
||||
var parser = GitignoreParser(rootPath: "/tmp/fake-root")
|
||||
parser.parseContent(content)
|
||||
return parser
|
||||
}
|
||||
|
||||
@Test("Simple extension wildcard matches at any depth")
|
||||
func extensionWildcard() {
|
||||
let p = parser(for: "*.log")
|
||||
#expect(p.isIgnored("debug.log"))
|
||||
#expect(p.isIgnored("nested/debug.log"))
|
||||
#expect(!p.isIgnored("debug.txt"))
|
||||
}
|
||||
|
||||
@Test("Directory pattern matches the directory and everything under it")
|
||||
func directoryPattern() {
|
||||
let p = parser(for: "build/")
|
||||
#expect(p.isIgnored("build"))
|
||||
#expect(p.isIgnored("build/output.txt"))
|
||||
#expect(p.isIgnored("foo/build/output.txt"))
|
||||
#expect(!p.isIgnored("rebuild"))
|
||||
}
|
||||
|
||||
@Test("Path-anchored pattern only matches that exact relative path, not nested occurrences")
|
||||
func pathAnchoredWildcard() {
|
||||
let p = parser(for: "src/*.tmp")
|
||||
#expect(p.isIgnored("src/foo.tmp"))
|
||||
#expect(!p.isIgnored("other/src/foo.tmp"))
|
||||
#expect(!p.isIgnored("src/sub/foo.tmp"))
|
||||
}
|
||||
|
||||
@Test("Double-star matches across any number of intermediate directories")
|
||||
func doubleStarPattern() {
|
||||
let p = parser(for: "**/logs")
|
||||
#expect(p.isIgnored("logs"))
|
||||
#expect(p.isIgnored("a/logs"))
|
||||
#expect(p.isIgnored("a/b/logs"))
|
||||
#expect(p.isIgnored("a/logs/file.txt"))
|
||||
#expect(!p.isIgnored("logsfile"))
|
||||
}
|
||||
|
||||
@Test("Negation un-ignores a path matched by an earlier rule")
|
||||
func negation() {
|
||||
let p = parser(for: "*.log\n!important.log")
|
||||
#expect(p.isIgnored("debug.log"))
|
||||
#expect(!p.isIgnored("important.log"))
|
||||
}
|
||||
|
||||
@Test("Comments and blank lines are skipped, not treated as patterns")
|
||||
func commentsAndBlankLines() {
|
||||
let p = parser(for: "# a comment\n\n*.log\n \n")
|
||||
#expect(p.isIgnored("x.log"))
|
||||
#expect(!p.isIgnored("# a comment"))
|
||||
}
|
||||
|
||||
@Test("Leading slash still matches (root-anchoring is not enforced by this implementation)")
|
||||
func leadingSlashPattern() {
|
||||
// Documents actual current behavior: the leading "/" is stripped without
|
||||
// truly restricting the match to the root level, unlike real git.
|
||||
let p = parser(for: "/dist")
|
||||
#expect(p.isIgnored("dist"))
|
||||
#expect(p.isIgnored("dist/file.txt"))
|
||||
}
|
||||
|
||||
@Test("No rules means nothing is ignored")
|
||||
func noRules() {
|
||||
let p = parser(for: "")
|
||||
#expect(!p.isIgnored("anything.txt"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user