mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-29 07:27:16 +00:00
Stabilize ChatViewModel test Tor lifecycle
This commit is contained in:
parent
6893c8377d
commit
14fbbc6c5f
@ -90,6 +90,16 @@ import UIKit
|
||||
#endif
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
struct ChatViewModelTorLifecycle {
|
||||
var torEnforced: @MainActor () -> Bool
|
||||
var isAutoStartAllowed: @MainActor () -> Bool
|
||||
|
||||
static let live = ChatViewModelTorLifecycle(
|
||||
torEnforced: { TorManager.shared.torEnforced },
|
||||
isAutoStartAllowed: { TorManager.shared.isAutoStartAllowed() }
|
||||
)
|
||||
}
|
||||
|
||||
/// Manages the application state and business logic for BitChat.
|
||||
/// Acts as the primary coordinator between UI components and backend services,
|
||||
/// implementing the BitchatDelegate protocol to handle network events.
|
||||
@ -268,6 +278,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
let idBridge: NostrIdentityBridge
|
||||
let identityManager: SecureIdentityStateManagerProtocol
|
||||
let ndrService: NdrNostrService
|
||||
let torLifecycle: ChatViewModelTorLifecycle
|
||||
|
||||
var nostrRelayManager: NostrRelayManager?
|
||||
private let userDefaults = UserDefaults.standard
|
||||
@ -397,14 +408,16 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
keychain: KeychainManagerProtocol,
|
||||
idBridge: NostrIdentityBridge,
|
||||
identityManager: SecureIdentityStateManagerProtocol,
|
||||
ndrService: NdrNostrService? = nil
|
||||
ndrService: NdrNostrService? = nil,
|
||||
torLifecycle: ChatViewModelTorLifecycle = .live
|
||||
) {
|
||||
self.init(
|
||||
keychain: keychain,
|
||||
idBridge: idBridge,
|
||||
identityManager: identityManager,
|
||||
transport: BLEService(keychain: keychain, idBridge: idBridge, identityManager: identityManager),
|
||||
ndrService: ndrService
|
||||
ndrService: ndrService,
|
||||
torLifecycle: torLifecycle
|
||||
)
|
||||
}
|
||||
|
||||
@ -416,13 +429,15 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
idBridge: NostrIdentityBridge,
|
||||
identityManager: SecureIdentityStateManagerProtocol,
|
||||
transport: Transport,
|
||||
ndrService: NdrNostrService? = nil
|
||||
ndrService: NdrNostrService? = nil,
|
||||
torLifecycle: ChatViewModelTorLifecycle = .live
|
||||
) {
|
||||
let resolvedNdrService = ndrService ?? NdrNostrService.shared
|
||||
self.keychain = keychain
|
||||
self.idBridge = idBridge
|
||||
self.identityManager = identityManager
|
||||
self.ndrService = resolvedNdrService
|
||||
self.torLifecycle = torLifecycle
|
||||
self.meshService = transport
|
||||
self.publicMessagePipeline = PublicMessagePipeline()
|
||||
|
||||
@ -502,12 +517,12 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
}
|
||||
|
||||
// Announce Tor status (geohash-only; do not show in mesh chat). Only when auto-start is allowed.
|
||||
if TorManager.shared.torEnforced && !torStatusAnnounced && TorManager.shared.isAutoStartAllowed() {
|
||||
if torLifecycle.torEnforced() && !torStatusAnnounced && torLifecycle.isAutoStartAllowed() {
|
||||
torStatusAnnounced = true
|
||||
addGeohashOnlySystemMessage(
|
||||
String(localized: "system.tor.starting", comment: "System message when Tor is starting")
|
||||
)
|
||||
} else if !TorManager.shared.torEnforced && !torStatusAnnounced {
|
||||
} else if !torLifecycle.torEnforced() && !torStatusAnnounced {
|
||||
torStatusAnnounced = true
|
||||
addGeohashOnlySystemMessage(
|
||||
String(localized: "system.tor.dev_bypass", comment: "System message when Tor bypass is enabled in development")
|
||||
|
||||
@ -15,7 +15,7 @@ extension ChatViewModel {
|
||||
|
||||
@objc func handleTorWillStart() {
|
||||
Task { @MainActor in
|
||||
if !self.torStatusAnnounced && TorManager.shared.torEnforced {
|
||||
if !self.torStatusAnnounced && self.torLifecycle.torEnforced() {
|
||||
self.torStatusAnnounced = true
|
||||
// Post only in geohash channels (queue if not active)
|
||||
self.addGeohashOnlySystemMessage(
|
||||
@ -44,7 +44,7 @@ extension ChatViewModel {
|
||||
String(localized: "system.tor.restarted", comment: "System message when Tor has restarted")
|
||||
)
|
||||
self.torRestartPending = false
|
||||
} else if TorManager.shared.torEnforced && !self.torInitialReadyAnnounced {
|
||||
} else if self.torLifecycle.torEnforced() && !self.torInitialReadyAnnounced {
|
||||
// Initial start completed
|
||||
self.addGeohashOnlySystemMessage(
|
||||
String(localized: "system.tor.started", comment: "System message when Tor has started")
|
||||
|
||||
@ -25,12 +25,17 @@ private func makeTestableViewModel() -> (viewModel: ChatViewModel, transport: Mo
|
||||
let idBridge = NostrIdentityBridge(keychain: keychainHelper)
|
||||
let identityManager = MockIdentityManager(keychain)
|
||||
let transport = MockTransport()
|
||||
let torLifecycle = ChatViewModelTorLifecycle(
|
||||
torEnforced: { true },
|
||||
isAutoStartAllowed: { false }
|
||||
)
|
||||
|
||||
let viewModel = ChatViewModel(
|
||||
keychain: keychain,
|
||||
idBridge: idBridge,
|
||||
identityManager: identityManager,
|
||||
transport: transport
|
||||
transport: transport,
|
||||
torLifecycle: torLifecycle
|
||||
)
|
||||
|
||||
return (viewModel, transport)
|
||||
|
||||
@ -318,7 +318,7 @@ struct ChatViewModelPrivateChatTests {
|
||||
@Test @MainActor
|
||||
func sendPrivateMessage_delegatesToTransport() async {
|
||||
let (viewModel, transport) = makeTestableViewModel()
|
||||
let recipientID = PeerID(str: "RECIPIENT")
|
||||
let recipientID = PeerID(str: "0000000000000001")
|
||||
|
||||
// Set up connected peer for routing
|
||||
transport.connectedPeers.insert(recipientID)
|
||||
@ -326,9 +326,9 @@ struct ChatViewModelPrivateChatTests {
|
||||
|
||||
viewModel.sendPrivateMessage("Secret message", to: recipientID)
|
||||
|
||||
// The message routing depends on connection state and other factors
|
||||
// At minimum, it should not crash
|
||||
#expect(true) // If we get here without crash, the test passes
|
||||
#expect(transport.sentPrivateMessages.count == 1)
|
||||
#expect(transport.sentPrivateMessages.first?.content == "Secret message")
|
||||
#expect(transport.sentPrivateMessages.first?.peerID == recipientID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,12 +18,17 @@ private func makeTestableViewModel() -> (viewModel: ChatViewModel, transport: Mo
|
||||
let idBridge = NostrIdentityBridge(keychain: keychainHelper)
|
||||
let identityManager = MockIdentityManager(keychain)
|
||||
let transport = MockTransport()
|
||||
let torLifecycle = ChatViewModelTorLifecycle(
|
||||
torEnforced: { true },
|
||||
isAutoStartAllowed: { false }
|
||||
)
|
||||
|
||||
let viewModel = ChatViewModel(
|
||||
keychain: keychain,
|
||||
idBridge: idBridge,
|
||||
identityManager: identityManager,
|
||||
transport: transport
|
||||
transport: transport,
|
||||
torLifecycle: torLifecycle
|
||||
)
|
||||
|
||||
return (viewModel, transport)
|
||||
|
||||
@ -286,12 +286,17 @@ struct ChatViewModelPresenceHandlingTests {
|
||||
let idBridge = NostrIdentityBridge(keychain: keychainHelper)
|
||||
let identityManager = MockIdentityManager(keychain)
|
||||
let transport = MockTransport()
|
||||
let torLifecycle = ChatViewModelTorLifecycle(
|
||||
torEnforced: { true },
|
||||
isAutoStartAllowed: { false }
|
||||
)
|
||||
|
||||
let viewModel = ChatViewModel(
|
||||
keychain: keychain,
|
||||
idBridge: idBridge,
|
||||
identityManager: identityManager,
|
||||
transport: transport
|
||||
transport: transport,
|
||||
torLifecycle: torLifecycle
|
||||
)
|
||||
|
||||
return (viewModel, transport)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user