2.5.0 #10

Merged
rune merged 41 commits from 2.5.0 into main 2026-08-03 08:33:23 +02:00
3 changed files with 0 additions and 248 deletions
Showing only changes of commit 1f6a62d2d7 - Show all commits
-20
View File
@@ -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)
}
}