Fix rename commit composition: drop unrelated test files, finish entitlements rename
Untrack ConversationListViewPureLogicTests.swift and NativeTextEditorPureLogicTests.swift — these belong to two other unrelated, unfinished features (conversation multi-select and input code formatting) and got swept in by an overly broad glob in the previous commit. Files remain on disk, just untracked again. Also stage the deletion of the old oAI.entitlements path — the earlier git mv to Confab.entitlements had its staged rename undone by an intermediate git reset, so the previous commit added the new file without ever removing the old one from tracking.
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<false/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<false/>
|
||||
<key>com.apple.security.personal-information.calendars</key>
|
||||
<true/>
|
||||
<key>com.apple.security.personal-information.reminders</key>
|
||||
<true/>
|
||||
<key>com.apple.security.personal-information.addressbook</key>
|
||||
<true/>
|
||||
<key>com.apple.security.personal-information.location</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// ConversationListViewPureLogicTests.swift
|
||||
// oAITests
|
||||
//
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
// Copyright (C) 2026 Rune Olsen
|
||||
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import Confab
|
||||
|
||||
@Suite("ConversationListView.idsInRange")
|
||||
struct ConversationListViewPureLogicTests {
|
||||
|
||||
private let ids = (0..<6).map { _ in UUID() }
|
||||
|
||||
@Test("Forward range includes anchor and target inclusive")
|
||||
func forwardRange() {
|
||||
let result = ConversationListView.idsInRange(orderedIds: ids, anchorId: ids[1], targetId: ids[4])
|
||||
#expect(result == Set(ids[1...4]))
|
||||
}
|
||||
|
||||
@Test("Backward range (target above anchor) still selects the span between them")
|
||||
func backwardRange() {
|
||||
let result = ConversationListView.idsInRange(orderedIds: ids, anchorId: ids[4], targetId: ids[1])
|
||||
#expect(result == Set(ids[1...4]))
|
||||
}
|
||||
|
||||
@Test("Anchor equal to target selects just that one id")
|
||||
func sameAnchorAndTarget() {
|
||||
let result = ConversationListView.idsInRange(orderedIds: ids, anchorId: ids[2], targetId: ids[2])
|
||||
#expect(result == [ids[2]])
|
||||
}
|
||||
|
||||
@Test("Nil anchor (first Shift-click) falls back to just the target")
|
||||
func nilAnchorFallsBackToTarget() {
|
||||
let result = ConversationListView.idsInRange(orderedIds: ids, anchorId: nil, targetId: ids[3])
|
||||
#expect(result == [ids[3]])
|
||||
}
|
||||
|
||||
@Test("Anchor no longer present in the ordered list falls back to just the target")
|
||||
func missingAnchorFallsBackToTarget() {
|
||||
let staleAnchor = UUID()
|
||||
let result = ConversationListView.idsInRange(orderedIds: ids, anchorId: staleAnchor, targetId: ids[3])
|
||||
#expect(result == [ids[3]])
|
||||
}
|
||||
|
||||
@Test("Single-element list selects that element")
|
||||
func singleElementList() {
|
||||
let solo = [ids[0]]
|
||||
let result = ConversationListView.idsInRange(orderedIds: solo, anchorId: ids[0], targetId: ids[0])
|
||||
#expect(result == [ids[0]])
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
//
|
||||
// NativeTextEditorPureLogicTests.swift
|
||||
// oAITests
|
||||
//
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
// Copyright (C) 2026 Rune Olsen
|
||||
|
||||
import Testing
|
||||
import Foundation
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
@testable import Confab
|
||||
|
||||
@Suite("NativeTextEditor.inlineCodeRanges")
|
||||
struct NativeTextEditorPureLogicTests {
|
||||
|
||||
@Test("No backticks yields no ranges")
|
||||
func noBackticks() {
|
||||
#expect(NativeTextEditor.inlineCodeRanges(in: "hello world").isEmpty)
|
||||
}
|
||||
|
||||
@Test("A single closed backtick pair is matched, backticks included")
|
||||
func singleClosedPair() {
|
||||
let text = "Hello `code` world"
|
||||
let ranges = NativeTextEditor.inlineCodeRanges(in: text)
|
||||
#expect(ranges.count == 1)
|
||||
let matched = (text as NSString).substring(with: ranges[0])
|
||||
#expect(matched == "`code`")
|
||||
}
|
||||
|
||||
@Test("An unterminated single backtick is not matched")
|
||||
func unterminatedBacktick() {
|
||||
let text = "Hello `code world"
|
||||
#expect(NativeTextEditor.inlineCodeRanges(in: text).isEmpty)
|
||||
}
|
||||
|
||||
@Test("Multiple closed pairs are all matched")
|
||||
func multiplePairs() {
|
||||
let text = "`one` and `two` and `three`"
|
||||
let ranges = NativeTextEditor.inlineCodeRanges(in: text)
|
||||
#expect(ranges.count == 3)
|
||||
let nsText = text as NSString
|
||||
#expect(ranges.map { nsText.substring(with: $0) } == ["`one`", "`two`", "`three`"])
|
||||
}
|
||||
|
||||
@Test("Backtick pair cannot span a newline")
|
||||
func doesNotSpanNewline() {
|
||||
let text = "`code\nblock`"
|
||||
#expect(NativeTextEditor.inlineCodeRanges(in: text).isEmpty)
|
||||
}
|
||||
|
||||
@Test("Empty string yields no ranges")
|
||||
func emptyString() {
|
||||
#expect(NativeTextEditor.inlineCodeRanges(in: "").isEmpty)
|
||||
}
|
||||
|
||||
@Test("Adjacent backtick pairs on the same line are each matched separately")
|
||||
func adjacentPairs() {
|
||||
let text = "`a``b`"
|
||||
let ranges = NativeTextEditor.inlineCodeRanges(in: text)
|
||||
let nsText = text as NSString
|
||||
#expect(ranges.map { nsText.substring(with: $0) } == ["`a`", "`b`"])
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("NativeTextEditor.fencedCodeBlockRanges")
|
||||
struct NativeTextEditorFencedBlockTests {
|
||||
|
||||
@Test("No fences yields no ranges")
|
||||
func noFences() {
|
||||
#expect(NativeTextEditor.fencedCodeBlockRanges(in: "hello world").isEmpty)
|
||||
}
|
||||
|
||||
@Test("A closed multi-line fence is matched in full, including the language tag")
|
||||
func closedMultilineFence() {
|
||||
let text = "```python\nprint(\"hi\")\n```"
|
||||
let ranges = NativeTextEditor.fencedCodeBlockRanges(in: text)
|
||||
#expect(ranges.count == 1)
|
||||
#expect((text as NSString).substring(with: ranges[0]) == text)
|
||||
}
|
||||
|
||||
@Test("An unterminated fence (no closing triple) is not matched")
|
||||
func unterminatedFence() {
|
||||
let text = "```python\nprint(\"hi\")"
|
||||
#expect(NativeTextEditor.fencedCodeBlockRanges(in: text).isEmpty)
|
||||
}
|
||||
|
||||
@Test("Text before and after a fence is excluded from the match")
|
||||
func surroundingTextExcluded() {
|
||||
let text = "before\n```\ncode\n```\nafter"
|
||||
let ranges = NativeTextEditor.fencedCodeBlockRanges(in: text)
|
||||
#expect(ranges.count == 1)
|
||||
#expect((text as NSString).substring(with: ranges[0]) == "```\ncode\n```")
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("NativeTextEditor.codeStyledRanges")
|
||||
struct NativeTextEditorCodeStyledRangesTests {
|
||||
|
||||
@Test("Combines a fenced block and a separate inline span")
|
||||
func combinesFencedAndInline() {
|
||||
let text = "See `foo` then:\n```\nbar\n```"
|
||||
let ranges = NativeTextEditor.codeStyledRanges(in: text)
|
||||
let nsText = text as NSString
|
||||
#expect(ranges.map { nsText.substring(with: $0) } == ["`foo`", "```\nbar\n```"])
|
||||
}
|
||||
|
||||
@Test("A backtick inside a fenced block's own content is not separately re-matched as inline")
|
||||
func backtickInsideFenceNotDoubleMatched() {
|
||||
let text = "```\nuse `code` here\n```"
|
||||
let ranges = NativeTextEditor.codeStyledRanges(in: text)
|
||||
#expect(ranges.count == 1)
|
||||
#expect((text as NSString).substring(with: ranges[0]) == text)
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("NativeTextEditor.fencedCodeBlocks (language + code-content extraction)")
|
||||
struct NativeTextEditorFencedCodeBlocksTests {
|
||||
|
||||
@Test("Extracts the language tag and the code content, excluding fences and the tag line")
|
||||
func extractsLanguageAndCodeContent() {
|
||||
let text = "```python\nprint(\"hi\")\n```"
|
||||
let blocks = NativeTextEditor.fencedCodeBlocks(in: text)
|
||||
#expect(blocks.count == 1)
|
||||
#expect(blocks[0].language == "python")
|
||||
let nsText = text as NSString
|
||||
#expect(nsText.substring(with: blocks[0].codeRange) == "print(\"hi\")\n")
|
||||
}
|
||||
|
||||
@Test("No language tag yields a nil language")
|
||||
func noLanguageTagYieldsNil() {
|
||||
let text = "```\ncode\n```"
|
||||
let blocks = NativeTextEditor.fencedCodeBlocks(in: text)
|
||||
#expect(blocks.count == 1)
|
||||
#expect(blocks[0].language == nil)
|
||||
}
|
||||
|
||||
@Test("Language alias is passed through as typed, unresolved (SyntaxHighlighter resolves aliases itself)")
|
||||
func languageAliasPassthrough() {
|
||||
let text = "```py\nprint(1)\n```"
|
||||
let blocks = NativeTextEditor.fencedCodeBlocks(in: text)
|
||||
#expect(blocks[0].language == "py")
|
||||
}
|
||||
|
||||
@Test("Unterminated fence yields no blocks")
|
||||
func unterminatedFenceYieldsNoBlocks() {
|
||||
#expect(NativeTextEditor.fencedCodeBlocks(in: "```python\nprint(1)").isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("SyntaxHighlighter runs → NSColor")
|
||||
struct SyntaxHighlighterBridgingTests {
|
||||
|
||||
// NB: bridging via `NSAttributedString(highlighted)` does NOT work — that path stores
|
||||
// SwiftUI's `.foregroundColor` under a private `SwiftUI.ForegroundColor` key, not the
|
||||
// standard Cocoa `.foregroundColor` key (confirmed empirically before landing on this
|
||||
// `.runs`-based approach, which is what `NativeTextEditor` actually uses in production).
|
||||
|
||||
@Test("A Python keyword's foreground color is readable via AttributedString.runs and converts to NSColor")
|
||||
func keywordColorReadableViaRuns() {
|
||||
let highlighted = SyntaxHighlighter.highlight(code: "def foo():", language: "python")
|
||||
#expect(!highlighted.runs.isEmpty)
|
||||
|
||||
var foundKeywordColor = false
|
||||
let expected = NSColor(SyntaxHighlighter.keywordColor)
|
||||
for run in highlighted.runs {
|
||||
guard let color = run.foregroundColor else { continue }
|
||||
if NSColor(color).usingColorSpace(.deviceRGB) == expected.usingColorSpace(.deviceRGB) {
|
||||
foundKeywordColor = true
|
||||
}
|
||||
}
|
||||
#expect(foundKeywordColor)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user