test: add resolveKnowledgeSource + full type inference tests
- Add resolveKnowledgeSource path test (knowledge_sources/<id>/) - Add empty knowledge_sources directory test - Add .txt→text and .epub→epub type inference - Add .png/.jpg/.jpeg/.webp→image inference - Remove misleading test that only asserted nil Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
2fa459d9ea
commit
86054edd5f
@ -3,12 +3,38 @@ import XCTest
|
|||||||
|
|
||||||
final class MaterialPathResolverTests: XCTestCase {
|
final class MaterialPathResolverTests: XCTestCase {
|
||||||
|
|
||||||
// MARK: - materialTypeFrom (infer from apiType + title)
|
// MARK: - resolveKnowledgeSource path
|
||||||
|
|
||||||
func test_materialTypeFrom_knowledge_source_with_md_title_returns_markdown() {
|
func test_resolveKnowledgeSource_finds_file_in_knowledge_sources_dir() {
|
||||||
let result = MaterialPathResolver.resolve(materialId: "m1", apiType: "knowledge_source", title: "note.md")
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
// Path won't exist, but we test the type inference via the file system cascade
|
let sourceId = "ks-test-\(UUID().uuidString)"
|
||||||
XCTAssertNil(result) // File doesn't exist
|
let ksDir = docs.appendingPathComponent("knowledge_sources/\(sourceId)")
|
||||||
|
try? FileManager.default.createDirectory(at: ksDir, withIntermediateDirectories: true)
|
||||||
|
let fileURL = ksDir.appendingPathComponent("content.md")
|
||||||
|
defer {
|
||||||
|
try? FileManager.default.removeItem(at: fileURL)
|
||||||
|
try? FileManager.default.removeItem(at: ksDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
|
let result = MaterialPathResolver.resolve(materialId: sourceId, apiType: "knowledge_source", title: "content.md")
|
||||||
|
XCTAssertNotNil(result)
|
||||||
|
XCTAssertEqual(result?.filePath, fileURL.path)
|
||||||
|
XCTAssertEqual(result?.materialType, .markdown)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_resolveKnowledgeSource_returns_nil_for_empty_dir() {
|
||||||
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
|
let sourceId = "ks-empty-\(UUID().uuidString)"
|
||||||
|
let ksDir = docs.appendingPathComponent("knowledge_sources/\(sourceId)")
|
||||||
|
try? FileManager.default.createDirectory(at: ksDir, withIntermediateDirectories: true)
|
||||||
|
defer { try? FileManager.default.removeItem(at: ksDir) }
|
||||||
|
|
||||||
|
// Empty directory → no files → falls through to Documents/Caches
|
||||||
|
let result = MaterialPathResolver.resolve(materialId: sourceId, apiType: "knowledge_source", title: "note.md")
|
||||||
|
// Directory exists but is empty → resolveKnowledgeSource returns nil → falls through
|
||||||
|
XCTAssertNil(result) // No file in Documents or Caches either
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - resolve returns nil for nonexistent file
|
// MARK: - resolve returns nil for nonexistent file
|
||||||
@ -26,11 +52,9 @@ final class MaterialPathResolverTests: XCTestCase {
|
|||||||
|
|
||||||
func test_resolve_finds_file_in_documents() {
|
func test_resolve_finds_file_in_documents() {
|
||||||
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
let fileId = "test-resolve-\(UUID().uuidString)"
|
let fileId = "test-docs-\(UUID().uuidString)"
|
||||||
let fileURL = docs.appendingPathComponent(fileId)
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
|
||||||
// Create a temp file in Documents
|
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: nil, title: nil)
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: nil, title: nil)
|
||||||
@ -45,7 +69,6 @@ final class MaterialPathResolverTests: XCTestCase {
|
|||||||
let fileId = "test-cache-\(UUID().uuidString)"
|
let fileId = "test-cache-\(UUID().uuidString)"
|
||||||
let fileURL = cache.appendingPathComponent(fileId)
|
let fileURL = cache.appendingPathComponent(fileId)
|
||||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: nil, title: nil)
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: nil, title: nil)
|
||||||
@ -53,28 +76,25 @@ final class MaterialPathResolverTests: XCTestCase {
|
|||||||
XCTAssertEqual(result?.filePath, fileURL.path)
|
XCTAssertEqual(result?.filePath, fileURL.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - materialType inference via file cascade
|
// MARK: - materialType inference from title extension
|
||||||
|
|
||||||
func test_resolve_infers_type_from_title_extension() {
|
func test_resolve_infers_markdown_from_title() {
|
||||||
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
let fileId = "test-type-\(UUID().uuidString)"
|
let fileId = "test-md-\(UUID().uuidString)"
|
||||||
let fileURL = docs.appendingPathComponent(fileId)
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
// .md title → markdown
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "temporary_file", title: "note.md")
|
||||||
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "knowledge_source", title: "doc.md")
|
|
||||||
XCTAssertNotNil(result)
|
XCTAssertNotNil(result)
|
||||||
XCTAssertEqual(result?.materialType, .markdown)
|
XCTAssertEqual(result?.materialType, .markdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_resolve_pdf_title_infers_pdf_type() {
|
func test_resolve_infers_pdf_from_title() {
|
||||||
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
let fileId = "test-pdf-\(UUID().uuidString)"
|
let fileId = "test-pdf-\(UUID().uuidString)"
|
||||||
let fileURL = docs.appendingPathComponent(fileId)
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "temporary_file", title: "book.pdf")
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "temporary_file", title: "book.pdf")
|
||||||
@ -82,12 +102,49 @@ final class MaterialPathResolverTests: XCTestCase {
|
|||||||
XCTAssertEqual(result?.materialType, .pdf)
|
XCTAssertEqual(result?.materialType, .pdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_resolve_unknown_apiType_defaults_to_unknown_materialType() {
|
func test_resolve_infers_text_from_title() {
|
||||||
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
let fileId = "test-unknown-\(UUID().uuidString)"
|
let fileId = "test-txt-\(UUID().uuidString)"
|
||||||
let fileURL = docs.appendingPathComponent(fileId)
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "knowledge_source", title: "notes.txt")
|
||||||
|
XCTAssertNotNil(result)
|
||||||
|
XCTAssertEqual(result?.materialType, .text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_resolve_infers_epub_from_title() {
|
||||||
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
|
let fileId = "test-epub-\(UUID().uuidString)"
|
||||||
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "temporary_file", title: "book.epub")
|
||||||
|
XCTAssertNotNil(result)
|
||||||
|
XCTAssertEqual(result?.materialType, .epub)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_resolve_infers_image_from_title() {
|
||||||
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
|
let fileId = "test-img-\(UUID().uuidString)"
|
||||||
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
|
for ext in ["png", "jpg", "jpeg", "webp"] {
|
||||||
|
let r = MaterialPathResolver.resolve(materialId: fileId, apiType: "knowledge_source", title: "photo.\(ext)")
|
||||||
|
XCTAssertNotNil(r)
|
||||||
|
XCTAssertEqual(r?.materialType, .image, "ext .\(ext) should infer .image")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_resolve_unknown_apiType_defaults_to_unknown() {
|
||||||
|
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||||
|
let fileId = "test-unk-\(UUID().uuidString)"
|
||||||
|
let fileURL = docs.appendingPathComponent(fileId)
|
||||||
|
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
FileManager.default.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8))
|
||||||
|
|
||||||
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "other_type", title: "file.bin")
|
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "other_type", title: "file.bin")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user