Skip to content

Commit 2780c4a

Browse files
Updated the mocks for the offline feature
1 parent 3b7bbe6 commit 2780c4a

File tree

13 files changed

+350
-57
lines changed

13 files changed

+350
-57
lines changed

StreamChatSwiftUI.xcodeproj/project.pbxproj

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@
162162
846608E7278C95E700D3D7B3 /* ChatChannelExtensions_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846608E6278C95E700D3D7B3 /* ChatChannelExtensions_Tests.swift */; };
163163
846608E9278C98CB00D3D7B3 /* TypingIndicatorView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846608E8278C98CB00D3D7B3 /* TypingIndicatorView_Tests.swift */; };
164164
846D6564279FF0800094B36E /* ReactionUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846D6563279FF0800094B36E /* ReactionUserView.swift */; };
165+
847BA08127E0B76400ED20C7 /* Spy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BA08027E0B76400ED20C7 /* Spy.swift */; };
166+
847BA08327E0B9C600ED20C7 /* EventBatcherMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BA08227E0B9C600ED20C7 /* EventBatcherMock.swift */; };
167+
847BA08527E0BA2500ED20C7 /* EventNotificationCenterMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BA08427E0BA2500ED20C7 /* EventNotificationCenterMock.swift */; };
168+
847BA08727E0BACB00ED20C7 /* WebSocketPingControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BA08627E0BACB00ED20C7 /* WebSocketPingControllerMock.swift */; };
169+
847BA08927E0BAEE00ED20C7 /* WebSocketEngineMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BA08827E0BAEE00ED20C7 /* WebSocketEngineMock.swift */; };
165170
847CEFEC27BFAB6400606257 /* StreamChat in Frameworks */ = {isa = PBXBuildFile; productRef = 847CEFEB27BFAB6400606257 /* StreamChat */; };
166171
847CEFEE27C38ABE00606257 /* MessageCachingUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CEFED27C38ABE00606257 /* MessageCachingUtils.swift */; };
167172
848399EA275FB3E9003075E4 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 848399E9275FB3E9003075E4 /* SnapshotTesting */; };
@@ -486,6 +491,11 @@
486491
846608E6278C95E700D3D7B3 /* ChatChannelExtensions_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatChannelExtensions_Tests.swift; sourceTree = "<group>"; };
487492
846608E8278C98CB00D3D7B3 /* TypingIndicatorView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView_Tests.swift; sourceTree = "<group>"; };
488493
846D6563279FF0800094B36E /* ReactionUserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionUserView.swift; sourceTree = "<group>"; };
494+
847BA08027E0B76400ED20C7 /* Spy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Spy.swift; sourceTree = "<group>"; };
495+
847BA08227E0B9C600ED20C7 /* EventBatcherMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBatcherMock.swift; sourceTree = "<group>"; };
496+
847BA08427E0BA2500ED20C7 /* EventNotificationCenterMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventNotificationCenterMock.swift; sourceTree = "<group>"; };
497+
847BA08627E0BACB00ED20C7 /* WebSocketPingControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketPingControllerMock.swift; sourceTree = "<group>"; };
498+
847BA08827E0BAEE00ED20C7 /* WebSocketEngineMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketEngineMock.swift; sourceTree = "<group>"; };
489499
847CEFED27C38ABE00606257 /* MessageCachingUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCachingUtils.swift; sourceTree = "<group>"; };
490500
848399EB275FB41B003075E4 /* ChatChannelListView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatChannelListView_Tests.swift; sourceTree = "<group>"; };
491501
848399F127601231003075E4 /* ReactionsOverlayView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsOverlayView_Tests.swift; sourceTree = "<group>"; };
@@ -1044,6 +1054,7 @@
10441054
84C94CBB27578B92007FE2B9 /* NSManagedObject+ContextChange.swift */,
10451055
84C94CBC27578B92007FE2B9 /* DatabaseContainer_Mock.swift */,
10461056
84C94CCB27578B92007FE2B9 /* ChatClient_Mock.swift */,
1057+
847BA08027E0B76400ED20C7 /* Spy.swift */,
10471058
);
10481059
path = TestTools;
10491060
sourceTree = "<group>";
@@ -1157,6 +1168,10 @@
11571168
84C94D2B275796F7007FE2B9 /* RequestRecorderURLProtocol.swift */,
11581169
84C94D452757D1CA007FE2B9 /* ImageLoader_Mock.swift */,
11591170
84C94D5B275A2E9F007FE2B9 /* StreamChatUtilsMocks.swift */,
1171+
847BA08227E0B9C600ED20C7 /* EventBatcherMock.swift */,
1172+
847BA08427E0BA2500ED20C7 /* EventNotificationCenterMock.swift */,
1173+
847BA08627E0BACB00ED20C7 /* WebSocketPingControllerMock.swift */,
1174+
847BA08827E0BAEE00ED20C7 /* WebSocketEngineMock.swift */,
11601175
);
11611176
path = Mocks;
11621177
sourceTree = "<group>";
@@ -1597,6 +1612,8 @@
15971612
84C94D442757C704007FE2B9 /* MoreChannelActionsViewModel_Tests.swift in Sources */,
15981613
84C94D5127591DE2007FE2B9 /* ChatMessageIDs_Tests.swift in Sources */,
15991614
84C94CD727578B92007FE2B9 /* ChatMessageLinkAttachment_Mock.swift in Sources */,
1615+
847BA08327E0B9C600ED20C7 /* EventBatcherMock.swift in Sources */,
1616+
847BA08527E0BA2500ED20C7 /* EventNotificationCenterMock.swift in Sources */,
16001617
84C94D0527578BF2007FE2B9 /* TestRunnerEnvironment.swift in Sources */,
16011618
84E6EC23279AEE6B0017207B /* MessageContainerView_Tests.swift in Sources */,
16021619
84C94D68275A6AFD007FE2B9 /* ChannelHeaderLoader_Tests.swift in Sources */,
@@ -1609,11 +1626,13 @@
16091626
84C94CDB27578B92007FE2B9 /* NSManagedObject+ContextChange.swift in Sources */,
16101627
84C94D0C27578BF2007FE2B9 /* AssertJSONEqual.swift in Sources */,
16111628
84C94D62275A5BB7007FE2B9 /* ChatChannelNamer_Tests.swift in Sources */,
1629+
847BA08927E0BAEE00ED20C7 /* WebSocketEngineMock.swift in Sources */,
16121630
84C94D492758BE1C007FE2B9 /* ChatChannelViewModel_Tests.swift in Sources */,
16131631
84C94CE027578B92007FE2B9 /* CurrentUserPayload.swift in Sources */,
16141632
84C94CCD27578B92007FE2B9 /* ChannelUnreadCount_Mock.swift in Sources */,
16151633
84C94CDC27578B92007FE2B9 /* DatabaseContainer_Mock.swift in Sources */,
16161634
84C94D1727578BF3007FE2B9 /* XCTAssertEqual+Difference.swift in Sources */,
1635+
847BA08127E0B76400ED20C7 /* Spy.swift in Sources */,
16171636
84C94CE327578B92007FE2B9 /* XCTestCase+Dummy.swift in Sources */,
16181637
84C94D0D27578BF2007FE2B9 /* AssertResult.swift in Sources */,
16191638
84E6EC25279AEE9F0017207B /* StreamChatTestCase.swift in Sources */,
@@ -1655,6 +1674,7 @@
16551674
84C94CD127578B92007FE2B9 /* CurrentChatUser_Mock.swift in Sources */,
16561675
841B2EF6278F108700ED619E /* MessageReadIndicatorView_Tests.swift in Sources */,
16571676
84C94D0E27578BF2007FE2B9 /* AssertAsync.swift in Sources */,
1677+
847BA08727E0BACB00ED20C7 /* WebSocketPingControllerMock.swift in Sources */,
16581678
84C94D1327578BF2007FE2B9 /* XCTestCase+MockJSON.swift in Sources */,
16591679
84C94D5E275A3AA9007FE2B9 /* ImageCDN_Tests.swift in Sources */,
16601680
84C94CDF27578B92007FE2B9 /* MessagePayload.swift in Sources */,
@@ -2123,7 +2143,7 @@
21232143
isa = XCRemoteSwiftPackageReference;
21242144
repositoryURL = "https://github.com/GetStream/stream-chat-swift.git";
21252145
requirement = {
2126-
branch = "feature/CIS-1275-offline-support";
2146+
branch = develop;
21272147
kind = branch;
21282148
};
21292149
};

StreamChatSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

StreamChatSwiftUITests/Infrastructure/Mocks/APIClient_Mock.swift

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,24 @@ import Foundation
77
import XCTest
88

99
/// Mock implementation of APIClient allowing easy control and simulation of responses.
10-
class APIClientMock: APIClient {
11-
@Atomic var request_allRecordedCalls: [(endpoint: AnyEndpoint, completion: Any?)] = []
12-
10+
class APIClientMock: APIClient, Spy {
11+
var recordedFunctions: [String] = []
12+
1313
/// The last endpoint `request` function was called with.
1414
@Atomic var request_endpoint: AnyEndpoint?
1515
@Atomic var request_completion: Any?
16+
@Atomic var request_allRecordedCalls: [(endpoint: AnyEndpoint, completion: Any?)] = []
17+
18+
/// The last endpoint `recoveryRequest` function was called with.
19+
@Atomic var recoveryRequest_endpoint: AnyEndpoint?
20+
@Atomic var recoveryRequest_completion: Any?
21+
@Atomic var recoveryRequest_allRecordedCalls: [(endpoint: AnyEndpoint, completion: Any?)] = []
1622

1723
/// The last endpoint `uploadFile` function was called with.
1824
@Atomic var uploadFile_attachment: AnyChatMessageAttachment?
1925
@Atomic var uploadFile_progress: ((Double) -> Void)?
2026
@Atomic var uploadFile_completion: ((Result<URL, Error>) -> Void)?
2127

22-
/// The last params `flushRequestsQueue` function was called with.
23-
@Atomic var flushRequestsQueue_timeout: TimeInterval?
24-
@Atomic var flushRequestsQueue_itemAction: ((APIClient.RequestsQueueItem) -> Void)?
25-
2628
@Atomic var init_sessionConfiguration: URLSessionConfiguration
2729
@Atomic var init_requestEncoder: RequestEncoder
2830
@Atomic var init_requestDecoder: RequestDecoder
@@ -39,17 +41,15 @@ class APIClientMock: APIClient {
3941
uploadFile_attachment = nil
4042
uploadFile_progress = nil
4143
uploadFile_completion = nil
42-
43-
flushRequestsQueue_timeout = nil
44-
flushRequestsQueue_itemAction = nil
4544
}
46-
45+
4746
override init(
4847
sessionConfiguration: URLSessionConfiguration,
4948
requestEncoder: RequestEncoder,
5049
requestDecoder: RequestDecoder,
5150
CDNClient: CDNClient,
52-
tokenRefresher: ((ClientError, @escaping () -> Void) -> Void)!
51+
tokenRefresher: ((@escaping () -> Void) -> Void)!,
52+
queueOfflineRequest: @escaping QueueOfflineRequestBlock
5353
) {
5454
init_sessionConfiguration = sessionConfiguration
5555
init_requestEncoder = requestEncoder
@@ -62,26 +62,40 @@ class APIClientMock: APIClient {
6262
requestEncoder: requestEncoder,
6363
requestDecoder: requestDecoder,
6464
CDNClient: CDNClient,
65-
tokenRefresher: tokenRefresher
65+
tokenRefresher: tokenRefresher,
66+
queueOfflineRequest: queueOfflineRequest
6667
)
6768
}
6869

6970
/// Simulates the response of the last `request` method call
7071
func test_simulateResponse<Response: Decodable>(_ response: Result<Response, Error>) {
71-
let completion = request_completion as! ((Result<Response, Error>) -> Void)
72-
completion(response)
72+
let completion = request_completion as? ((Result<Response, Error>) -> Void)
73+
completion?(response)
74+
}
75+
76+
func test_simulateRecoveryResponse<Response: Decodable>(_ response: Result<Response, Error>) {
77+
let completion = recoveryRequest_completion as? ((Result<Response, Error>) -> Void)
78+
completion?(response)
7379
}
7480

7581
override func request<Response>(
7682
endpoint: Endpoint<Response>,
77-
timeout: TimeInterval,
7883
completion: @escaping (Result<Response, Error>) -> Void
7984
) where Response: Decodable {
8085
request_endpoint = AnyEndpoint(endpoint)
8186
request_completion = completion
8287
_request_allRecordedCalls.mutate { $0.append((request_endpoint!, request_completion!)) }
8388
request_expectation.fulfill()
8489
}
90+
91+
override func recoveryRequest<Response>(
92+
endpoint: Endpoint<Response>,
93+
completion: @escaping (Result<Response, Error>) -> Void
94+
) where Response: Decodable {
95+
recoveryRequest_endpoint = AnyEndpoint(endpoint)
96+
recoveryRequest_completion = completion
97+
_recoveryRequest_allRecordedCalls.mutate { $0.append((recoveryRequest_endpoint!, recoveryRequest_completion!)) }
98+
}
8599

86100
override func uploadAttachment(
87101
_ attachment: AnyChatMessageAttachment,
@@ -92,20 +106,26 @@ class APIClientMock: APIClient {
92106
uploadFile_progress = progress
93107
uploadFile_completion = completion
94108
}
95-
96-
override func flushRequestsQueue(
97-
after timeout: TimeInterval = 0,
98-
itemAction: ((APIClient.RequestsQueueItem) -> Void)? = nil
99-
) {
100-
flushRequestsQueue_timeout = timeout
101-
flushRequestsQueue_itemAction = itemAction
109+
110+
override func flushRequestsQueue() {
111+
record()
102112
}
103113

104114
@discardableResult
105115
func waitForRequest(timeout: Double = 0.5) -> AnyEndpoint? {
106116
XCTWaiter().wait(for: [request_expectation], timeout: timeout)
107117
return request_endpoint
108118
}
119+
120+
override func enterRecoveryMode() {
121+
record()
122+
super.enterRecoveryMode()
123+
}
124+
125+
override func exitRecoveryMode() {
126+
record()
127+
super.exitRecoveryMode()
128+
}
109129
}
110130

111131
extension APIClientMock {
@@ -115,7 +135,8 @@ extension APIClientMock {
115135
requestEncoder: DefaultRequestEncoder(baseURL: .unique(), apiKey: .init(.unique)),
116136
requestDecoder: DefaultRequestDecoder(),
117137
CDNClient: CDNClient_Mock(),
118-
tokenRefresher: { _, _ in }
138+
tokenRefresher: { _ in },
139+
queueOfflineRequest: { _ in }
119140
)
120141
}
121142
}

StreamChatSwiftUITests/Infrastructure/Mocks/AnyEndpoint.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66
@testable import StreamChat
77

88
struct AnyEndpoint: Equatable {
9-
let path: String
9+
let path: EndpointPath
1010
let method: EndpointMethod
1111
let queryItems: AnyEncodable?
1212
let requiresConnectionId: Bool
@@ -23,7 +23,7 @@ struct AnyEndpoint: Equatable {
2323
}
2424

2525
static func == (lhs: AnyEndpoint, rhs: AnyEndpoint) -> Bool {
26-
lhs.path == rhs.path
26+
lhs.path.value == rhs.path.value
2727
&& lhs.method == rhs.method
2828
&& lhs.queryItems == rhs.queryItems
2929
&& lhs.requiresConnectionId == rhs.requiresConnectionId
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// Copyright © 2022 Stream.io Inc. All rights reserved.
3+
//
4+
5+
import Foundation
6+
@testable import StreamChat
7+
8+
final class EventBatcherMock: EventBatcher {
9+
var currentBatch: [Event] = []
10+
11+
let handler: ([Event]) -> Void
12+
13+
init(
14+
period: TimeInterval = 0,
15+
timerType: StreamChat.Timer.Type = DefaultTimer.self,
16+
handler: @escaping ([Event]) -> Void
17+
) {
18+
self.handler = handler
19+
}
20+
21+
lazy var mock_append = MockFunc.mock(for: append)
22+
23+
func append(_ event: Event) {
24+
mock_append.call(with: (event))
25+
26+
handler([event])
27+
}
28+
29+
lazy var mock_processImmediately = MockFunc.mock(for: processImmediately)
30+
31+
func processImmediately() {
32+
mock_processImmediately.call(with: ())
33+
}
34+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// Copyright © 2022 Stream.io Inc. All rights reserved.
3+
//
4+
5+
import Foundation
6+
@testable import StreamChat
7+
8+
/// Mock implementation of `EventNotificationCenter`
9+
final class EventNotificationCenterMock: EventNotificationCenter {
10+
lazy var mock_process = MockFunc<([Event], Bool, (() -> Void)?), Void>.mock(for: process)
11+
12+
override func process(
13+
_ events: [Event],
14+
postNotifications: Bool = true,
15+
completion: (() -> Void)? = nil
16+
) {
17+
super.process(events, postNotifications: postNotifications, completion: completion)
18+
19+
mock_process.call(with: (events, postNotifications, completion))
20+
}
21+
}

StreamChatSwiftUITests/Infrastructure/Mocks/MockBackgroundTaskScheduler.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@
55
import Foundation
66
@testable import StreamChat
77

8-
class MockBackgroundTaskScheduler: BackgroundTaskScheduler {
8+
/// Mock implementation of `BackgroundTaskScheduler`.
9+
final class MockBackgroundTaskScheduler: BackgroundTaskScheduler {
10+
var isAppActive_called: Bool = false
11+
var isAppActive_returns: Bool = true
12+
var isAppActive: Bool {
13+
isAppActive_called = true
14+
return isAppActive_returns
15+
}
16+
917
var beginBackgroundTask_called: Bool = false
1018
var beginBackgroundTask_expirationHandler: (() -> Void)?
1119
var beginBackgroundTask_returns: Bool = true
@@ -37,3 +45,15 @@ class MockBackgroundTaskScheduler: BackgroundTaskScheduler {
3745
stopListeningForAppStateUpdates_called = true
3846
}
3947
}
48+
49+
extension MockBackgroundTaskScheduler {
50+
func simulateAppGoingToBackground() {
51+
isAppActive_returns = false
52+
startListeningForAppStateUpdates_onBackground?()
53+
}
54+
55+
func simulateAppGoingToForeground() {
56+
isAppActive_returns = true
57+
startListeningForAppStateUpdates_onForeground?()
58+
}
59+
}

0 commit comments

Comments
 (0)