mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 14:45:22 +00:00
Add ChatViewModel testability and unit tests
- Add testable ChatViewModel initializer accepting Transport dependency - Create MockTransport implementing full Transport protocol for testing - Add 21 unit tests covering: - Initialization (delegate, services, nickname) - Message sending (basic, empty, mentions, commands) - Message receiving (delegate calls, public messages) - Peer connections (connect, disconnect, isPeerConnected) - Deduplication service integration - Private chat routing - Bluetooth state handling - Panic clear functionality - Guard NotificationService methods against test environment crashes - Make deduplicationService internal for test access All 303 tests pass.
This commit is contained in:
@@ -16,10 +16,18 @@ import AppKit
|
||||
|
||||
final class NotificationService {
|
||||
static let shared = NotificationService()
|
||||
|
||||
|
||||
/// Returns true if running in test environment (XCTest, Swift Testing, or SPM tests)
|
||||
private var isRunningTests: Bool {
|
||||
NSClassFromString("XCTestCase") != nil ||
|
||||
ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil ||
|
||||
Bundle.main.bundleIdentifier == nil
|
||||
}
|
||||
|
||||
private init() {}
|
||||
|
||||
|
||||
func requestAuthorization() {
|
||||
guard !isRunningTests else { return }
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
|
||||
if granted {
|
||||
// Permission granted
|
||||
@@ -36,6 +44,7 @@ final class NotificationService {
|
||||
userInfo: [String: Any]? = nil,
|
||||
interruptionLevel: UNNotificationInterruptionLevel = .active
|
||||
) {
|
||||
guard !isRunningTests else { return }
|
||||
let content = UNMutableNotificationContent()
|
||||
content.title = title
|
||||
content.body = body
|
||||
|
||||
@@ -188,7 +188,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
private let privateChatManager: PrivateChatManager
|
||||
private let unifiedPeerService: UnifiedPeerService
|
||||
private let autocompleteService: AutocompleteService
|
||||
private let deduplicationService: MessageDeduplicationService
|
||||
let deduplicationService: MessageDeduplicationService // internal for test access
|
||||
|
||||
// Computed properties for compatibility
|
||||
@MainActor
|
||||
@@ -417,17 +417,34 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
private var nostrKeyMapping: [PeerID: String] = [:] // senderPeerID -> nostrPubkey
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
|
||||
@MainActor
|
||||
init(
|
||||
convenience init(
|
||||
keychain: KeychainManagerProtocol,
|
||||
idBridge: NostrIdentityBridge,
|
||||
identityManager: SecureIdentityStateManagerProtocol
|
||||
) {
|
||||
self.init(
|
||||
keychain: keychain,
|
||||
idBridge: idBridge,
|
||||
identityManager: identityManager,
|
||||
transport: BLEService(keychain: keychain, idBridge: idBridge, identityManager: identityManager)
|
||||
)
|
||||
}
|
||||
|
||||
/// Testable initializer that accepts a Transport dependency.
|
||||
/// Use this initializer for unit testing with MockTransport.
|
||||
@MainActor
|
||||
init(
|
||||
keychain: KeychainManagerProtocol,
|
||||
idBridge: NostrIdentityBridge,
|
||||
identityManager: SecureIdentityStateManagerProtocol,
|
||||
transport: Transport
|
||||
) {
|
||||
self.keychain = keychain
|
||||
self.idBridge = idBridge
|
||||
self.identityManager = identityManager
|
||||
self.meshService = BLEService(keychain: keychain, idBridge: idBridge, identityManager: identityManager)
|
||||
self.meshService = transport
|
||||
self.publicMessagePipeline = PublicMessagePipeline()
|
||||
|
||||
// Load persisted read receipts
|
||||
@@ -616,7 +633,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
// Request notification permission
|
||||
// Request notification permission (guards test environment internally)
|
||||
NotificationService.shared.requestAuthorization()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user