Merge pull request #43 from lihenggui/compose_multiplatform

Convert :core:data and :core:domain to the multiplatform modules and fix test errors
pull/1323/head
Mercury Li 2 years ago committed by GitHub
commit 2990594dbf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -43,6 +43,7 @@ kotlin {
}
commonTest.dependencies {
implementation(libs.multiplatform.settings)
implementation(libs.multiplatform.settings.test)
implementation(libs.kotlinx.serialization.json)
implementation(projects.core.testing)

@ -18,6 +18,7 @@ package com.google.samples.apps.nowinandroid.core.data.repository
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.model.data.mapToUserNewsResources
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@ -30,6 +31,7 @@ import me.tatarka.inject.annotations.Inject
* Implements a [UserNewsResourceRepository] by combining a [NewsRepository] with a
* [UserDataRepository].
*/
@OptIn(ExperimentalCoroutinesApi::class)
@Inject
class CompositeUserNewsResourceRepository(
val newsRepository: NewsRepository,

@ -25,6 +25,7 @@ import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.database.model.asFtsEntity
import com.google.samples.apps.nowinandroid.core.di.IODispatcher
import com.google.samples.apps.nowinandroid.core.model.data.SearchResult
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@ -34,6 +35,7 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.withContext
import me.tatarka.inject.annotations.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@Inject
internal class DefaultSearchContentsRepository(
private val newsResourceDao: NewsResourceDao,

@ -21,8 +21,8 @@ import com.google.samples.apps.nowinandroid.core.data.changeListSync
import com.google.samples.apps.nowinandroid.core.data.model.asEntity
import com.google.samples.apps.nowinandroid.core.data.model.topicCrossReferences
import com.google.samples.apps.nowinandroid.core.data.model.topicEntityShells
import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceDao
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao
import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceDaoInterface
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDaoInterface
import com.google.samples.apps.nowinandroid.core.database.model.PopulatedNewsResource
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
@ -48,8 +48,8 @@ private const val SYNC_BATCH_SIZE = 40
@Inject
internal class OfflineFirstNewsRepository(
private val niaPreferencesDataSource: NiaPreferencesDataSource,
private val newsResourceDao: NewsResourceDao,
private val topicDao: TopicDao,
private val newsResourceDao: NewsResourceDaoInterface,
private val topicDao: TopicDaoInterface,
private val network: NiaNetworkDataSource,
private val notifier: Notifier,
) : NewsRepository {

@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.core.data.repository
import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.changeListSync
import com.google.samples.apps.nowinandroid.core.data.model.asEntity
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDaoInterface
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
@ -36,7 +36,7 @@ import me.tatarka.inject.annotations.Inject
*/
@Inject
internal class OfflineFirstTopicsRepository(
private val topicDao: TopicDao,
private val topicDao: TopicDaoInterface,
private val network: NiaNetworkDataSource,
) : TopicsRepository {

@ -32,18 +32,17 @@ import com.google.samples.apps.nowinandroid.core.database.model.PopulatedNewsRes
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferencesDataStore
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
import com.google.samples.apps.nowinandroid.core.testing.notifications.TestNotifier
import com.russhwolf.settings.MapSettings
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
@ -51,7 +50,10 @@ import kotlin.test.assertTrue
class OfflineFirstNewsRepositoryTest {
private val testScope = TestScope(UnconfinedTestDispatcher())
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(dispatcher)
private lateinit var subject: OfflineFirstNewsRepository
@ -67,13 +69,11 @@ class OfflineFirstNewsRepositoryTest {
private lateinit var synchronizer: Synchronizer
@get:Rule
val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
@BeforeTest
fun setup() {
niaPreferencesDataSource = NiaPreferencesDataSource(
tmpFolder.testUserPreferencesDataStore(testScope),
settings = MapSettings(),
dispatcher = dispatcher,
)
newsResourceDao = TestNewsResourceDao()
topicDao = TestTopicDao()
@ -176,7 +176,7 @@ class OfflineFirstNewsRepositoryTest {
// Delete half of the items on the network
val deletedItems = newsResourcesFromNetwork
.map(NewsResource::id)
.partition { it.chars().sum() % 2 == 0 }
.partition { it.length % 2 == 0 }
.first
.toSet()
@ -327,7 +327,7 @@ class OfflineFirstNewsRepositoryTest {
val followedTopicIds = networkNewsResources
.flatMap(NetworkNewsResource::topicEntityShells)
.mapNotNull { topic ->
when (topic.id.chars().sum() % 2) {
when (topic.id.length % 2) {
0 -> topic.id
else -> null
}

@ -21,13 +21,14 @@ import com.google.samples.apps.nowinandroid.core.data.model.asEntity
import com.google.samples.apps.nowinandroid.core.data.testdoubles.CollectionType
import com.google.samples.apps.nowinandroid.core.data.testdoubles.TestNiaNetworkDataSource
import com.google.samples.apps.nowinandroid.core.data.testdoubles.TestTopicDao
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDaoInterface
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferencesDataStore
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
import com.russhwolf.settings.MapSettings
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
@ -38,11 +39,14 @@ import kotlin.test.assertEquals
class OfflineFirstTopicsRepositoryTest {
private val testScope = TestScope(UnconfinedTestDispatcher())
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(dispatcher)
private lateinit var subject: OfflineFirstTopicsRepository
private lateinit var topicDao: TopicDao
private lateinit var topicDao: TopicDaoInterface
private lateinit var network: TestNiaNetworkDataSource
@ -55,7 +59,8 @@ class OfflineFirstTopicsRepositoryTest {
topicDao = TestTopicDao()
network = TestNiaNetworkDataSource()
niaPreferences = NiaPreferencesDataSource(
tmpFolder.testUserPreferencesDataStore(testScope),
settings = MapSettings(),
dispatcher = dispatcher,
)
synchronizer = TestSynchronizer(niaPreferences)
@ -140,7 +145,7 @@ class OfflineFirstTopicsRepositoryTest {
// Delete half of the items on the network
val deletedItems = networkTopics
.map(Topic::id)
.partition { it.chars().sum() % 2 == 0 }
.partition { it.length % 2 == 0 }
.first
.toSet()

@ -22,6 +22,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.core.model.data.UserData
import com.russhwolf.settings.MapSettings
import com.russhwolf.settings.Settings
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@ -39,7 +40,7 @@ class OfflineFirstUserDataRepositoryTest {
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = UnconfinedTestDispatcher()
private val settings = MapSettings()
private val settings: Settings = MapSettings()
private val testScope = TestScope(dispatcher)

@ -21,6 +21,7 @@ import com.google.samples.apps.nowinandroid.core.network.fake.FakeNiaNetworkData
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.serialization.json.Json
@ -33,6 +34,7 @@ enum class CollectionType {
/**
* Test double for [NiaNetworkDataSource]
*/
@OptIn(ExperimentalCoroutinesApi::class)
class TestNiaNetworkDataSource : NiaNetworkDataSource {
private val source = FakeNiaNetworkDataSource(

@ -0,0 +1,50 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
alias(libs.plugins.nowinandroid.kmp.library)
alias(libs.plugins.protobuf)
id("kotlinx-serialization")
}
android {
namespace = "com.google.samples.apps.nowinandroid.core.datastore.proto"
}
// Setup protobuf configuration, generating lite Java and Kotlin classes
protobuf {
protoc {
artifact = libs.protobuf.protoc.get().toString()
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
register("kotlin") {
option("lite")
}
}
}
}
}
kotlin {
sourceSets {
commonMain.dependencies {
api(libs.protobuf.kotlin.lite)
implementation(libs.kotlinx.serialization.core)
}
}
}

@ -0,0 +1,24 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.core.datastore
enum class DarkThemeConfigProto {
DARK_THEME_CONFIG_UNSPECIFIED,
DARK_THEME_CONFIG_FOLLOW_SYSTEM,
DARK_THEME_CONFIG_LIGHT,
DARK_THEME_CONFIG_DARK,
}

@ -0,0 +1,23 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.core.datastore
enum class ThemeBrandProto {
THEME_BRAND_UNSPECIFIED,
THEME_BRAND_DEFAULT,
THEME_BRAND_ANDROID,
}

@ -0,0 +1,57 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.core.datastore
import com.google.samples.apps.nowinandroid.core.datastore.DarkThemeConfigProto.DARK_THEME_CONFIG_FOLLOW_SYSTEM
import com.google.samples.apps.nowinandroid.core.datastore.ThemeBrandProto.THEME_BRAND_UNSPECIFIED
import kotlinx.serialization.Serializable
// A lot of workaround brought by Proto
@Serializable
data class UserPreferences(
val topicChangeListVersion: Int,
val authorChangeListVersion: Int,
val newsResourceChangeListVersion: Int,
val hasDoneIntToStringIdMigration: Boolean,
val hasDoneListToMapMigration: Boolean,
val followedTopicIds: Set<String>,
val followedAuthorIds: Set<String>,
val bookmarkedNewsResourceIds: Set<String>,
val viewedNewsResourceIds: Set<String>,
val themeBrand: ThemeBrandProto,
val darkThemeConfig: DarkThemeConfigProto,
val shouldHideOnboarding: Boolean,
val useDynamicColor: Boolean,
) {
companion object {
val DEFAULT = UserPreferences(
topicChangeListVersion = 0,
authorChangeListVersion = 0,
newsResourceChangeListVersion = 0,
hasDoneIntToStringIdMigration = false,
hasDoneListToMapMigration = false,
themeBrand = THEME_BRAND_UNSPECIFIED,
darkThemeConfig = DARK_THEME_CONFIG_FOLLOW_SYSTEM,
shouldHideOnboarding = false,
useDynamicColor = false,
followedTopicIds = emptySet(),
followedAuthorIds = emptySet(),
bookmarkedNewsResourceIds = emptySet(),
viewedNewsResourceIds = emptySet(),
)
}
}

@ -0,0 +1,27 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
option java_package = "com.google.samples.apps.nowinandroid.core.datastore";
option java_multiple_files = true;
enum DarkThemeConfigProto {
DARK_THEME_CONFIG_UNSPECIFIED = 0;
DARK_THEME_CONFIG_FOLLOW_SYSTEM = 1;
DARK_THEME_CONFIG_LIGHT = 2;
DARK_THEME_CONFIG_DARK = 3;
}

@ -0,0 +1,26 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
option java_package = "com.google.samples.apps.nowinandroid.core.datastore";
option java_multiple_files = true;
enum ThemeBrandProto {
THEME_BRAND_UNSPECIFIED = 0;
THEME_BRAND_DEFAULT = 1;
THEME_BRAND_ANDROID = 2;
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
import "com/google/samples/apps/nowinandroid/data/dark_theme_config.proto";
import "com/google/samples/apps/nowinandroid/data/theme_brand.proto";
option java_package = "com.google.samples.apps.nowinandroid.core.datastore";
option java_multiple_files = true;
message UserPreferences {
reserved 2;
repeated int32 deprecated_int_followed_topic_ids = 1;
int32 topicChangeListVersion = 3;
int32 authorChangeListVersion = 4;
int32 newsResourceChangeListVersion = 6;
repeated int32 deprecated_int_followed_author_ids = 7;
bool has_done_int_to_string_id_migration = 8;
repeated string deprecated_followed_topic_ids = 9;
repeated string deprecated_followed_author_ids = 10;
repeated string deprecated_bookmarked_news_resource_ids = 11;
bool has_done_list_to_map_migration = 12;
// Each map is used to store a set of string IDs. The bool has no meaning, but proto3 doesn't
// have a Set type so this is the closest we can get to a Set.
map<string, bool> followed_topic_ids = 13;
map<string, bool> followed_author_ids = 14;
map<string, bool> bookmarked_news_resource_ids = 15;
map<string, bool> viewed_news_resource_ids = 20;
ThemeBrandProto theme_brand = 16;
DarkThemeConfigProto dark_theme_config = 17;
bool should_hide_onboarding = 18;
bool use_dynamic_color = 19;
// NEXT AVAILABLE ID: 21
}

@ -42,6 +42,7 @@ kotlin {
implementation(libs.kotlinx.serialization.core)
implementation(projects.core.model)
implementation(projects.core.common)
implementation(projects.core.datastoreProto)
}
commonTest.dependencies {
implementation(libs.multiplatform.settings.test)

@ -25,6 +25,11 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
namespace = "com.google.samples.apps.nowinandroid.core.designsystem"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
kotlin {

@ -14,7 +14,8 @@
* limitations under the License.
*/
plugins {
alias(libs.plugins.nowinandroid.android.library)
alias(libs.plugins.nowinandroid.kmp.library)
alias(libs.plugins.nowinandroid.kotlin.inject)
alias(libs.plugins.nowinandroid.android.library.jacoco)
id("com.google.devtools.ksp")
}
@ -23,11 +24,14 @@ android {
namespace = "com.google.samples.apps.nowinandroid.core.domain"
}
dependencies {
api(projects.core.data)
api(projects.core.model)
implementation(libs.javax.inject)
testImplementation(projects.core.testing)
}
kotlin {
sourceSets {
commonMain.dependencies {
api(projects.core.data)
api(projects.core.model)
}
commonTest.dependencies {
implementation(projects.core.testing)
}
}
}

@ -23,12 +23,11 @@ import com.google.samples.apps.nowinandroid.core.domain.TopicSortField.NONE
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import javax.inject.Inject
/**
* A use case which obtains a list of topics with their followed state.
*/
class GetFollowableTopicsUseCase @Inject constructor(
class GetFollowableTopicsUseCase(
private val topicsRepository: TopicsRepository,
private val userDataRepository: UserDataRepository,
) {

@ -19,12 +19,13 @@ package com.google.samples.apps.nowinandroid.core.domain
import com.google.samples.apps.nowinandroid.core.data.model.RecentSearchQuery
import com.google.samples.apps.nowinandroid.core.data.repository.RecentSearchRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import me.tatarka.inject.annotations.Inject
/**
* A use case which returns the recent search queries.
*/
class GetRecentSearchQueriesUseCase @Inject constructor(
@Inject
class GetRecentSearchQueriesUseCase(
private val recentSearchRepository: RecentSearchRepository,
) {
operator fun invoke(limit: Int = 10): Flow<List<RecentSearchQuery>> =

@ -18,12 +18,13 @@ package com.google.samples.apps.nowinandroid.core.domain
import com.google.samples.apps.nowinandroid.core.data.repository.SearchContentsRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import me.tatarka.inject.annotations.Inject
/**
* A use case which returns total count of *Fts tables
*/
class GetSearchContentsCountUseCase @Inject constructor(
@Inject
class GetSearchContentsCountUseCase(
private val searchContentsRepository: SearchContentsRepository,
) {
operator fun invoke(): Flow<Int> =

@ -25,12 +25,13 @@ import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.model.data.UserSearchResult
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import javax.inject.Inject
import me.tatarka.inject.annotations.Inject
/**
* A use case which returns the searched contents matched with the search query.
*/
class GetSearchContentsUseCase @Inject constructor(
@Inject
class GetSearchContentsUseCase(
private val searchContentsRepository: SearchContentsRepository,
private val userDataRepository: UserDataRepository,
) {

@ -21,18 +21,13 @@ import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import kotlin.test.Test
import kotlin.test.assertEquals
class GetFollowableTopicsUseCaseTest {
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
private val topicsRepository = TestTopicsRepository()
private val userDataRepository = TestUserDataRepository()

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest />

@ -28,6 +28,7 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.onRoot
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.github.takahirom.roborazzi.ExperimentalRoborazziApi
import com.github.takahirom.roborazzi.RoborazziOptions
import com.github.takahirom.roborazzi.RoborazziOptions.CompareOptions
import com.github.takahirom.roborazzi.RoborazziOptions.RecordOptions
@ -36,6 +37,7 @@ import com.google.accompanist.testharness.TestHarness
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import org.robolectric.RuntimeEnvironment
@OptIn(ExperimentalRoborazziApi::class)
val DefaultRoborazziOptions =
RoborazziOptions(
// Pixel-perfect matching

@ -16,8 +16,6 @@
plugins {
alias(libs.plugins.nowinandroid.kmp.library)
alias(libs.plugins.nowinandroid.kotlin.inject)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.hilt)
}
android {
@ -28,7 +26,6 @@ kotlin {
sourceSets {
commonMain.dependencies {
api(kotlin("test"))
// api(libs.androidx.compose.ui.test)
api(projects.core.analytics)
api(projects.core.data)
api(projects.core.model)

@ -45,6 +45,7 @@ include(":core:data")
include(":core:data-test")
include(":core:database")
include(":core:datastore")
include(":core:datastore-proto")
include(":core:designsystem")
include(":core:domain")
include(":core:model")

Loading…
Cancel
Save