Refactor Nostr ID Bridge & Keychain Helper (#796)

* Extract each type to a separate file

* Nostr ID Bridge: Convert static func/vars to instance

* `KeychainHelper` behind a protocol to easily mock

* Update tests with ID Bridge and MockKeychainHelper

---------

Co-authored-by: jack <212554440+jackjackbits@users.noreply.github.com>
This commit is contained in:
Islam
2025-10-14 12:26:18 +02:00
committed by GitHub
co-authored by jack
parent e3149fa098
commit ad4103bacc
18 changed files with 442 additions and 370 deletions
@@ -15,15 +15,21 @@ struct FragmentationTests {
private let mockKeychain: MockKeychain
private let mockIdentityManager: MockIdentityManager
private let idBridge: NostrIdentityBridge
init() {
mockKeychain = MockKeychain()
mockIdentityManager = MockIdentityManager(mockKeychain)
idBridge = NostrIdentityBridge(keychain: MockKeychainHelper())
}
@Test("Reassembly from fragments delivers a public message")
func reassemblyFromFragmentsDeliversPublicMessage() async throws {
let ble = BLEService(keychain: mockKeychain, identityManager: mockIdentityManager)
let ble = BLEService(
keychain: mockKeychain,
idBridge: idBridge,
identityManager: mockIdentityManager
)
let capture = CaptureDelegate()
ble.delegate = capture
@@ -55,7 +61,11 @@ struct FragmentationTests {
@Test("Duplicate fragment does not break reassembly")
func duplicateFragmentDoesNotBreakReassembly() async throws {
let ble = BLEService(keychain: mockKeychain, identityManager: mockIdentityManager)
let ble = BLEService(
keychain: mockKeychain,
idBridge: idBridge,
identityManager: mockIdentityManager
)
let capture = CaptureDelegate()
ble.delegate = capture
@@ -85,7 +95,11 @@ struct FragmentationTests {
@Test("Invalid fragment header is ignored")
func invalidFragmentHeaderIsIgnored() async throws {
let ble = BLEService(keychain: mockKeychain, identityManager: mockIdentityManager)
let ble = BLEService(
keychain: mockKeychain,
idBridge: idBridge,
identityManager: mockIdentityManager
)
let capture = CaptureDelegate()
ble.delegate = capture
+3 -2
View File
@@ -37,9 +37,10 @@ final class LocationChannelsTests: XCTestCase {
func testPerGeohashIdentityDeterministic() throws {
// Derive twice for same geohash; should be identical
let idBridge = NostrIdentityBridge(keychain: MockKeychainHelper())
let gh = "u4pruy"
let id1 = try NostrIdentityBridge.deriveIdentity(forGeohash: gh)
let id2 = try NostrIdentityBridge.deriveIdentity(forGeohash: gh)
let id1 = try idBridge.deriveIdentity(forGeohash: gh)
let id2 = try idBridge.deriveIdentity(forGeohash: gh)
XCTAssertEqual(id1.publicKeyHex, id2.publicKeyHex)
}
}
+18
View File
@@ -44,3 +44,21 @@ final class MockKeychain: KeychainManagerProtocol {
storage["identity_noiseStaticKey"] != nil
}
}
final class MockKeychainHelper: KeychainHelperProtocol {
private typealias Service = String
private typealias Key = String
private var storage: [Service: [Key: Data]] = [:]
func save(key: String, data: Data, service: String, accessible: CFString?) {
storage[service]?[key] = data
}
func load(key: String, service: String) -> Data? {
storage[service]?[key]
}
func delete(key: String, service: String) {
storage[service]?.removeValue(forKey: key)
}
}