Files
oai-swift/oAITests/ConversationNotesServiceTests.swift
T
rune 3414e37e24 Add per-conversation notes.md
Gives each conversation an opt-in, persistent memory file the model reads
automatically every turn and writes to on its own initiative via a fenced
```update-notes``` block in its reply — no per-write approval, matching the
Confab-as-CLAUDE.md-for-itself concept Rune wanted. /notes on|off|show,
files live in ~/Library/Application Support/oAI/notes/, embedded ID header
for future Git Sync compatibility. Adds DB migration v12.
2026-08-04 07:58:47 +02:00

66 lines
2.8 KiB
Swift

//
// ConversationNotesServiceTests.swift
// oAITests
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen
import Testing
import Foundation
@testable import Confab
@Suite("ConversationNotesService")
struct ConversationNotesServiceTests {
@Test("makeFilename sanitizes the conversation name and appends a short ID suffix")
func makeFilenameSanitizesAndSuffixes() {
let id = UUID(uuidString: "A3F2B1C0-0000-0000-0000-000000000000")!
let filename = ConversationNotesService.shared.makeFilename(conversationName: "My Recipe Chat", conversationId: id)
#expect(filename == "My Recipe Chat-a3f2.md")
}
@Test("makeFilename sanitizes invalid filename characters in the conversation name")
func makeFilenameSanitizesInvalidChars() {
let id = UUID(uuidString: "A3F2B1C0-0000-0000-0000-000000000000")!
let filename = ConversationNotesService.shared.makeFilename(conversationName: "Q&A: What/Why?", conversationId: id)
#expect(filename == "Q&A- What-Why--a3f2.md")
}
@Test("makeFilename falls back to Untitled for an empty conversation name")
func makeFilenameFallsBackForEmptyName() {
let id = UUID(uuidString: "A3F2B1C0-0000-0000-0000-000000000000")!
let filename = ConversationNotesService.shared.makeFilename(conversationName: "", conversationId: id)
#expect(filename == "Untitled-a3f2.md")
}
@Test("write then readBody round-trips the body with the ID header stripped")
func writeReadRoundTrip() {
let id = UUID()
let filename = "test-notes-\(UUID().uuidString).md"
defer { ConversationNotesService.shared.delete(filename: filename) }
ConversationNotesService.shared.write(body: "User prefers dark roast coffee.", filename: filename, conversationId: id)
let body = ConversationNotesService.shared.readBody(filename: filename)
#expect(body == "User prefers dark roast coffee.")
}
@Test("readBody on a nonexistent file returns nil, not an error")
func readBodyMissingFileReturnsNil() {
let body = ConversationNotesService.shared.readBody(filename: "definitely-does-not-exist-\(UUID().uuidString).md")
#expect(body == nil)
}
@Test("stripIDHeader removes the embedded ID line and following blank line")
func stripIDHeaderRemovesHeader() {
let content = "**ID**: `12345678-1234-1234-1234-123456789012`\n\nActual notes content."
#expect(ConversationNotesService.stripIDHeader(from: content) == "Actual notes content.")
}
@Test("stripIDHeader leaves content without the header untouched")
func stripIDHeaderLeavesUnheaderedContentUntouched() {
let content = "Just some content, no header."
#expect(ConversationNotesService.stripIDHeader(from: content) == content)
}
}