ios-projects/AIStudyApp/AIStudyAppTests/MaterialPathResolverTests.swift
wangdl 86054edd5f 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>
2026-06-18 13:07:30 +08:00

155 lines
7.4 KiB
Swift

import XCTest
@testable import AIStudyApp
final class MaterialPathResolverTests: XCTestCase {
// MARK: - resolveKnowledgeSource path
func test_resolveKnowledgeSource_finds_file_in_knowledge_sources_dir() {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let sourceId = "ks-test-\(UUID().uuidString)"
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
func test_resolve_returns_nil_for_nonexistent_material() {
let result = MaterialPathResolver.resolve(
materialId: UUID().uuidString,
apiType: nil,
title: nil
)
XCTAssertNil(result)
}
// MARK: - resolve finds file in Documents
func test_resolve_finds_file_in_documents() {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileId = "test-docs-\(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: nil, title: nil)
XCTAssertNotNil(result)
XCTAssertEqual(result?.filePath, fileURL.path)
}
// MARK: - resolve finds file in Caches
func test_resolve_finds_file_in_caches() {
let cache = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let fileId = "test-cache-\(UUID().uuidString)"
let fileURL = cache.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: nil, title: nil)
XCTAssertNotNil(result)
XCTAssertEqual(result?.filePath, fileURL.path)
}
// MARK: - materialType inference from title extension
func test_resolve_infers_markdown_from_title() {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileId = "test-md-\(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: "note.md")
XCTAssertNotNil(result)
XCTAssertEqual(result?.materialType, .markdown)
}
func test_resolve_infers_pdf_from_title() {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileId = "test-pdf-\(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.pdf")
XCTAssertNotNil(result)
XCTAssertEqual(result?.materialType, .pdf)
}
func test_resolve_infers_text_from_title() {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileId = "test-txt-\(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: "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))
let result = MaterialPathResolver.resolve(materialId: fileId, apiType: "other_type", title: "file.bin")
XCTAssertNotNil(result)
XCTAssertEqual(result?.materialType, .unknown)
}
}