Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 59 additions & 20 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

235 changes: 235 additions & 0 deletions ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11556,13 +11556,248 @@ class MediaProviderMock: MediaProviderProtocol, @unchecked Sendable {
}
}
}
class NSEUserSessionMock: NSEUserSessionProtocol, @unchecked Sendable {
var inviteAvatarsVisibilityCallsCount = 0
var inviteAvatarsVisibilityCalled: Bool {
return inviteAvatarsVisibilityCallsCount > 0
}

var inviteAvatarsVisibility: InviteAvatars {
get async {
inviteAvatarsVisibilityCallsCount += 1
if let inviteAvatarsVisibilityClosure = inviteAvatarsVisibilityClosure {
return await inviteAvatarsVisibilityClosure()
} else {
return underlyingInviteAvatarsVisibility
}
}
}
var underlyingInviteAvatarsVisibility: InviteAvatars!
var inviteAvatarsVisibilityClosure: (() async -> InviteAvatars)?
var mediaPreviewVisibilityCallsCount = 0
var mediaPreviewVisibilityCalled: Bool {
return mediaPreviewVisibilityCallsCount > 0
}

var mediaPreviewVisibility: MediaPreviews {
get async {
mediaPreviewVisibilityCallsCount += 1
if let mediaPreviewVisibilityClosure = mediaPreviewVisibilityClosure {
return await mediaPreviewVisibilityClosure()
} else {
return underlyingMediaPreviewVisibility
}
}
}
var underlyingMediaPreviewVisibility: MediaPreviews!
var mediaPreviewVisibilityClosure: (() async -> MediaPreviews)?
var threadsEnabled: Bool {
get { return underlyingThreadsEnabled }
set(value) { underlyingThreadsEnabled = value }
}
var underlyingThreadsEnabled: Bool!

//MARK: - notificationItemProxy

var notificationItemProxyRoomIDEventIDUnderlyingCallsCount = 0
var notificationItemProxyRoomIDEventIDCallsCount: Int {
get {
if Thread.isMainThread {
return notificationItemProxyRoomIDEventIDUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = notificationItemProxyRoomIDEventIDUnderlyingCallsCount
}

return returnValue!
}
}
set {
if Thread.isMainThread {
notificationItemProxyRoomIDEventIDUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
notificationItemProxyRoomIDEventIDUnderlyingCallsCount = newValue
}
}
}
}
var notificationItemProxyRoomIDEventIDCalled: Bool {
return notificationItemProxyRoomIDEventIDCallsCount > 0
}
var notificationItemProxyRoomIDEventIDReceivedArguments: (roomID: String, eventID: String)?
var notificationItemProxyRoomIDEventIDReceivedInvocations: [(roomID: String, eventID: String)] = []

var notificationItemProxyRoomIDEventIDUnderlyingReturnValue: NotificationItemProxyProtocol?
var notificationItemProxyRoomIDEventIDReturnValue: NotificationItemProxyProtocol? {
get {
if Thread.isMainThread {
return notificationItemProxyRoomIDEventIDUnderlyingReturnValue
} else {
var returnValue: NotificationItemProxyProtocol?? = nil
DispatchQueue.main.sync {
returnValue = notificationItemProxyRoomIDEventIDUnderlyingReturnValue
}

return returnValue!
}
}
set {
if Thread.isMainThread {
notificationItemProxyRoomIDEventIDUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
notificationItemProxyRoomIDEventIDUnderlyingReturnValue = newValue
}
}
}
}
var notificationItemProxyRoomIDEventIDClosure: ((String, String) async -> NotificationItemProxyProtocol?)?

func notificationItemProxy(roomID: String, eventID: String) async -> NotificationItemProxyProtocol? {
notificationItemProxyRoomIDEventIDCallsCount += 1
notificationItemProxyRoomIDEventIDReceivedArguments = (roomID: roomID, eventID: eventID)
DispatchQueue.main.async {
self.notificationItemProxyRoomIDEventIDReceivedInvocations.append((roomID: roomID, eventID: eventID))
}
if let notificationItemProxyRoomIDEventIDClosure = notificationItemProxyRoomIDEventIDClosure {
return await notificationItemProxyRoomIDEventIDClosure(roomID, eventID)
} else {
return notificationItemProxyRoomIDEventIDReturnValue
}
}
//MARK: - roomForIdentifier

var roomForIdentifierUnderlyingCallsCount = 0
var roomForIdentifierCallsCount: Int {
get {
if Thread.isMainThread {
return roomForIdentifierUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = roomForIdentifierUnderlyingCallsCount
}

return returnValue!
}
}
set {
if Thread.isMainThread {
roomForIdentifierUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
roomForIdentifierUnderlyingCallsCount = newValue
}
}
}
}
var roomForIdentifierCalled: Bool {
return roomForIdentifierCallsCount > 0
}
var roomForIdentifierReceivedRoomID: String?
var roomForIdentifierReceivedInvocations: [String] = []

var roomForIdentifierUnderlyingReturnValue: Room?
var roomForIdentifierReturnValue: Room? {
get {
if Thread.isMainThread {
return roomForIdentifierUnderlyingReturnValue
} else {
var returnValue: Room?? = nil
DispatchQueue.main.sync {
returnValue = roomForIdentifierUnderlyingReturnValue
}

return returnValue!
}
}
set {
if Thread.isMainThread {
roomForIdentifierUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
roomForIdentifierUnderlyingReturnValue = newValue
}
}
}
}
var roomForIdentifierClosure: ((String) -> Room?)?

func roomForIdentifier(_ roomID: String) -> Room? {
roomForIdentifierCallsCount += 1
roomForIdentifierReceivedRoomID = roomID
DispatchQueue.main.async {
self.roomForIdentifierReceivedInvocations.append(roomID)
}
if let roomForIdentifierClosure = roomForIdentifierClosure {
return roomForIdentifierClosure(roomID)
} else {
return roomForIdentifierReturnValue
}
}
}
class NetworkMonitorMock: NetworkMonitorProtocol, @unchecked Sendable {
var reachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never> {
get { return underlyingReachabilityPublisher }
set(value) { underlyingReachabilityPublisher = value }
}
var underlyingReachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never>!

}
class NotificationItemProxyMock: NotificationItemProxyProtocol, @unchecked Sendable {
var event: NotificationEvent?
var senderID: String {
get { return underlyingSenderID }
set(value) { underlyingSenderID = value }
}
var underlyingSenderID: String!
var roomID: String {
get { return underlyingRoomID }
set(value) { underlyingRoomID = value }
}
var underlyingRoomID: String!
var receiverID: String {
get { return underlyingReceiverID }
set(value) { underlyingReceiverID = value }
}
var underlyingReceiverID: String!
var senderDisplayName: String?
var senderAvatarMediaSource: MediaSourceProxy?
var roomDisplayName: String {
get { return underlyingRoomDisplayName }
set(value) { underlyingRoomDisplayName = value }
}
var underlyingRoomDisplayName: String!
var roomAvatarMediaSource: MediaSourceProxy?
var roomJoinedMembers: Int {
get { return underlyingRoomJoinedMembers }
set(value) { underlyingRoomJoinedMembers = value }
}
var underlyingRoomJoinedMembers: Int!
var isRoomDirect: Bool {
get { return underlyingIsRoomDirect }
set(value) { underlyingIsRoomDirect = value }
}
var underlyingIsRoomDirect: Bool!
var isRoomPrivate: Bool {
get { return underlyingIsRoomPrivate }
set(value) { underlyingIsRoomPrivate = value }
}
var underlyingIsRoomPrivate: Bool!
var isNoisy: Bool {
get { return underlyingIsNoisy }
set(value) { underlyingIsNoisy = value }
}
var underlyingIsNoisy: Bool!
var hasMention: Bool {
get { return underlyingHasMention }
set(value) { underlyingHasMention = value }
}
var underlyingHasMention: Bool!
var threadRootEventID: String?

}
class NotificationManagerMock: NotificationManagerProtocol, @unchecked Sendable {
weak var delegate: NotificationManagerDelegate?
Expand Down
24 changes: 24 additions & 0 deletions ElementX/Sources/Mocks/NSEUserSessionMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Copyright 2025 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 MatrixRustSDK

struct NSEUserSessionMockConfiguration {
var inviteAvatarsVisibility = InviteAvatars.on
var mediaPreviewVisibility = MediaPreviews.on
var threadsEnabled = true
}

extension NSEUserSessionMock {
convenience init(_ configuration: NSEUserSessionMockConfiguration) {
self.init()

underlyingInviteAvatarsVisibility = configuration.inviteAvatarsVisibility
underlyingMediaPreviewVisibility = configuration.mediaPreviewVisibility
underlyingThreadsEnabled = configuration.threadsEnabled
}
}
55 changes: 55 additions & 0 deletions ElementX/Sources/Mocks/NotificationItemProxyMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright 2025 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 Foundation
import MatrixRustSDK

struct NotificationItemProxyMockConfiguration {
var event: NotificationEvent? = {
// This is likely the most common notification kind
// So it's also the best to use as a default test
let messageType = MessageType.text(content: TextMessageContent(body: "Hello world!", formatted: nil))
let messageLikeContent = MessageLikeEventContent.roomMessage(messageType: messageType, inReplyToEventId: nil)
let event = TimelineEventSDKMock()
event.eventIdUnderlyingReturnValue = UUID().uuidString
event.eventTypeReturnValue = TimelineEventType.messageLike(content: messageLikeContent)
return .timeline(event: event)
}()

var senderID: String = UUID().uuidString
var roomID: String = UUID().uuidString
var receiverID: String = UUID().uuidString
var senderDisplayName: String?
var senderAvatarMediaSource: MediaSourceProxy?
var roomAvatarMediaSource: MediaSourceProxy?
var roomDisplayName: String
var roomJoinedMembers = 2
var isRoomDirect = false
var isRoomPrivate = false
var isNoisy = false
var hasMention = false
var threadRootEventID: String?
}

extension NotificationItemProxyMock {
convenience init(_ configuration: NotificationItemProxyMockConfiguration) {
self.init()
event = configuration.event
underlyingSenderID = configuration.senderID
underlyingRoomID = configuration.roomID
underlyingReceiverID = configuration.receiverID
senderDisplayName = configuration.senderDisplayName
roomAvatarMediaSource = configuration.roomAvatarMediaSource
underlyingRoomDisplayName = configuration.roomDisplayName
underlyingRoomJoinedMembers = configuration.roomJoinedMembers
underlyingIsRoomDirect = configuration.isRoomDirect
underlyingIsRoomPrivate = configuration.isRoomPrivate
underlyingIsNoisy = configuration.isNoisy
underlyingHasMention = configuration.hasMention
threadRootEventID = configuration.threadRootEventID
}
}
7 changes: 7 additions & 0 deletions ElementX/SupportingFiles/target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,10 @@ targets:
- path: ../SupportingFiles
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX
- path: ../../DevelopmentAssets/Media

# This is required for testing purposes... The problem with unit tests is that if you
# try to `@testable import NSE` you can only get the definition of files, but due to a
# limitation in how they work, they can only compile files that are part of the main test
# target, so linking will fail. The solution is to just have the main app to reference the
# extension code, and test it directly.
- path: ../../NSE/Sources
19 changes: 16 additions & 3 deletions NSE/Sources/NSEUserSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
import Foundation
import MatrixRustSDK

final class NSEUserSession {
let sessionDirectories: SessionDirectories
let appSettings: CommonSettingsProtocol
// sourcery: AutoMockable
protocol NSEUserSessionProtocol {
var inviteAvatarsVisibility: InviteAvatars { get async }
var mediaPreviewVisibility: MediaPreviews { get async }
var threadsEnabled: Bool { get }

func notificationItemProxy(roomID: String, eventID: String) async -> NotificationItemProxyProtocol?
func roomForIdentifier(_ roomID: String) -> Room?
}

final class NSEUserSession: NSEUserSessionProtocol {
private let sessionDirectories: SessionDirectories
private let appSettings: CommonSettingsProtocol
private let baseClient: Client
private let notificationClient: NotificationClient
private let userID: String
Expand Down Expand Up @@ -42,6 +51,10 @@ final class NSEUserSession {
}
}
}

var threadsEnabled: Bool {
appSettings.threadsEnabled
}

init(credentials: KeychainCredentials,
roomID: String,
Expand Down
Loading
Loading