mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 20:38:41 +00:00
Attempt to improve unit test reliability:
- synchronize mock properties on the main queue - sleep for longer when processing routes - finish encoding before deallocating the keyed archiver - wait for NotificationCenter notifications to be delivered - change were we process remote notification permissions
This commit is contained in:
committed by
Stefan Ceriu
parent
da598302df
commit
7645971812
File diff suppressed because it is too large
Load Diff
@@ -23,17 +23,7 @@ final class NotificationManager: NSObject, NotificationManagerProtocol {
|
|||||||
private let notificationCenter: UserNotificationCenterProtocol
|
private let notificationCenter: UserNotificationCenterProtocol
|
||||||
private let appSettings: AppSettings
|
private let appSettings: AppSettings
|
||||||
|
|
||||||
private var userSession: UserSessionProtocol? {
|
private var userSession: UserSessionProtocol?
|
||||||
didSet {
|
|
||||||
// If notification permissions were given previously then attempt re-registering
|
|
||||||
// for remote notifications on startup. Otherwise let the onboarding flow handle it
|
|
||||||
Task { @MainActor in
|
|
||||||
if await self.notificationCenter.authorizationStatus() == .authorized {
|
|
||||||
self.delegate?.registerForRemoteNotifications()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
private var notificationsEnabled = false
|
private var notificationsEnabled = false
|
||||||
@@ -103,6 +93,18 @@ final class NotificationManager: NSObject, NotificationManagerProtocol {
|
|||||||
|
|
||||||
func setUserSession(_ userSession: UserSessionProtocol?) {
|
func setUserSession(_ userSession: UserSessionProtocol?) {
|
||||||
self.userSession = userSession
|
self.userSession = userSession
|
||||||
|
|
||||||
|
// If notification permissions were given previously then attempt re-registering
|
||||||
|
// for remote notifications on startup. Otherwise let the onboarding flow handle it
|
||||||
|
Task { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
if await notificationCenter.authorizationStatus() == .authorized {
|
||||||
|
await MainActor.run {
|
||||||
|
delegate?.registerForRemoteNotifications()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func registrationFailed(with error: Error) {
|
func registrationFailed(with error: Error) {
|
||||||
|
|||||||
@@ -45,7 +45,30 @@ import {{ import }}
|
|||||||
{% call methodThrowableErrorDeclaration method %}
|
{% call methodThrowableErrorDeclaration method %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not method.isInitializer %}
|
{% if not method.isInitializer %}
|
||||||
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}CallsCount = 0
|
var {% call swiftifyMethodName method.selectorName %}UnderlyingCallsCount = 0
|
||||||
|
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}CallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return {% call swiftifyMethodName method.selectorName %}UnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = {% call swiftifyMethodName method.selectorName %}UnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
{% call swiftifyMethodName method.selectorName %}UnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
{% call swiftifyMethodName method.selectorName %}UnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}Called: Bool {
|
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}Called: Bool {
|
||||||
return {% call swiftifyMethodName method.selectorName %}CallsCount > 0
|
return {% call swiftifyMethodName method.selectorName %}CallsCount > 0
|
||||||
}
|
}
|
||||||
@@ -63,7 +86,31 @@ import {{ import }}
|
|||||||
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReceivedInvocations: [({% for param in method.parameters %}{{ param.name }}: {{ param.unwrappedTypeName if param.typeAttributes.escaping else param.typeName }}{{ ', ' if not forloop.last }}{% endfor %})] = []
|
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReceivedInvocations: [({% for param in method.parameters %}{{ param.name }}: {{ param.unwrappedTypeName if param.typeAttributes.escaping else param.typeName }}{{ ', ' if not forloop.last }}{% endfor %})] = []
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not method.returnTypeName.isVoid and not method.isInitializer %}
|
{% if not method.returnTypeName.isVoid and not method.isInitializer %}
|
||||||
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ method.returnTypeName }}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ '!' if not method.isOptionalReturnType }}
|
|
||||||
|
var {% call swiftifyMethodName method.selectorName %}UnderlyingReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ method.returnTypeName }}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ '!' if not method.isOptionalReturnType }}
|
||||||
|
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ method.returnTypeName }}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ '!' if not method.isOptionalReturnType }} {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return {% call swiftifyMethodName method.selectorName %}UnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: {{ method.returnTypeName }}? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = {% call swiftifyMethodName method.selectorName %}UnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
{% call swiftifyMethodName method.selectorName %}UnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
{% call swiftifyMethodName method.selectorName %}UnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% call methodClosureDeclaration method %}
|
{% call methodClosureDeclaration method %}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class MockCoder: NSKeyedArchiver {
|
final class MockCoder: NSKeyedArchiver {
|
||||||
|
deinit {
|
||||||
|
finishEncoding()
|
||||||
|
}
|
||||||
|
|
||||||
override func decodeObject(forKey _: String) -> Any { "" }
|
override func decodeObject(forKey _: String) -> Any { "" }
|
||||||
override func decodeInt64(forKey key: String) -> Int64 { 0 }
|
override func decodeInt64(forKey key: String) -> Int64 { 0 }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,10 +212,14 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
// No interaction if the object is nil or of the wrong type
|
// No interaction if the object is nil or of the wrong type
|
||||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: nil)
|
NotificationCenter.default.post(name: .roomMarkedAsRead, object: nil)
|
||||||
|
try? await Task.sleep(for: .seconds(0.25)) // Wait for the notification to be delivered
|
||||||
|
|
||||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
||||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 0)
|
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 0)
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: 1)
|
NotificationCenter.default.post(name: .roomMarkedAsRead, object: 1)
|
||||||
|
try? await Task.sleep(for: .seconds(0.25)) // Wait for the notification to be delivered
|
||||||
|
|
||||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
||||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 0)
|
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 0)
|
||||||
|
|
||||||
@@ -226,7 +230,10 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
notificationCenter.removeDeliveredNotificationsWithIdentifiersClosure = { _ in
|
notificationCenter.removeDeliveredNotificationsWithIdentifiersClosure = { _ in
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: "RoomID")
|
NotificationCenter.default.post(name: .roomMarkedAsRead, object: "RoomID")
|
||||||
|
try? await Task.sleep(for: .seconds(0.25)) // Wait for the notification to be delivered
|
||||||
|
|
||||||
await fulfillment(of: [expectation])
|
await fulfillment(of: [expectation])
|
||||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
||||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 1)
|
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 1)
|
||||||
@@ -238,7 +245,10 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
notificationCenter.removeDeliveredNotificationsWithIdentifiersClosure = { _ in
|
notificationCenter.removeDeliveredNotificationsWithIdentifiersClosure = { _ in
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .invitesScreenAppeared, object: nil)
|
NotificationCenter.default.post(name: .invitesScreenAppeared, object: nil)
|
||||||
|
try? await Task.sleep(for: .seconds(0.25)) // Wait for the notification to be delivered
|
||||||
|
|
||||||
await fulfillment(of: [expectation])
|
await fulfillment(of: [expectation])
|
||||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
||||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 1)
|
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsWithIdentifiersCallsCount, 1)
|
||||||
|
|||||||
@@ -155,12 +155,8 @@ class RoomFlowCoordinatorTests: XCTestCase {
|
|||||||
|
|
||||||
private func process(route: AppRoute) async throws {
|
private func process(route: AppRoute) async throws {
|
||||||
roomFlowCoordinator.handleAppRoute(route, animated: true)
|
roomFlowCoordinator.handleAppRoute(route, animated: true)
|
||||||
if case .childRoom = route {
|
|
||||||
// A single yield isn't enough when creating the new flow coordinator.
|
// A single yield isn't enough when creating the new flow coordinator.
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
} else {
|
|
||||||
await Task.yield()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func process(route: AppRoute, expectedAction: RoomFlowCoordinatorAction) async throws {
|
private func process(route: AppRoute, expectedAction: RoomFlowCoordinatorAction) async throws {
|
||||||
|
|||||||
Reference in New Issue
Block a user