import XCTest @testable import Ten31Transcripts final class VoiceprintStoreTests: XCTestCase { private func tempURL() -> URL { FileManager.default.temporaryDirectory.appendingPathComponent("vp_\(UUID().uuidString).json") } private func response() throws -> LabelMergeResponse { let json = #"{"duration":10,"speakers":[{"cluster":"Speaker_0","name":"Grant","source":"visual","overlap_confidence":0.99,"fingerprint":[0.1,0.2,0.3]},{"cluster":"Speaker_1","name":"Sarah","source":"voiceprint","match_similarity":0.7,"fingerprint":[0.4,0.5,0.6]},{"cluster":"Speaker_2","name":"Bob","source":"visual","overlap_confidence":0.5,"fingerprint":[0.7,0.8,0.9]},{"cluster":"Speaker_3","name":"Unknown_0","source":"unmatched"}],"segments":[],"fingerprints":{"Grant":[0.1,0.2,0.3],"Sarah":[0.4,0.5,0.6]},"models":{}}"# return try JSONDecoder().decode(LabelMergeResponse.self, from: Data(json.utf8)) } func testStoresOnlyConfidentNamedSpeakers() throws { let url = tempURL(); defer { try? FileManager.default.removeItem(at: url) } let store = VoiceprintStore(fileURL: url) store.update(with: try response()) XCTAssertNotNil(store.entries["Grant"]) // visual, high overlap XCTAssertNotNil(store.entries["Sarah"]) // voiceprint match XCTAssertNil(store.entries["Bob"]) // overlap 0.5 < 0.8 XCTAssertNil(store.entries["Unknown_0"]) XCTAssertEqual(store.knownVoiceprints()["Grant"], [0.1, 0.2, 0.3]) XCTAssertEqual(store.entries["Grant"]?.calls, 1) } func testStoresMicChannelSelf() throws { let url = tempURL(); defer { try? FileManager.default.removeItem(at: url) } let store = VoiceprintStore(fileURL: url) let json = #"{"duration":10,"speakers":[{"cluster":"mic","name":"Grant","source":"mic_channel","fingerprint":[0.5,0.6]}],"segments":[],"fingerprints":{"Grant":[0.5,0.6]},"models":{}}"# store.update(with: try JSONDecoder().decode(LabelMergeResponse.self, from: Data(json.utf8))) XCTAssertEqual(store.knownVoiceprints()["Grant"], [0.5, 0.6]) // clean self print stored } func testPersistsAcrossInstancesAndIncrementsCalls() throws { let url = tempURL(); defer { try? FileManager.default.removeItem(at: url) } let store = VoiceprintStore(fileURL: url) store.update(with: try response()) store.update(with: try response()) XCTAssertEqual(store.entries["Grant"]?.calls, 2) let reopened = VoiceprintStore(fileURL: url) XCTAssertEqual(reopened.knownVoiceprints().count, 2) } func testRenameRemoveReset() throws { let url = tempURL(); defer { try? FileManager.default.removeItem(at: url) } let store = VoiceprintStore(fileURL: url) store.update(with: try response()) store.rename("Sarah", to: "Sarah Jones") XCTAssertNotNil(store.entries["Sarah Jones"]); XCTAssertNil(store.entries["Sarah"]) store.remove("Grant"); XCTAssertNil(store.entries["Grant"]) store.reset(); XCTAssertTrue(store.entries.isEmpty) } }