Fix LiveLocationManager flaky tests (#5389)

This commit is contained in:
Mauro
2026-04-13 18:05:47 +02:00
committed by GitHub
parent 7c812201cb
commit 8bfdc70b9c
6 changed files with 120 additions and 9 deletions
@@ -0,0 +1,20 @@
//
// Copyright 2026 Element Creations Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import CoreLocation
extension CLLocationManagerMock {
struct Configuration {
var authorizationStatus: CLAuthorizationStatus = .authorizedAlways
}
convenience init(_ configuration: Configuration) {
self.init()
underlyingAuthorizationStatus = configuration.authorizationStatus
}
}
@@ -2187,6 +2187,65 @@ class BugReportServiceMock: BugReportServiceProtocol, @unchecked Sendable {
}
}
}
class CLLocationManagerMock: CLLocationManagerProtocol, @unchecked Sendable {
weak var delegate: CLLocationManagerDelegate?
var allowsBackgroundLocationUpdates: Bool {
get { return underlyingAllowsBackgroundLocationUpdates }
set(value) { underlyingAllowsBackgroundLocationUpdates = value }
}
var underlyingAllowsBackgroundLocationUpdates: Bool!
var desiredAccuracy: CLLocationAccuracy {
get { return underlyingDesiredAccuracy }
set(value) { underlyingDesiredAccuracy = value }
}
var underlyingDesiredAccuracy: CLLocationAccuracy!
var pausesLocationUpdatesAutomatically: Bool {
get { return underlyingPausesLocationUpdatesAutomatically }
set(value) { underlyingPausesLocationUpdatesAutomatically = value }
}
var underlyingPausesLocationUpdatesAutomatically: Bool!
var authorizationStatus: CLAuthorizationStatus {
get { return underlyingAuthorizationStatus }
set(value) { underlyingAuthorizationStatus = value }
}
var underlyingAuthorizationStatus: CLAuthorizationStatus!
//MARK: - requestAlwaysAuthorization
var requestAlwaysAuthorizationUnderlyingCallsCount = 0
var requestAlwaysAuthorizationCallsCount: Int {
get {
if Thread.isMainThread {
return requestAlwaysAuthorizationUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = requestAlwaysAuthorizationUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
requestAlwaysAuthorizationUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
requestAlwaysAuthorizationUnderlyingCallsCount = newValue
}
}
}
}
var requestAlwaysAuthorizationCalled: Bool {
return requestAlwaysAuthorizationCallsCount > 0
}
var requestAlwaysAuthorizationClosure: (() -> Void)?
func requestAlwaysAuthorization() {
requestAlwaysAuthorizationCallsCount += 1
requestAlwaysAuthorizationClosure?()
}
}
class CXProviderMock: CXProviderProtocol, @unchecked Sendable {
//MARK: - setDelegate
@@ -0,0 +1,21 @@
//
// Copyright 2026 Element Creations Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import CoreLocation
// sourcery: AutoMockable
protocol CLLocationManagerProtocol: AnyObject {
var delegate: CLLocationManagerDelegate? { get set }
var allowsBackgroundLocationUpdates: Bool { get set }
var desiredAccuracy: CLLocationAccuracy { get set }
var pausesLocationUpdatesAutomatically: Bool { get set }
var authorizationStatus: CLAuthorizationStatus { get }
func requestAlwaysAuthorization()
}
extension CLLocationManager: CLLocationManagerProtocol { }
@@ -10,7 +10,7 @@ import CoreLocation
class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationManagerDelegate {
private let clientProxy: ClientProxyProtocol
private let locationManager: CLLocationManager
private let locationManager: CLLocationManagerProtocol
private let appSettings: AppSettings
private let authorizationStatusSubject: CurrentValueSubject<CLAuthorizationStatus, Never>
@@ -30,21 +30,22 @@ class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationMana
@MainActor
init(clientProxy: ClientProxyProtocol,
appSettings: AppSettings) {
appSettings: AppSettings,
locationManager: @autoclosure @MainActor () -> CLLocationManagerProtocol = CLLocationManager()) {
self.clientProxy = clientProxy
self.appSettings = appSettings
// Very important, the CLLocationManager needs to be initialised on the main thread
// or the delegate functions won't be handled!
// https://developer.apple.com/documentation/corelocation/cllocationmanagerdelegate
locationManager = CLLocationManager()
authorizationStatusSubject = CurrentValueSubject(locationManager.authorizationStatus)
self.locationManager = locationManager()
authorizationStatusSubject = CurrentValueSubject(self.locationManager.authorizationStatus)
super.init()
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.pausesLocationUpdatesAutomatically = false
self.locationManager.delegate = self
self.locationManager.allowsBackgroundLocationUpdates = true
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.pausesLocationUpdatesAutomatically = false
setupSubscriptions()
}