Skip to content

Commit b7dea0a

Browse files
committed
Add test coverage to ChatThreadListView
1 parent 47a8578 commit b7dea0a

12 files changed

+290
-6
lines changed

β€ŽSources/StreamChatSwiftUI/ChatThreadList/ChatThreadListLoadingView.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import SwiftUI
88
public struct ChatThreadListLoadingView: View {
99
public var body: some View {
1010
ScrollView {
11-
LazyVStack {
11+
VStack {
1212
ForEach((0..<10)) { _ in
1313
ChatThreadListItemContentView(
1414
channelNameText: placeholder(length: 8),

β€ŽSources/StreamChatSwiftUI/CommonViews/FloatingBannerViewModifier.swiftβ€Ž

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ struct FloatingBannerViewModifier<BannerView: View>: ViewModifier {
5151
content
5252
if isPresented {
5353
bannerView()
54-
.animation(.easeInOut)
55-
.transition(
56-
.move(edge: alignment == .bottom ? .bottom : .top)
57-
.combined(with: .opacity)
58-
)
5954
}
6055
}
6156
}

β€ŽStreamChatSwiftUI.xcodeproj/project.pbxprojβ€Ž

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@
520520
ADE0F5622CB8556F0053B8B9 /* ChatThreadListFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE0F5612CB8556F0053B8B9 /* ChatThreadListFooterView.swift */; };
521521
ADE0F5642CB9609E0053B8B9 /* ChatThreadListHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE0F5632CB9609E0053B8B9 /* ChatThreadListHeaderView.swift */; };
522522
ADE0F5662CB962470053B8B9 /* ActionBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE0F5652CB962470053B8B9 /* ActionBannerView.swift */; };
523+
ADE442F02CBDAAB70066CDF7 /* ChatThreadListView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE442EF2CBDAAB70066CDF7 /* ChatThreadListView_Tests.swift */; };
523524
ADE442F22CBDAAC40066CDF7 /* ChatThreadListItemView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE442F12CBDAAC40066CDF7 /* ChatThreadListItemView_Tests.swift */; };
524525
C14A465B284665B100EF498E /* SDKIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14A465A284665B100EF498E /* SDKIdentifier.swift */; };
525526
E3A1C01C282BAC66002D1E26 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = E3A1C01B282BAC66002D1E26 /* Sentry */; };
@@ -1110,6 +1111,7 @@
11101111
ADE0F5612CB8556F0053B8B9 /* ChatThreadListFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListFooterView.swift; sourceTree = "<group>"; };
11111112
ADE0F5632CB9609E0053B8B9 /* ChatThreadListHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListHeaderView.swift; sourceTree = "<group>"; };
11121113
ADE0F5652CB962470053B8B9 /* ActionBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBannerView.swift; sourceTree = "<group>"; };
1114+
ADE442EF2CBDAAB70066CDF7 /* ChatThreadListView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListView_Tests.swift; sourceTree = "<group>"; };
11131115
ADE442F12CBDAAC40066CDF7 /* ChatThreadListItemView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListItemView_Tests.swift; sourceTree = "<group>"; };
11141116
C14A465A284665B100EF498E /* SDKIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKIdentifier.swift; sourceTree = "<group>"; };
11151117
/* End PBXFileReference section */
@@ -2263,7 +2265,15 @@
22632265
path = ChatThreadList;
22642266
sourceTree = "<group>";
22652267
};
2268+
ADE442EC2CBDAA320066CDF7 /* ChatThreadList */ = {
2269+
isa = PBXGroup;
2270+
children = (
2271+
ADE442EF2CBDAAB70066CDF7 /* ChatThreadListView_Tests.swift */,
22662272
ADE442F12CBDAAC40066CDF7 /* ChatThreadListItemView_Tests.swift */,
2273+
);
2274+
path = ChatThreadList;
2275+
sourceTree = "<group>";
2276+
};
22672277
/* End PBXGroup section */
22682278

22692279
/* Begin PBXHeadersBuildPhase section */
@@ -2960,6 +2970,7 @@
29602970
8423C34C277DDD250092DCF1 /* MuteCommandHandler_Tests.swift in Sources */,
29612971
84C94D1127578BF2007FE2B9 /* ChannelId.swift in Sources */,
29622972
84B2B5D628196FD100479CEE /* MediaAttachmentsView_Tests.swift in Sources */,
2973+
ADE442F02CBDAAB70066CDF7 /* ChatThreadListView_Tests.swift in Sources */,
29632974
84AB7B21277203EF00631A10 /* GalleryView_Tests.swift in Sources */,
29642975
84E0478D284A444E00BAFA17 /* ImageLoader_Mock.swift in Sources */,
29652976
8423C348277DBBDA0092DCF1 /* InstantCommandsHandler_Tests.swift in Sources */,
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
//
2+
// Copyright Β© 2024 Stream.io Inc. All rights reserved.
3+
//
4+
5+
import SnapshotTesting
6+
@testable import StreamChat
7+
@testable import StreamChatSwiftUI
8+
@testable import StreamChatTestTools
9+
import StreamSwiftTestHelpers
10+
import SwiftUI
11+
import XCTest
12+
13+
class ChatThreadListView_Tests: StreamChatTestCase {
14+
15+
func test_chatThreadListView_empty() {
16+
let view = makeView(.empty())
17+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
18+
}
19+
20+
func test_chatThreadListView_loading() {
21+
let view = makeView(.loading())
22+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
23+
}
24+
25+
func test_chatThreadListView_withThreads() {
26+
let view = makeView(.withThreads())
27+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
28+
}
29+
30+
func test_chatThreadListView_loadingMoreThreads() {
31+
let view = makeView(.loadingMoreThreads())
32+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
33+
}
34+
35+
func test_chatThreadListView_reloadingThreads() {
36+
let view = makeView(.reloadingThreads())
37+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
38+
}
39+
40+
func test_chatThreadListView_whenNewThreadsAvailable() {
41+
let view = makeView(.newThreadsAvailable())
42+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
43+
}
44+
45+
func test_chatThreadListView_errorLoadingThreads() {
46+
let view = makeView(.errorLoadingThreads())
47+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
48+
}
49+
50+
func test_chatThreadListView_errorLoadingMoreThreads() {
51+
let view = makeView(.errorLoadingMoreThreads())
52+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
53+
}
54+
55+
private func makeView(_ viewModel: MockChatThreadListViewModel) -> some View {
56+
ChatThreadListView(
57+
viewFactory: DefaultViewFactory.shared,
58+
viewModel: viewModel
59+
)
60+
.applyDefaultSize()
61+
}
62+
}
63+
64+
class CustomFactory: ViewFactory {
65+
@Injected(\.chatClient) public var chatClient
66+
67+
func makeThreadListLoadingView() -> some View {
68+
LoadingView()
69+
}
70+
}
71+
72+
private class MockChatThreadListViewModel: ChatThreadListViewModel {
73+
static func empty() -> MockChatThreadListViewModel {
74+
return MockChatThreadListViewModel(
75+
threads: [],
76+
isLoading: false,
77+
isReloading: false,
78+
isEmpty: true,
79+
failedToLoadThreads: false,
80+
failedToLoadMoreThreads: false,
81+
isLoadingMoreThreads: false,
82+
hasLoadedAllThreads: false,
83+
newThreadsCount: 0,
84+
hasNewThreads: false
85+
)
86+
}
87+
88+
static func loading() -> MockChatThreadListViewModel {
89+
return MockChatThreadListViewModel(
90+
threads: [],
91+
isLoading: true,
92+
isReloading: false,
93+
isEmpty: false,
94+
failedToLoadThreads: false,
95+
failedToLoadMoreThreads: false,
96+
isLoadingMoreThreads: false,
97+
hasLoadedAllThreads: false,
98+
newThreadsCount: 0,
99+
hasNewThreads: false
100+
)
101+
}
102+
103+
static func withThreads() -> MockChatThreadListViewModel {
104+
return MockChatThreadListViewModel(
105+
threads: mockThreads,
106+
isLoading: false,
107+
isReloading: false,
108+
isEmpty: false,
109+
failedToLoadThreads: false,
110+
failedToLoadMoreThreads: false,
111+
isLoadingMoreThreads: false,
112+
hasLoadedAllThreads: false,
113+
newThreadsCount: 0,
114+
hasNewThreads: false
115+
)
116+
}
117+
118+
static func loadingMoreThreads() -> MockChatThreadListViewModel {
119+
return MockChatThreadListViewModel(
120+
threads: mockThreads,
121+
isLoading: false,
122+
isReloading: false,
123+
isEmpty: false,
124+
failedToLoadThreads: false,
125+
failedToLoadMoreThreads: false,
126+
isLoadingMoreThreads: true,
127+
hasLoadedAllThreads: false,
128+
newThreadsCount: 0,
129+
hasNewThreads: false
130+
)
131+
}
132+
133+
static func reloadingThreads() -> MockChatThreadListViewModel {
134+
return MockChatThreadListViewModel(
135+
threads: mockThreads,
136+
isLoading: false,
137+
isReloading: true,
138+
isEmpty: false,
139+
failedToLoadThreads: false,
140+
failedToLoadMoreThreads: false,
141+
isLoadingMoreThreads: false,
142+
hasLoadedAllThreads: false,
143+
newThreadsCount: 0,
144+
hasNewThreads: false
145+
)
146+
}
147+
148+
static func newThreadsAvailable() -> MockChatThreadListViewModel {
149+
return MockChatThreadListViewModel(
150+
threads: mockThreads,
151+
isLoading: false,
152+
isReloading: false,
153+
isEmpty: false,
154+
failedToLoadThreads: false,
155+
failedToLoadMoreThreads: false,
156+
isLoadingMoreThreads: false,
157+
hasLoadedAllThreads: false,
158+
newThreadsCount: 2,
159+
hasNewThreads: true
160+
)
161+
}
162+
163+
static func errorLoadingThreads() -> MockChatThreadListViewModel {
164+
return MockChatThreadListViewModel(
165+
threads: [],
166+
isLoading: false,
167+
isReloading: false,
168+
isEmpty: true,
169+
failedToLoadThreads: true,
170+
failedToLoadMoreThreads: false,
171+
isLoadingMoreThreads: false,
172+
hasLoadedAllThreads: false,
173+
newThreadsCount: 0,
174+
hasNewThreads: false
175+
)
176+
}
177+
178+
static func errorLoadingMoreThreads() -> MockChatThreadListViewModel {
179+
return MockChatThreadListViewModel(
180+
threads: mockThreads,
181+
isLoading: false,
182+
isReloading: false,
183+
isEmpty: false,
184+
failedToLoadThreads: false,
185+
failedToLoadMoreThreads: true,
186+
isLoadingMoreThreads: false,
187+
hasLoadedAllThreads: false,
188+
newThreadsCount: 0,
189+
hasNewThreads: false
190+
)
191+
}
192+
193+
convenience init(
194+
threads: [ChatThread],
195+
isLoading: Bool,
196+
isReloading: Bool,
197+
isEmpty: Bool,
198+
failedToLoadThreads: Bool,
199+
failedToLoadMoreThreads: Bool,
200+
isLoadingMoreThreads: Bool,
201+
hasLoadedAllThreads: Bool,
202+
newThreadsCount: Int,
203+
hasNewThreads: Bool
204+
) {
205+
self.init(threadListController: nil, eventsController: nil)
206+
self.threads = LazyCachedMapCollection(elements: threads)
207+
self.isLoading = isLoading
208+
self.isReloading = isReloading
209+
self.isEmpty = isEmpty
210+
self.failedToLoadThreads = failedToLoadThreads
211+
self.failedToLoadMoreThreads = failedToLoadMoreThreads
212+
self.isLoadingMoreThreads = isLoadingMoreThreads
213+
self.hasLoadedAllThreads = hasLoadedAllThreads
214+
self.newThreadsCount = newThreadsCount
215+
self.hasNewThreads = hasNewThreads
216+
}
217+
218+
override func viewDidAppear() {}
219+
override func loadThreads() {}
220+
override func loadMoreThreads() {}
221+
override func controller(
222+
_ controller: ChatThreadListController,
223+
didChangeThreads changes: [ListChange<ChatThread>]
224+
) {}
225+
226+
227+
static var mockYoda = ChatUser.mock(id: .unique, name: "Yoda")
228+
static var mockVader = ChatUser.mock(id: .unique, name: "Vader")
229+
230+
static var mockThreads: [ChatThread] {
231+
[
232+
.mock(
233+
parentMessage: .mock(text: "Parent Message", author: mockYoda),
234+
channel: .mock(cid: .unique, name: "Star Wars Channel"),
235+
createdBy: mockVader,
236+
replyCount: 3,
237+
participantCount: 2,
238+
threadParticipants: [
239+
.mock(user: mockYoda),
240+
.mock(user: mockVader)
241+
],
242+
lastMessageAt: .unique,
243+
createdAt: .unique,
244+
updatedAt: .unique,
245+
title: nil,
246+
latestReplies: [
247+
.mock(text: "First Message", author: mockYoda),
248+
.mock(text: "Second Message", author: mockVader),
249+
.mock(text: "Third Message", author: mockYoda)
250+
],
251+
reads: [
252+
.mock(user: mockYoda, unreadMessagesCount: 6)
253+
],
254+
extraData: [:]
255+
),
256+
.mock(
257+
parentMessage: .mock(text: "Parent Message 2", author: mockYoda),
258+
channel: .mock(cid: .unique, name: "Marvel Channel"),
259+
createdBy: mockVader,
260+
replyCount: 3,
261+
participantCount: 2,
262+
threadParticipants: [
263+
.mock(user: mockYoda),
264+
.mock(user: mockVader)
265+
],
266+
lastMessageAt: .unique,
267+
createdAt: .unique,
268+
updatedAt: .unique,
269+
title: nil,
270+
latestReplies: [
271+
.mock(text: "First Message", author: mockVader)
272+
],
273+
reads: [],
274+
extraData: [:]
275+
)
276+
]
277+
}
278+
}
72.4 KB
Loading
Loading
Loading
72.4 KB
Loading
Loading
Loading

0 commit comments

Comments
Β (0)