-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathProjectActivitiesViewModelTests.swift
206 lines (167 loc) · 8.55 KB
/
ProjectActivitiesViewModelTests.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import XCTest
@testable import Library
@testable import KsApi
@testable import ReactiveExtensions_TestHelpers
import Result
import KsApi
import Prelude
final class ProjectActivitiesViewModelTests: TestCase {
fileprivate let vm: ProjectActivitiesViewModelType = ProjectActivitiesViewModel()
fileprivate let activitiesPresent = TestObserver<Bool, NoError>()
fileprivate let goTo = TestObserver<ProjectActivitiesGoTo, NoError>()
fileprivate let groupedDates = TestObserver<Bool, NoError>()
fileprivate let isRefreshing = TestObserver<Bool, NoError>()
fileprivate let project = TestObserver<Project, NoError>()
fileprivate let showEmptyState = TestObserver<Bool, NoError>()
override func setUp() {
super.setUp()
self.vm.outputs.projectActivityData
.map { !$0.activities.isEmpty }
.observe(self.activitiesPresent.observer)
self.vm.outputs.goTo.observe(self.goTo.observer)
self.vm.outputs.isRefreshing.observe(self.isRefreshing.observer)
self.vm.outputs.projectActivityData
.map { $0.project }
.observe(self.project.observer)
self.vm.outputs.projectActivityData
.map { $0.groupedDates }
.observe(self.groupedDates.observer)
self.vm.outputs.showEmptyState.observe(self.showEmptyState.observer)
AppEnvironment.login(AccessTokenEnvelope(accessToken: "deadbeef", user: .template))
}
func testFlow() {
let project = Project.template
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse:
[.template |> Activity.lens.id .~ 1])) {
self.vm.inputs.configureWith(project)
self.vm.inputs.viewDidLoad()
self.activitiesPresent.assertDidNotEmitValue("No activities")
self.scheduler.advance()
self.activitiesPresent.assertValues([true], "Show activities after scheduler advances")
self.groupedDates.assertValues([true], "Group dates by default")
self.project.assertValues([project], "Emits project")
XCTAssertEqual(["Viewed Project Activity", "Creator Activity View"],
self.trackingClient.events, "View event and its deprecated version are tracked")
}
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse:
[.template |> Activity.lens.id .~ 2])) {
self.vm.inputs.refresh()
self.scheduler.advance()
self.activitiesPresent.assertValues([true, true], "Activities refreshed")
self.groupedDates.assertValues([true, true], "Group dates by default")
self.project.assertValues([project, project], "Emits project")
XCTAssertEqual(["Viewed Project Activity", "Creator Activity View", "Loaded Newer Project Activity",
"Creator Activity View Load Newer"],
self.trackingClient.events, "Load newer event and its deprecated version are tracked")
}
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse:
[.template |> Activity.lens.id .~ 3])) {
self.vm.inputs.willDisplayRow(9, outOf: 10)
self.scheduler.advance()
self.activitiesPresent.assertValues([true, true, true], "Activities paginate")
self.groupedDates.assertValues([true, true, true], "Group dates by default")
self.project.assertValues([project, project, project], "Emits project")
XCTAssertEqual(["Viewed Project Activity", "Creator Activity View", "Loaded Newer Project Activity",
"Creator Activity View Load Newer", "Loaded Older Project Activity",
"Creator Activity View Load Older"],
self.trackingClient.events, "Load older event and its deprecated version are tracked")
}
self.showEmptyState.assertValues([false],
"Don't show, because each activity emission was a non-empty array")
}
func testEmptyState() {
let project = Project.template
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse: [])) {
self.vm.inputs.configureWith(project)
self.vm.inputs.viewDidLoad()
self.scheduler.advance()
self.activitiesPresent.assertValues([false], "No activities")
self.showEmptyState.assertValues([true], "Activities not present, show empty state")
self.project.assertValues([project], "Emits project")
}
}
func testGoTo() {
let project = Project.template
let comment = Comment.template
let backing = Backing.template |> Backing.lens.projectId .~ project.id
let update = Update.template
let user = User.template
let backingActivity = .template
|> Activity.lens.category .~ .backing
|> Activity.lens.memberData.backing .~ backing
|> Activity.lens.project .~ project
|> Activity.lens.user .~ user
let commentPostActivity = .template
|> Activity.lens.category .~ .commentPost
|> Activity.lens.comment .~ comment
|> Activity.lens.project .~ project
|> Activity.lens.update .~ update
|> Activity.lens.user .~ user
let commentProjectActivity = .template
|> Activity.lens.category .~ .commentProject
|> Activity.lens.comment .~ comment
|> Activity.lens.project .~ project
|> Activity.lens.user .~ user
let successActivity = .template
|> Activity.lens.category .~ .failure
|> Activity.lens.project .~ (project |> Project.lens.state .~ .successful)
|> Activity.lens.user .~ user
let updateActivity = .template
|> Activity.lens.category .~ .update
|> Activity.lens.project .~ project
|> Activity.lens.update .~ update
|> Activity.lens.user .~ user
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse:
[backingActivity, commentPostActivity, commentProjectActivity, successActivity, updateActivity])) {
self.vm.inputs.configureWith(project)
self.vm.inputs.viewDidLoad()
self.scheduler.advance()
// Testing when cells are tapped for different categories of activity
self.vm.inputs.activityAndProjectCellTapped(activity: backingActivity, project: project)
self.goTo.assertValueCount(1, "Should go to backing")
self.vm.inputs.activityAndProjectCellTapped(activity: commentPostActivity, project: project)
self.goTo.assertValueCount(2, "Should go to comments for update")
self.vm.inputs.activityAndProjectCellTapped(activity: commentProjectActivity, project: project)
self.goTo.assertValueCount(3, "Should go to comments for project")
self.vm.inputs.activityAndProjectCellTapped(activity: successActivity, project: project)
self.goTo.assertValueCount(4, "Should go to project")
self.vm.inputs.activityAndProjectCellTapped(activity: updateActivity, project: project)
self.goTo.assertValueCount(5, "Should go to update")
// Testing delegate methods
self.vm.inputs.projectActivityBackingCellGoToBacking(project: project, user: user)
self.goTo.assertValueCount(6, "Should go to backing")
self.vm.inputs.projectActivityBackingCellGoToSendMessage(project: project, backing: backing)
self.goTo.assertValueCount(7, "Should go to send message")
self.vm.inputs.projectActivityCommentCellGoToBacking(project: project, user: user)
self.goTo.assertValueCount(8, "Should go to backing")
self.vm.inputs.projectActivityCommentCellGoToSendReply(project: project, update: nil, comment: comment)
self.goTo.assertValueCount(9, "Should go to comments for project")
self.vm.inputs.projectActivityCommentCellGoToSendReply(project: project,
update: update,
comment: comment)
self.goTo.assertValueCount(10, "Should go to comments for update")
}
}
func testGroupedDatesWhenVoiceOverIsNotRunning() {
let project = Project.template
let activities = [.template |> Activity.lens.project .~ project]
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse: activities),
isVoiceOverRunning: { false }) {
self.vm.inputs.configureWith(project)
self.vm.inputs.viewDidLoad()
self.scheduler.advance()
self.groupedDates.assertValues([true], "Group dates when voice over is not running")
}
}
func testGroupedDatesWhenVoiceOverIsRunning() {
let project = Project.template
let activities = [.template |> Activity.lens.project .~ project]
withEnvironment(apiService: MockService(fetchProjectActivitiesResponse: activities),
isVoiceOverRunning: { true }) {
self.vm.inputs.configureWith(project)
self.vm.inputs.viewDidLoad()
self.scheduler.advance()
self.groupedDates.assertValues([false], "Don't group dates when voice over is running")
}
}
}