Rename app from oAI to Confab
"oAI" reads as easily confused with OpenAI, both visually and in casual conversation. Renamed to "Confab" throughout: Xcode target/scheme/bundle ID (com.oai.Confab), Info.plist and Help Book identity, all user-facing UI text, internal Log subsystem and color identifiers, localization catalogs (6 languages, including a proper reworded/retranslated Intel-deprecation notice), Help Book HTML content, and docs (README/DEVELOPMENT/PRIVACY/SECURITY). Deliberately cosmetic-only: the on-disk data folder (~/Library/Application Support/oAI/), database/backup filenames, Keychain service identifiers, and EncryptionService's key-derivation inputs are all left untouched so existing conversations, settings, and stored API keys survive the update with zero migration and no re-entering credentials. Verified live: a real signed build successfully decrypted a stored API key and loaded an existing conversation database after the bundle ID change. Also includes a small already-completed, previously uncommitted model-release-date feature (ModelInfo/OpenRouterModels/ OpenRouterProvider/ModelInfoView) that happened to share several files with this rename. Gitignored on this branch and updated on disk but not part of this commit: CLAUDE.md, RELEASE_NOTES.md, and the build*.sh scripts.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// 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]])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user