Skip to content

Commit 3ca68d4

Browse files
authored
Merge pull request #417 from SimonMarquis/patch/assets-as-json-files
Migrate hard-coded JSON data into JSON assets files
2 parents bbc5460 + ee8eac3 commit 3ca68d4

File tree

18 files changed

+5735
-169
lines changed

18 files changed

+5735
-169
lines changed

core/data/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ plugins {
2222

2323
android {
2424
namespace = "com.google.samples.apps.nowinandroid.core.data"
25+
testOptions {
26+
unitTests {
27+
isIncludeAndroidResources = true
28+
}
29+
}
2530
}
2631

2732
dependencies {

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeAuthorsRepository.kt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsReposito
2121
import com.google.samples.apps.nowinandroid.core.model.data.Author
2222
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
2323
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
24+
import com.google.samples.apps.nowinandroid.core.network.fake.FakeAssetManager
2425
import com.google.samples.apps.nowinandroid.core.network.fake.FakeDataSource
2526
import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
27+
import java.io.InputStream
2628
import javax.inject.Inject
2729
import kotlinx.coroutines.CoroutineDispatcher
2830
import kotlinx.coroutines.flow.Flow
2931
import kotlinx.coroutines.flow.flow
3032
import kotlinx.coroutines.flow.flowOn
3133
import kotlinx.coroutines.flow.map
32-
import kotlinx.serialization.decodeFromString
3334
import kotlinx.serialization.json.Json
35+
import kotlinx.serialization.json.decodeFromStream
3436

3537
/**
3638
* Fake implementation of the [AuthorsRepository] that returns hardcoded authors.
@@ -41,20 +43,23 @@ import kotlinx.serialization.json.Json
4143
class FakeAuthorsRepository @Inject constructor(
4244
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
4345
private val networkJson: Json,
46+
private val assets: FakeAssetManager,
4447
) : AuthorsRepository {
4548

4649
override fun getAuthorsStream(): Flow<List<Author>> = flow {
4750
emit(
48-
networkJson.decodeFromString<List<NetworkAuthor>>(FakeDataSource.authors).map {
49-
Author(
50-
id = it.id,
51-
name = it.name,
52-
imageUrl = it.imageUrl,
53-
twitter = it.twitter,
54-
mediumPage = it.mediumPage,
55-
bio = it.bio,
56-
)
57-
}
51+
assets.open(FakeDataSource.AUTHORS)
52+
.use<InputStream, List<NetworkAuthor>>(networkJson::decodeFromStream)
53+
.map {
54+
Author(
55+
id = it.id,
56+
name = it.name,
57+
imageUrl = it.imageUrl,
58+
twitter = it.twitter,
59+
mediumPage = it.mediumPage,
60+
bio = it.bio,
61+
)
62+
}
5863
)
5964
}
6065
.flowOn(ioDispatcher)

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeNewsRepository.kt

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
2424
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
2525
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
2626
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
27+
import com.google.samples.apps.nowinandroid.core.network.fake.FakeAssetManager
2728
import com.google.samples.apps.nowinandroid.core.network.fake.FakeDataSource
2829
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
30+
import java.io.InputStream
2931
import javax.inject.Inject
3032
import kotlinx.coroutines.CoroutineDispatcher
3133
import kotlinx.coroutines.flow.Flow
3234
import kotlinx.coroutines.flow.flow
3335
import kotlinx.coroutines.flow.flowOn
34-
import kotlinx.serialization.decodeFromString
3536
import kotlinx.serialization.json.Json
37+
import kotlinx.serialization.json.decodeFromStream
3638

3739
/**
3840
* Fake implementation of the [NewsRepository] that retrieves the news resources from a JSON String.
@@ -42,13 +44,15 @@ import kotlinx.serialization.json.Json
4244
*/
4345
class FakeNewsRepository @Inject constructor(
4446
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
45-
private val networkJson: Json
47+
private val networkJson: Json,
48+
private val assets: FakeAssetManager,
4649
) : NewsRepository {
4750

4851
override fun getNewsResourcesStream(): Flow<List<NewsResource>> =
4952
flow {
5053
emit(
51-
networkJson.decodeFromString<List<NetworkNewsResource>>(FakeDataSource.data)
54+
assets.open(FakeDataSource.DATA)
55+
.use<InputStream, List<NetworkNewsResource>>(networkJson::decodeFromStream)
5256
.map(NetworkNewsResource::asEntity)
5357
.map(NewsResourceEntity::asExternalModel)
5458
)
@@ -61,13 +65,15 @@ class FakeNewsRepository @Inject constructor(
6165
): Flow<List<NewsResource>> =
6266
flow {
6367
emit(
64-
networkJson.decodeFromString<List<NetworkNewsResource>>(FakeDataSource.data)
65-
.filter {
66-
it.authors.intersect(filterAuthorIds).isNotEmpty() ||
67-
it.topics.intersect(filterTopicIds).isNotEmpty()
68-
}
69-
.map(NetworkNewsResource::asEntity)
70-
.map(NewsResourceEntity::asExternalModel)
68+
assets.open(FakeDataSource.DATA).use { stream ->
69+
networkJson.decodeFromStream<List<NetworkNewsResource>>(stream)
70+
.filter {
71+
it.authors.intersect(filterAuthorIds).isNotEmpty() ||
72+
it.topics.intersect(filterTopicIds).isNotEmpty()
73+
}
74+
.map(NetworkNewsResource::asEntity)
75+
.map(NewsResourceEntity::asExternalModel)
76+
}
7177
)
7278
}
7379
.flowOn(ioDispatcher)

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepositor
2121
import com.google.samples.apps.nowinandroid.core.model.data.Topic
2222
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
2323
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
24+
import com.google.samples.apps.nowinandroid.core.network.fake.FakeAssetManager
2425
import com.google.samples.apps.nowinandroid.core.network.fake.FakeDataSource
2526
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
27+
import java.io.InputStream
2628
import javax.inject.Inject
2729
import kotlinx.coroutines.CoroutineDispatcher
2830
import kotlinx.coroutines.flow.Flow
2931
import kotlinx.coroutines.flow.flow
3032
import kotlinx.coroutines.flow.flowOn
3133
import kotlinx.coroutines.flow.map
32-
import kotlinx.serialization.decodeFromString
3334
import kotlinx.serialization.json.Json
35+
import kotlinx.serialization.json.decodeFromStream
3436

3537
/**
3638
* Fake implementation of the [TopicsRepository] that retrieves the topics from a JSON String, and
@@ -42,19 +44,22 @@ import kotlinx.serialization.json.Json
4244
class FakeTopicsRepository @Inject constructor(
4345
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
4446
private val networkJson: Json,
47+
private val assets: FakeAssetManager,
4548
) : TopicsRepository {
46-
override fun getTopicsStream(): Flow<List<Topic>> = flow<List<Topic>> {
49+
override fun getTopicsStream(): Flow<List<Topic>> = flow {
4750
emit(
48-
networkJson.decodeFromString<List<NetworkTopic>>(FakeDataSource.topicsData).map {
49-
Topic(
50-
id = it.id,
51-
name = it.name,
52-
shortDescription = it.shortDescription,
53-
longDescription = it.longDescription,
54-
url = it.url,
55-
imageUrl = it.imageUrl
56-
)
57-
}
51+
assets.open(FakeDataSource.TOPICS)
52+
.use<InputStream, List<NetworkTopic>>(networkJson::decodeFromStream)
53+
.map {
54+
Topic(
55+
id = it.id,
56+
name = it.name,
57+
shortDescription = it.shortDescription,
58+
longDescription = it.longDescription,
59+
url = it.url,
60+
imageUrl = it.imageUrl
61+
)
62+
}
5863
)
5964
}
6065
.flowOn(ioDispatcher)

core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNiaNetworkDataSource.kt

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
package com.google.samples.apps.nowinandroid.core.data.testdoubles
1818

1919
import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
20-
import com.google.samples.apps.nowinandroid.core.network.fake.FakeDataSource
20+
import com.google.samples.apps.nowinandroid.core.network.fake.FakeNiaNetworkDataSource
2121
import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
2222
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
2323
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
2424
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
25-
import kotlinx.serialization.decodeFromString
25+
import kotlinx.coroutines.runBlocking
26+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
2627
import kotlinx.serialization.json.Json
2728

2829
enum class CollectionType {
@@ -36,16 +37,13 @@ enum class CollectionType {
3637
*/
3738
class TestNiaNetworkDataSource : NiaNetworkDataSource {
3839

39-
private val networkJson = Json
40+
private val source = FakeNiaNetworkDataSource(UnconfinedTestDispatcher(), Json)
4041

41-
private val allTopics =
42-
networkJson.decodeFromString<List<NetworkTopic>>(FakeDataSource.topicsData)
42+
private val allTopics = runBlocking { source.getTopics() }
4343

44-
private val allAuthors =
45-
networkJson.decodeFromString<List<NetworkAuthor>>(FakeDataSource.authors)
44+
private val allAuthors = runBlocking { source.getAuthors() }
4645

47-
private val allNewsResources =
48-
networkJson.decodeFromString<List<NetworkNewsResource>>(FakeDataSource.data)
46+
private val allNewsResources = runBlocking { source.getNewsResources() }
4947

5048
private val changeLists: MutableMap<CollectionType, List<NetworkChangeList>> = mutableMapOf(
5149
CollectionType.Topics to allTopics

core/network/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ android {
2727
buildConfig = true
2828
}
2929
namespace = "com.google.samples.apps.nowinandroid.core.network"
30+
testOptions {
31+
unitTests {
32+
isIncludeAndroidResources = true
33+
}
34+
}
3035
}
3136

3237
secrets {

core/network/lint.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2022 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<lint>
18+
<!--
19+
Lint crashes when it tries to analyse a file without a package name:
20+
java.lang.IllegalStateException: () -> kotlin.String at org.jetbrains.kotlin.asJava.classes.KtLightClassForFacadeImpl$Companion.createForFacadeNoCache
21+
-->
22+
<issue id="LintError">
23+
<ignore path="**/JvmUnitTestFakeAssetManager.kt" />
24+
</issue>
25+
</lint>

core/network/src/demo/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt renamed to core/network/src/demo/java/com/google/samples/apps/nowinandroid/core/network/di/FlavoredNetworkModule.kt

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,13 @@ import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
2020
import com.google.samples.apps.nowinandroid.core.network.fake.FakeNiaNetworkDataSource
2121
import dagger.Binds
2222
import dagger.Module
23-
import dagger.Provides
2423
import dagger.hilt.InstallIn
2524
import dagger.hilt.components.SingletonComponent
26-
import javax.inject.Singleton
27-
import kotlinx.serialization.json.Json
2825

2926
@Module
3027
@InstallIn(SingletonComponent::class)
31-
interface NetworkModule {
28+
interface FlavoredNetworkModule {
3229

3330
@Binds
34-
fun bindsNiaNetwork(
35-
niANetwork: FakeNiaNetworkDataSource
36-
): NiaNetworkDataSource
37-
38-
companion object {
39-
@Provides
40-
@Singleton
41-
fun providesNetworkJson(): Json = Json {
42-
ignoreUnknownKeys = true
43-
}
44-
}
31+
fun FakeNiaNetworkDataSource.binds(): NiaNetworkDataSource
4532
}

0 commit comments

Comments
 (0)