Skip to content

Commit adde145

Browse files
committed
Cover RealPostFetcherServices
Signed-off-by: Matt Ramotar <[email protected]>
1 parent 33c1bcf commit adde145

File tree

2 files changed

+234
-0
lines changed
  • xplat/lib/repositories/post/impl/src

2 files changed

+234
-0
lines changed

xplat/lib/repositories/post/impl/src/commonMain/kotlin/org/mobilenativefoundation/trails/xplat/lib/repositories/post/impl/store/fetcher/RealPostFetcherServices.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ class RealPostFetcherServices(
146146
)
147147
)
148148

149+
output.values.filterIsInstance<Post.Composite>().forEach { post ->
150+
// Save the post and associated entities
151+
postDAO.insertOneComposite(post)
152+
}
153+
149154
emit(output)
150155
}
151156

xplat/lib/repositories/post/impl/src/commonTest/kotlin/org/mobilenativefoundation/trails/xplat/lib/repositories/post/impl/store/fetcher/RealPostFetcherServicesTest.kt

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import app.cash.turbine.test
44
import dev.mokkery.MockMode
55
import dev.mokkery.answering.returns
66
import dev.mokkery.everySuspend
7+
import dev.mokkery.matcher.eq
78
import dev.mokkery.matcher.ofType
89
import dev.mokkery.mock
910
import dev.mokkery.verifySuspend
@@ -12,11 +13,15 @@ import kotlinx.coroutines.test.runTest
1213
import kotlinx.datetime.Clock
1314
import kotlinx.datetime.TimeZone
1415
import kotlinx.datetime.toLocalDateTime
16+
import org.mobilenativefoundation.trails.xplat.lib.models.post.Creator
1517
import org.mobilenativefoundation.trails.xplat.lib.models.post.Platform
1618
import org.mobilenativefoundation.trails.xplat.lib.models.post.Post
1719
import org.mobilenativefoundation.trails.xplat.lib.models.post.PostOutput
1820
import org.mobilenativefoundation.trails.xplat.lib.operations.io.Operation
21+
import org.mobilenativefoundation.trails.xplat.lib.operations.io.Operation.Query.QueryMany
22+
import org.mobilenativefoundation.trails.xplat.lib.operations.io.Operation.Query.QueryOne
1923
import org.mobilenativefoundation.trails.xplat.lib.operations.query.DataSources
24+
import org.mobilenativefoundation.trails.xplat.lib.operations.query.Query
2025
import org.mobilenativefoundation.trails.xplat.lib.repositories.post.impl.extensions.PostExtensions.asPostEntity
2126
import org.mobilenativefoundation.trails.xplat.lib.repositories.post.impl.store.database.PostDAO
2227
import org.mobilenativefoundation.trails.xplat.lib.rest.api.post.PostOperations
@@ -29,6 +34,61 @@ class RealPostFetcherServicesTest {
2934
private val postDAO = mock<PostDAO>(MockMode.autoUnit)
3035
private val postFetcherServices = RealPostFetcherServices(client, postDAO)
3136

37+
@Test
38+
fun findAndEmitOne_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() = runTest {
39+
// Given
40+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
41+
42+
val operation = Operation.Query.FindOne(
43+
key = Post.Key(1),
44+
dataSources = DataSources.all
45+
)
46+
47+
val post1 = createPost(1)
48+
49+
everySuspend { client.findOne(eq(operation.key)) }.returns(post1)
50+
51+
// When
52+
postFetcherServices.findAndEmitOne(operation) { flow.emit(it) }
53+
54+
// Then
55+
verifySuspend { postDAO.insertOne(post1.asPostEntity()) }
56+
57+
flow.test {
58+
val output = awaitItem()
59+
assertEquals(PostOutput.Single(post1), output)
60+
expectNoEvents()
61+
}
62+
}
63+
64+
@Test
65+
fun findAndEmitOneComposite_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
66+
runTest {
67+
// Given
68+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
69+
70+
val operation = Operation.Query.FindOneComposite(
71+
key = Post.Key(1),
72+
dataSources = DataSources.all
73+
)
74+
75+
val compositePost = createCompositePost(1)
76+
77+
everySuspend { client.findOneComposite(eq(operation.key)) }.returns(compositePost)
78+
79+
// When
80+
postFetcherServices.findAndEmitOneComposite(operation) { flow.emit(it) }
81+
82+
// Then
83+
verifySuspend { postDAO.insertOneComposite(compositePost) }
84+
85+
flow.test {
86+
val output = awaitItem()
87+
assertEquals(PostOutput.Single(compositePost), output)
88+
expectNoEvents()
89+
}
90+
}
91+
3292
@Test
3393
fun findAndEmitMany_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
3494
runTest {
@@ -64,6 +124,153 @@ class RealPostFetcherServicesTest {
64124
}
65125
}
66126

127+
@Test
128+
fun findAndEmitAll_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
129+
runTest {
130+
// Given
131+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
132+
133+
val operation = Operation.Query.FindAll(
134+
dataSources = DataSources.all
135+
)
136+
137+
val post1 = createPost(1)
138+
val post2 = createPost(2)
139+
140+
val posts = listOf(
141+
post1,
142+
post2
143+
)
144+
145+
everySuspend { client.findAll() }.returns(posts)
146+
147+
// When
148+
postFetcherServices.findAndEmitAll(operation) { flow.emit(it) }
149+
150+
// Then
151+
verifySuspend { postDAO.insertOne(post1.asPostEntity()) }
152+
verifySuspend { postDAO.insertOne(post2.asPostEntity()) }
153+
154+
flow.test {
155+
val output = awaitItem()
156+
assertEquals(PostOutput.Collection(posts), output)
157+
expectNoEvents()
158+
}
159+
}
160+
161+
@Test
162+
fun queryAndEmitOne_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
163+
runTest {
164+
// Given
165+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
166+
167+
val operation = QueryOne(
168+
query = Query.One<Post.Node>(
169+
dataSources = DataSources.all,
170+
predicate = null,
171+
order = null
172+
),
173+
dataSources = DataSources.all
174+
)
175+
176+
val post1 = createPost(1)
177+
178+
everySuspend { client.queryOne(ofType()) }.returns(post1)
179+
180+
// When
181+
postFetcherServices.queryAndEmitOne(operation) { flow.emit(it) }
182+
183+
// Then
184+
verifySuspend { postDAO.insertOne(post1.asPostEntity()) }
185+
186+
flow.test {
187+
val output = awaitItem()
188+
assertEquals(PostOutput.Single(post1), output)
189+
expectNoEvents()
190+
}
191+
}
192+
193+
@Test
194+
fun queryAndEmitMany_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
195+
runTest {
196+
// Given
197+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
198+
199+
val operation = QueryMany(
200+
query = Query.Many<Post.Node>(
201+
dataSources = DataSources.all,
202+
predicate = null,
203+
order = null,
204+
limit = null
205+
),
206+
dataSources = DataSources.all
207+
)
208+
209+
val post1 = createPost(1)
210+
val post2 = createPost(2)
211+
212+
val posts = listOf(
213+
post1,
214+
post2
215+
)
216+
217+
everySuspend { client.queryMany(ofType()) }.returns(posts)
218+
219+
// When
220+
postFetcherServices.queryAndEmitMany(operation) { flow.emit(it) }
221+
222+
// Then
223+
verifySuspend { postDAO.insertOne(post1.asPostEntity()) }
224+
verifySuspend { postDAO.insertOne(post2.asPostEntity()) }
225+
226+
flow.test {
227+
val output = awaitItem()
228+
assertEquals(PostOutput.Collection(posts), output)
229+
expectNoEvents()
230+
}
231+
}
232+
233+
234+
@Test
235+
fun queryAndEmitManyComposite_givenNormalClientAndDb_whenSuccessfulNetworkRequest_thenShouldUpdateDbAndEmitOutput() =
236+
runTest {
237+
// Given
238+
val flow = MutableSharedFlow<PostOutput>(replay = 10)
239+
240+
val operation = Operation.Query.QueryManyComposite(
241+
query = Query.Many<Post.Node>(
242+
dataSources = DataSources.all,
243+
predicate = null,
244+
order = null,
245+
limit = null
246+
),
247+
dataSources = DataSources.all
248+
)
249+
250+
val post1 = createCompositePost(1)
251+
val post2 = createCompositePost(2)
252+
253+
val posts = listOf(
254+
post1,
255+
post2
256+
)
257+
258+
everySuspend { client.queryManyComposite(ofType()) }.returns(PostOutput.Collection(posts))
259+
260+
// When
261+
postFetcherServices.queryAndEmitManyComposite(operation) { flow.emit(it) }
262+
263+
// Then
264+
verifySuspend { postDAO.insertOneComposite(post1) }
265+
verifySuspend { postDAO.insertOneComposite(post2) }
266+
267+
flow.test {
268+
val output = awaitItem()
269+
assertEquals(PostOutput.Collection(posts), output)
270+
expectNoEvents()
271+
}
272+
}
273+
67274
private fun createPost(id: Int) = Post.Node(
68275
key = Post.Key(id),
69276
properties = Post.Properties(
@@ -80,4 +287,26 @@ class RealPostFetcherServicesTest {
80287
locationName = null,
81288
)
82289
)
290+
291+
private fun createCompositePost(id: Int) = Post.Composite(
292+
node = createPost(id),
293+
edges = Post.Edges(
294+
creator = createCreator(id),
295+
hashtags = emptyList(),
296+
mentions = emptyList(),
297+
media = emptyList()
298+
)
299+
)
300+
301+
private fun createCreator(id: Int) = Creator.Node(
302+
key = Creator.Key(id),
303+
properties = Creator.Properties(
304+
username = "",
305+
fullName = "",
306+
profilePicURL = "",
307+
isVerified = false,
308+
bio = "",
309+
platform = Platform.Instagram
310+
)
311+
)
83312
}

0 commit comments

Comments
 (0)