mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Removing Delivered Notifications (#1305)
* completed * changelog * tests * more tests * better naming * fix * a bit more waiting time * generated mocks * xcodegen
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C070FD43DC6BF4E50217965A /* LocalizationTests.swift */; };
|
||||
020F7E70167FB2833266F2F0 /* AnalyticsSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39D7F513A36C9C1951DB44C /* AnalyticsSettingsScreen.swift */; };
|
||||
02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */; };
|
||||
02F4FAE40AF63A1941FD3BBA /* NotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10B7F8EE25775DE2A305CBB5 /* NotificationCenterProtocol.swift */; };
|
||||
037006FB6DF1374F94E4058D /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */; };
|
||||
03D684A3AE85A23B3DA3B43F /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26747B3154A5DBC3A7E24A5 /* Image.swift */; };
|
||||
0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */; };
|
||||
@@ -566,6 +567,7 @@
|
||||
C413D36D44F89DE63D3ADFA4 /* ReportContentScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */; };
|
||||
C4180F418235DAD9DD173951 /* TemplateScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */; };
|
||||
C49FCC766673006B6D299F1C /* RoomDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DF8F7A3AD83D04C08D75E01 /* RoomDetailsEditScreenViewModelProtocol.swift */; };
|
||||
C4C84901ABAC9B17564AB7EB /* NotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4151163F666ED94FD959475A /* NotificationName.swift */; };
|
||||
C4D2BCAA54E2C62B94B24AF4 /* InviteUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */; };
|
||||
C4E0D03DF88242697545A9B7 /* UserIndicatorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */; };
|
||||
C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; };
|
||||
@@ -835,6 +837,7 @@
|
||||
0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenModels.swift; sourceTree = "<group>"; };
|
||||
1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
|
||||
10B7F8EE25775DE2A305CBB5 /* NotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCenterProtocol.swift; sourceTree = "<group>"; };
|
||||
10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderProtocol.swift; sourceTree = "<group>"; };
|
||||
10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenSelectedItem.swift; sourceTree = "<group>"; };
|
||||
11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -964,6 +967,7 @@
|
||||
3FFDA99C98BE05F43A92343B /* test_pdf.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = test_pdf.pdf; sourceTree = "<group>"; };
|
||||
40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
|
||||
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenUITests.swift; sourceTree = "<group>"; };
|
||||
4151163F666ED94FD959475A /* NotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationName.swift; sourceTree = "<group>"; };
|
||||
4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreen.swift; sourceTree = "<group>"; };
|
||||
421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -2052,6 +2056,7 @@
|
||||
C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */,
|
||||
2AFEF3AC64B1358083F76B8B /* List.swift */,
|
||||
23AA3F4B285570805CB0CCDD /* MapTiler.swift */,
|
||||
4151163F666ED94FD959475A /* NotificationName.swift */,
|
||||
F72EFC8C634469F9262659C7 /* NSItemProvider.swift */,
|
||||
95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */,
|
||||
7310D8DFE01AF45F0689C3AA /* Publisher.swift */,
|
||||
@@ -3194,6 +3199,7 @@
|
||||
6A580295A56B55A856CC4084 /* InfoPlistReader.swift */,
|
||||
6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */,
|
||||
C789E7BFC066CF39B8AE0974 /* NetworkMonitor.swift */,
|
||||
10B7F8EE25775DE2A305CBB5 /* NotificationCenterProtocol.swift */,
|
||||
F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */,
|
||||
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */,
|
||||
DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */,
|
||||
@@ -4386,10 +4392,12 @@
|
||||
0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */,
|
||||
9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */,
|
||||
368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */,
|
||||
02F4FAE40AF63A1941FD3BBA /* NotificationCenterProtocol.swift in Sources */,
|
||||
3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */,
|
||||
CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */,
|
||||
652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */,
|
||||
06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */,
|
||||
C4C84901ABAC9B17564AB7EB /* NotificationName.swift in Sources */,
|
||||
6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */,
|
||||
F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */,
|
||||
D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */,
|
||||
|
||||
@@ -197,6 +197,25 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
class NotificationCenterMock: NotificationCenterProtocol {
|
||||
|
||||
//MARK: - post
|
||||
|
||||
var postNameObjectCallsCount = 0
|
||||
var postNameObjectCalled: Bool {
|
||||
return postNameObjectCallsCount > 0
|
||||
}
|
||||
var postNameObjectReceivedArguments: (aName: NSNotification.Name, anObject: Any?)?
|
||||
var postNameObjectReceivedInvocations: [(aName: NSNotification.Name, anObject: Any?)] = []
|
||||
var postNameObjectClosure: ((NSNotification.Name, Any?) -> Void)?
|
||||
|
||||
func post(name aName: NSNotification.Name, object anObject: Any?) {
|
||||
postNameObjectCallsCount += 1
|
||||
postNameObjectReceivedArguments = (aName: aName, anObject: anObject)
|
||||
postNameObjectReceivedInvocations.append((aName: aName, anObject: anObject))
|
||||
postNameObjectClosure?(aName, anObject)
|
||||
}
|
||||
}
|
||||
class NotificationManagerMock: NotificationManagerProtocol {
|
||||
var delegate: NotificationManagerDelegate?
|
||||
|
||||
@@ -1365,6 +1384,39 @@ class UserNotificationCenterMock: UserNotificationCenterProtocol {
|
||||
return requestAuthorizationOptionsReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - deliveredNotifications
|
||||
|
||||
var deliveredNotificationsCallsCount = 0
|
||||
var deliveredNotificationsCalled: Bool {
|
||||
return deliveredNotificationsCallsCount > 0
|
||||
}
|
||||
var deliveredNotificationsReturnValue: [UNNotification]!
|
||||
var deliveredNotificationsClosure: (() async -> [UNNotification])?
|
||||
|
||||
func deliveredNotifications() async -> [UNNotification] {
|
||||
deliveredNotificationsCallsCount += 1
|
||||
if let deliveredNotificationsClosure = deliveredNotificationsClosure {
|
||||
return await deliveredNotificationsClosure()
|
||||
} else {
|
||||
return deliveredNotificationsReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - removeDeliveredNotifications
|
||||
|
||||
var removeDeliveredNotificationsWithIdentifiersCallsCount = 0
|
||||
var removeDeliveredNotificationsWithIdentifiersCalled: Bool {
|
||||
return removeDeliveredNotificationsWithIdentifiersCallsCount > 0
|
||||
}
|
||||
var removeDeliveredNotificationsWithIdentifiersReceivedIdentifiers: [String]?
|
||||
var removeDeliveredNotificationsWithIdentifiersReceivedInvocations: [[String]] = []
|
||||
var removeDeliveredNotificationsWithIdentifiersClosure: (([String]) -> Void)?
|
||||
|
||||
func removeDeliveredNotifications(withIdentifiers identifiers: [String]) {
|
||||
removeDeliveredNotificationsWithIdentifiersCallsCount += 1
|
||||
removeDeliveredNotificationsWithIdentifiersReceivedIdentifiers = identifiers
|
||||
removeDeliveredNotificationsWithIdentifiersReceivedInvocations.append(identifiers)
|
||||
removeDeliveredNotificationsWithIdentifiersClosure?(identifiers)
|
||||
}
|
||||
//MARK: - setNotificationCategories
|
||||
|
||||
var setNotificationCategoriesCallsCount = 0
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Notification.Name {
|
||||
static let roomMarkedAsRead = Notification.Name("roomMarkedAsRead")
|
||||
static let invitesScreenAppeared = Notification.Name("invitesScreenAppeared")
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol NotificationCenterProtocol: AnyObject {
|
||||
func post(name aName: NSNotification.Name, object anObject: Any?)
|
||||
}
|
||||
|
||||
extension NotificationCenter: NotificationCenterProtocol { }
|
||||
@@ -48,4 +48,5 @@ struct InvitesScreenRoomDetails: Identifiable {
|
||||
enum InvitesScreenViewAction {
|
||||
case accept(InvitesScreenRoomDetails)
|
||||
case decline(InvitesScreenRoomDetails)
|
||||
case appeared
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ class InvitesScreenViewModel: InvitesScreenViewModelType, InvitesScreenViewModel
|
||||
private let appSettings: AppSettings
|
||||
private let analytics: AnalyticsService
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let notificationCenterProtocol: NotificationCenterProtocol
|
||||
|
||||
private let previouslySeenInvites: Set<String>
|
||||
private let actionsSubject: PassthroughSubject<InvitesScreenViewModelAction, Never> = .init()
|
||||
@@ -36,11 +37,13 @@ class InvitesScreenViewModel: InvitesScreenViewModelType, InvitesScreenViewModel
|
||||
init(userSession: UserSessionProtocol,
|
||||
appSettings: AppSettings,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
notificationCenterProtocol: NotificationCenterProtocol = NotificationCenter.default) {
|
||||
self.userSession = userSession
|
||||
self.appSettings = appSettings
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.notificationCenterProtocol = notificationCenterProtocol
|
||||
|
||||
previouslySeenInvites = appSettings.seenInvites
|
||||
super.init(initialViewState: InvitesScreenViewState(), imageProvider: userSession.mediaProvider)
|
||||
@@ -55,6 +58,8 @@ class InvitesScreenViewModel: InvitesScreenViewModelType, InvitesScreenViewModel
|
||||
accept(invite: invite)
|
||||
case .decline(let invite):
|
||||
startDeclineFlow(invite: invite)
|
||||
case .appeared:
|
||||
notificationCenterProtocol.post(name: .invitesScreenAppeared, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,11 @@ struct InvitesScreen: View {
|
||||
noInvitesContent
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
context.send(viewAction: .appeared)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var noInvitesContent: some View {
|
||||
Text(L10n.screenInvitesEmptyList)
|
||||
.font(.compound.bodyLG)
|
||||
|
||||
@@ -33,18 +33,21 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let analytics: AnalyticsService
|
||||
private unowned let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let notificationCenterProtocol: NotificationCenterProtocol
|
||||
|
||||
init(timelineController: RoomTimelineControllerProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
roomProxy: RoomProxyProtocol,
|
||||
appSettings: AppSettings,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
notificationCenterProtocol: NotificationCenterProtocol = NotificationCenter.default) {
|
||||
self.roomProxy = roomProxy
|
||||
self.timelineController = timelineController
|
||||
self.appSettings = appSettings
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.notificationCenterProtocol = notificationCenterProtocol
|
||||
|
||||
super.init(initialViewState: RoomScreenViewState(roomId: timelineController.roomID,
|
||||
roomTitle: roomProxy.roomTitle,
|
||||
@@ -214,6 +217,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
|
||||
private func markRoomAsRead() async {
|
||||
notificationCenterProtocol.post(name: .roomMarkedAsRead, object: roomProxy.id)
|
||||
_ = await timelineController.markRoomAsRead()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import Foundation
|
||||
import UIKit
|
||||
import UserNotifications
|
||||
|
||||
class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
final class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
private let notificationCenter: UserNotificationCenterProtocol
|
||||
private let appSettings: AppSettings
|
||||
|
||||
@@ -31,6 +31,8 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
appSettings: AppSettings) {
|
||||
self.notificationCenter = notificationCenter
|
||||
self.appSettings = appSettings
|
||||
super.init()
|
||||
addObservers()
|
||||
}
|
||||
|
||||
// MARK: NotificationManagerProtocol
|
||||
@@ -169,6 +171,47 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
delegate?.unregisterForRemoteNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
private func addObservers() {
|
||||
NotificationCenter
|
||||
.default
|
||||
.publisher(for: .roomMarkedAsRead)
|
||||
.sink { [weak self] notification in
|
||||
guard let roomID = notification.object as? String else {
|
||||
return
|
||||
}
|
||||
self?.removeMessageNotifications(for: roomID)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
NotificationCenter
|
||||
.default
|
||||
.publisher(for: .invitesScreenAppeared)
|
||||
.sink { [weak self] _ in
|
||||
self?.removeInviteNotifications()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func removeMessageNotifications(for roomID: String) {
|
||||
Task {
|
||||
let notificationsIdentifiers = await notificationCenter
|
||||
.deliveredNotifications()
|
||||
.filter { $0.request.content.roomID == roomID }
|
||||
.map(\.request.identifier)
|
||||
notificationCenter.removeDeliveredNotifications(withIdentifiers: notificationsIdentifiers)
|
||||
}
|
||||
}
|
||||
|
||||
private func removeInviteNotifications() {
|
||||
Task {
|
||||
let notificationsIdentifiers = await notificationCenter
|
||||
.deliveredNotifications()
|
||||
.filter { $0.request.content.categoryIdentifier == NotificationConstants.Category.invite }
|
||||
.map(\.request.identifier)
|
||||
notificationCenter.removeDeliveredNotifications(withIdentifiers: notificationsIdentifiers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UNUserNotificationCenterDelegate
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
// Sadly we can't mock this because the delegate needs to be weak
|
||||
// Use UserNotificationCenterSpy
|
||||
protocol UserNotificationCenterProtocol: AnyObject {
|
||||
var delegate: UNUserNotificationCenterDelegate? { get set }
|
||||
func add(_ request: UNNotificationRequest) async throws
|
||||
func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool
|
||||
func deliveredNotifications() async -> [UNNotification]
|
||||
func removeDeliveredNotifications(withIdentifiers identifiers: [String])
|
||||
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
|
||||
func authorizationStatus() async -> UNAuthorizationStatus
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class InvitesScreenViewModelTests: XCTestCase {
|
||||
var viewModel: InvitesScreenViewModelProtocol!
|
||||
var clientProxy: MockClientProxy!
|
||||
var userSession: MockUserSession!
|
||||
var mockNotificationCenter: NotificationCenterMock!
|
||||
|
||||
var context: InvitesScreenViewModelType.Context {
|
||||
viewModel.context
|
||||
@@ -30,6 +31,7 @@ class InvitesScreenViewModelTests: XCTestCase {
|
||||
override func setUpWithError() throws {
|
||||
clientProxy = MockClientProxy(userID: "@a:b.com")
|
||||
userSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider())
|
||||
mockNotificationCenter = NotificationCenterMock()
|
||||
}
|
||||
|
||||
func testEmptyState() async throws {
|
||||
@@ -72,6 +74,14 @@ class InvitesScreenViewModelTests: XCTestCase {
|
||||
context.send(viewAction: .decline(.init(roomDetails: details, isUnread: false)))
|
||||
XCTAssertNotNil(context.alertInfo)
|
||||
}
|
||||
|
||||
func testHasAppeared() async {
|
||||
setupViewModel()
|
||||
context.send(viewAction: .appeared)
|
||||
|
||||
await Task.yield()
|
||||
XCTAssertEqual(mockNotificationCenter.postNameObjectReceivedArguments?.aName, .invitesScreenAppeared)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@@ -85,6 +95,7 @@ class InvitesScreenViewModelTests: XCTestCase {
|
||||
viewModel = InvitesScreenViewModel(userSession: userSession,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
notificationCenterProtocol: mockNotificationCenter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import NotificationCenter
|
||||
import XCTest
|
||||
|
||||
import Combine
|
||||
@testable import ElementX
|
||||
|
||||
final class NotificationManagerTests: XCTestCase {
|
||||
@@ -176,6 +177,32 @@ final class NotificationManagerTests: XCTestCase {
|
||||
await notificationManager.userNotificationCenter(UNUserNotificationCenter.current(), didReceive: response)
|
||||
XCTAssertTrue(notificationTappedDelegateCalled)
|
||||
}
|
||||
|
||||
func test_MessageNotificationsRemoval() async throws {
|
||||
// No interaction if the object is nil or of the wrong type
|
||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: nil)
|
||||
try await Task.sleep(for: .microseconds(200))
|
||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 0)
|
||||
|
||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: 1)
|
||||
try await Task.sleep(for: .microseconds(200))
|
||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
|
||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 0)
|
||||
|
||||
// The center calls the delivered and the removal functions when an id is passed
|
||||
NotificationCenter.default.post(name: .roomMarkedAsRead, object: "RoomID")
|
||||
try await Task.sleep(for: .microseconds(200))
|
||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 1)
|
||||
}
|
||||
|
||||
func test_InvitesNotificationsRemoval() async throws {
|
||||
NotificationCenter.default.post(name: .invitesScreenAppeared, object: nil)
|
||||
try await Task.sleep(for: .microseconds(200))
|
||||
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
|
||||
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 1)
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationManagerTests: NotificationManagerDelegate {
|
||||
|
||||
@@ -17,9 +17,20 @@
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
class UserNotificationCenterSpy: UserNotificationCenterProtocol {
|
||||
final class UserNotificationCenterSpy: UserNotificationCenterProtocol {
|
||||
weak var delegate: UNUserNotificationCenterDelegate?
|
||||
|
||||
|
||||
var deliveredNotificationsCallsCount = 0
|
||||
func deliveredNotifications() async -> [UNNotification] {
|
||||
deliveredNotificationsCallsCount += 1
|
||||
return []
|
||||
}
|
||||
|
||||
var removeDeliveredNotificationsCallsCount = 0
|
||||
func removeDeliveredNotifications(withIdentifiers identifiers: [String]) {
|
||||
removeDeliveredNotificationsCallsCount += 1
|
||||
}
|
||||
|
||||
var addRequest: UNNotificationRequest?
|
||||
func add(_ request: UNNotificationRequest) async throws {
|
||||
addRequest = request
|
||||
|
||||
@@ -349,6 +349,27 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
await Task.yield()
|
||||
XCTAssert(roomProxyMock.cancelSendTransactionIDCallsCount == 0)
|
||||
}
|
||||
|
||||
func testMarkAsRead() async {
|
||||
// Setup
|
||||
let notificationCenterMock = NotificationCenterMock()
|
||||
let timelineController = MockRoomTimelineController()
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: ""))
|
||||
|
||||
let viewModel = RoomScreenViewModel(timelineController: timelineController,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
roomProxy: roomProxyMock,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: userIndicatorControllerMock,
|
||||
notificationCenterProtocol: notificationCenterMock)
|
||||
|
||||
viewModel.context.send(viewAction: .markRoomAsRead)
|
||||
await Task.yield()
|
||||
XCTAssertEqual(notificationCenterMock.postNameObjectReceivedArguments?.aName, .roomMarkedAsRead)
|
||||
let roomID = notificationCenterMock.postNameObjectReceivedArguments?.anObject as? String
|
||||
XCTAssertEqual(roomID, roomProxyMock.id)
|
||||
}
|
||||
}
|
||||
|
||||
private extension TextRoomTimelineItem {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Push notifications for a room are cleared from the notification centre when opening its timeline. Same for invitations when opening the invite screen.
|
||||
Reference in New Issue
Block a user