Merge remote-tracking branch 'fork/main' into patch/assets-as-json-files

pull/417/head
Simon Marquis 3 years ago
commit b5d342468e

@ -34,16 +34,16 @@ jobs:
uses: gradle/gradle-build-action@v2
- name: Check spotless
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache
- name: Check lint
run: ./gradlew lintDemoDebug --stacktrace
run: ./gradlew lintDemoDebug
- name: Build all build type and flavor permutations
run: ./gradlew assemble --stacktrace
run: ./gradlew assemble
- name: Run local tests
run: ./gradlew testDemoDebug testProdDebug --stacktrace
run: ./gradlew testDemoDebug testProdDebug
- name: Upload build outputs (APKs)
uses: actions/upload-artifact@v3
@ -90,7 +90,7 @@ jobs:
disable-animations: true
disk-size: 6000M
heap-size: 600M
script: ./gradlew connectedProdDebugAndroidTest -x :benchmark:connectedProdBenchmarkAndroidTest --stacktrace
script: ./gradlew connectedProdDebugAndroidTest -x :benchmark:connectedProdBenchmarkAndroidTest
- name: Upload test reports
if: always()

@ -18,15 +18,31 @@
# End users may safely ignore this file. It has no relevance to other systems.
---
status: PUBLISHED
technologies: [Android]
technologies: [Android, JetpackCompose, Coroutines]
categories:
- AndroidTesting
- AndroidArchitecture
- AndroidArchitectureUILayer
- AndroidArchitectureDomainLayer
- AndroidArchitectureDataLayer
- AndroidArchitectureStateProduction
- AndroidArchitectureStateHolder
- JetpackComposeTesting
- JetpackComposeA11y
- JetpackComposeArchitectureAndState
- JetpackComposeDesignSystems
- JetpackComposeNavigation
- JetpackComposeAnimation
solutions:
- Mobile
- Flow
- JetpackHilt
- JetpackDataStore
- JetpackRoom
- JetpackNavigation
- JetpackWorkManager
- JetpackLifecycle
languages: [Kotlin]
solutions: [Mobile]
github: android/nowinandroid
level: ADVANCED
license: apache2

@ -0,0 +1,44 @@
<?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.
-->
<component name="ProjectRunConfigurationManager">
<!--
Baseline Profiles improve code execution speed by around 30% from the first launch by avoiding interpretation and just-in-time (JIT) compilation steps for included code paths.
More information at http://d.android.com/baseline-profiles.
-->
<configuration default="false" name="Generate Demo Baseline Profile" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<!-- TODO Once we use Gradle wrapper 7.6, we can use rerun instead of rerun-tasks that will skip cache only for one task -->
<option name="scriptParameters" value="--rerun-tasks -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":benchmark:pixel6Api31DemoBenchmarkAndroidTest" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

@ -91,13 +91,13 @@ dependencies {
implementation(project(":core:model"))
implementation(project(":sync:work"))
implementation(project(":sync:sync-test"))
androidTestImplementation(project(":core:testing"))
androidTestImplementation(project(":core:datastore-test"))
androidTestImplementation(project(":core:data-test"))
androidTestImplementation(project(":core:network"))
androidTestImplementation(libs.androidx.navigation.testing)
androidTestImplementation(kotlin("test"))
debugImplementation(libs.androidx.compose.ui.testManifest)
implementation(libs.accompanist.systemuicontroller)

@ -31,13 +31,13 @@ import androidx.navigation.compose.composable
import androidx.navigation.createGraph
import androidx.navigation.testing.TestNavHostController
import com.google.samples.apps.nowinandroid.core.testing.util.TestNetworkMonitor
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test

@ -32,8 +32,7 @@
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name">
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

@ -15,12 +15,6 @@
limitations under the License.
-->
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<!-- Status bar -->
<color name="black30">#4D000000</color>
</resources>

@ -21,7 +21,7 @@ plugins {
}
android {
namespace = "com.google.samples.apps.nowinandroid.benchmark"
namespace = "com.google.samples.apps.nowinandroid.benchmarks"
defaultConfig {
minSdk = 23
@ -55,9 +55,9 @@ android {
testOptions {
managedDevices {
devices {
create<ManagedVirtualDevice>("pixel5Api30") {
device = "Pixel 5"
apiLevel = 30
create<ManagedVirtualDevice>("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}

@ -16,10 +16,16 @@
package com.google.samples.apps.nowinandroid
import com.google.samples.apps.nowinandroid.benchmark.BuildConfig
import com.google.samples.apps.nowinandroid.benchmarks.BuildConfig
/**
* Convenience parameter to use proper package name with regards to build type and build flavor.
*/
const val PACKAGE_NAME =
"com.google.samples.apps.nowinandroid.${BuildConfig.FLAVOR}.${BuildConfig.BUILD_TYPE}"
val PACKAGE_NAME = StringBuilder("com.google.samples.apps.nowinandroid").apply {
if (BuildConfig.FLAVOR != "prod") {
append(".${BuildConfig.FLAVOR}")
}
if (BuildConfig.BUILD_TYPE != "release") {
append(".${BuildConfig.BUILD_TYPE}")
}
}.toString()

@ -21,6 +21,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.kotlin
class AndroidFeatureConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
@ -46,7 +47,9 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
add("implementation", project(":core:common"))
add("implementation", project(":core:domain"))
add("testImplementation", kotlin("test"))
add("testImplementation", project(":core:testing"))
add("androidTestImplementation", kotlin("test"))
add("androidTestImplementation", project(":core:testing"))
add("implementation", libs.findLibrary("coil.kt").get())

@ -26,6 +26,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.kotlin
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
@ -51,6 +52,10 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
force("org.objenesis:objenesis:2.6")
}
}
dependencies {
add("androidTestImplementation", kotlin("test"))
add("testImplementation", kotlin("test"))
}
}
}
}

@ -17,9 +17,9 @@
package com.google.samples.apps.nowinandroid.core.result
import app.cash.turbine.test
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test
class ResultKtTest {

@ -21,8 +21,8 @@ import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResourceExpanded
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
import kotlin.test.assertEquals
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Test
class NetworkEntityKtTest {

@ -29,9 +29,9 @@ import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferen
import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -68,7 +68,7 @@ class OfflineFirstAuthorsRepositoryTest {
@Test
fun offlineFirstAuthorsRepository_Authors_stream_is_backed_by_Authors_dao() =
runTest {
Assert.assertEquals(
assertEquals(
authorDao.getAuthorEntitiesStream()
.first()
.map(AuthorEntity::asExternalModel),
@ -88,13 +88,13 @@ class OfflineFirstAuthorsRepositoryTest {
val dbAuthors = authorDao.getAuthorEntitiesStream()
.first()
Assert.assertEquals(
assertEquals(
networkAuthors.map(AuthorEntity::id),
dbAuthors.map(AuthorEntity::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
network.latestChangeListVersion(CollectionType.Authors),
synchronizer.getChangeListVersions().authorVersion
)
@ -125,13 +125,13 @@ class OfflineFirstAuthorsRepositoryTest {
val db = authorDao.getAuthorEntitiesStream()
.first()
Assert.assertEquals(
assertEquals(
network.map(AuthorEntity::id),
db.map(AuthorEntity::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
changeList.last().changeListVersion,
synchronizer.getChangeListVersions().authorVersion
)
@ -166,13 +166,13 @@ class OfflineFirstAuthorsRepositoryTest {
.map(AuthorEntity::asExternalModel)
// Assert that items marked deleted on the network have been deleted locally
Assert.assertEquals(
assertEquals(
networkAuthors.map(Author::id) - deletedItems,
dbAuthors.map(Author::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
network.latestChangeListVersion(CollectionType.Authors),
synchronizer.getChangeListVersions().authorVersion
)

@ -39,9 +39,9 @@ import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferen
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -112,7 +112,7 @@ class OfflineFirstNewsRepositoryTest {
)
assertEquals(
emptyList<NewsResource>(),
emptyList(),
subject.getNewsResourcesStream(
filterTopicIds = nonPresentInterestsIds,
)
@ -136,7 +136,7 @@ class OfflineFirstNewsRepositoryTest {
)
assertEquals(
emptyList<NewsResource>(),
emptyList(),
subject.getNewsResourcesStream(
filterAuthorIds = nonPresentInterestsIds
)

@ -28,9 +28,9 @@ import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSou
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 kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -69,7 +69,7 @@ class OfflineFirstTopicsRepositoryTest {
@Test
fun offlineFirstTopicsRepository_topics_stream_is_backed_by_topics_dao() =
runTest {
Assert.assertEquals(
assertEquals(
topicDao.getTopicEntitiesStream()
.first()
.map(TopicEntity::asExternalModel),
@ -89,13 +89,13 @@ class OfflineFirstTopicsRepositoryTest {
val dbTopics = topicDao.getTopicEntitiesStream()
.first()
Assert.assertEquals(
assertEquals(
networkTopics.map(TopicEntity::id),
dbTopics.map(TopicEntity::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
network.latestChangeListVersion(CollectionType.Topics),
synchronizer.getChangeListVersions().topicVersion
)
@ -119,13 +119,13 @@ class OfflineFirstTopicsRepositoryTest {
val dbTopics = topicDao.getTopicEntitiesStream()
.first()
Assert.assertEquals(
assertEquals(
networkTopics.map(TopicEntity::id),
dbTopics.map(TopicEntity::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
network.latestChangeListVersion(CollectionType.Topics),
synchronizer.getChangeListVersions().topicVersion
)
@ -160,13 +160,13 @@ class OfflineFirstTopicsRepositoryTest {
.map(TopicEntity::asExternalModel)
// Assert that items marked deleted on the network have been deleted locally
Assert.assertEquals(
assertEquals(
networkTopics.map(Topic::id) - deletedItems,
dbTopics.map(Topic::id)
)
// After sync version should be updated
Assert.assertEquals(
assertEquals(
network.latestChangeListVersion(CollectionType.Topics),
synchronizer.getChangeListVersions().topicVersion
)

@ -21,10 +21,12 @@ import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferen
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 kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -194,9 +196,9 @@ class OfflineFirstUserDataRepositoryTest {
runTest {
subject.setFollowedTopicIds(setOf("1"))
subject.setShouldHideOnboarding(true)
assertEquals(true, subject.userDataStream.first().shouldHideOnboarding)
assertTrue(subject.userDataStream.first().shouldHideOnboarding)
subject.setFollowedTopicIds(emptySet())
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
}

@ -20,8 +20,8 @@ import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import kotlin.test.assertEquals
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Test
class PopulatedNewsResourceKtTest {

@ -17,7 +17,7 @@
package com.google.samples.apps.nowinandroid.core.database.util
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType
import org.junit.Assert.assertEquals
import kotlin.test.assertEquals
import org.junit.Test
class NewsResourceTypeConverterTest {

@ -27,10 +27,10 @@ import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceTopi
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.model.data.NewsResourceType
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

@ -16,9 +16,9 @@
package com.google.samples.apps.nowinandroid.core.datastore
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
/**

@ -16,8 +16,9 @@
package com.google.samples.apps.nowinandroid.core.datastore
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Test
class ListToMapMigrationTest {
@ -29,7 +30,7 @@ class ListToMapMigrationTest {
deprecatedFollowedTopicIds.addAll(listOf("1", "2", "3"))
}
// Assert that there are no topic ids in the map yet
Assert.assertEquals(
assertEquals(
emptyMap<String, Boolean>(),
preMigrationUserPreferences.followedTopicIdsMap
)
@ -39,13 +40,13 @@ class ListToMapMigrationTest {
ListToMapMigration.migrate(preMigrationUserPreferences)
// Assert the deprecated topic ids have been migrated to the topic ids map
Assert.assertEquals(
assertEquals(
mapOf("1" to true, "2" to true, "3" to true),
postMigrationUserPreferences.followedTopicIdsMap
)
// Assert that the migration has been marked complete
Assert.assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
}
@Test
@ -55,7 +56,7 @@ class ListToMapMigrationTest {
deprecatedFollowedAuthorIds.addAll(listOf("4", "5", "6"))
}
// Assert that there are no author ids in the map yet
Assert.assertEquals(
assertEquals(
emptyMap<String, Boolean>(),
preMigrationUserPreferences.followedAuthorIdsMap
)
@ -65,13 +66,13 @@ class ListToMapMigrationTest {
ListToMapMigration.migrate(preMigrationUserPreferences)
// Assert the deprecated author ids have been migrated to the author ids map
Assert.assertEquals(
assertEquals(
mapOf("4" to true, "5" to true, "6" to true),
postMigrationUserPreferences.followedAuthorIdsMap
)
// Assert that the migration has been marked complete
Assert.assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
}
@Test
@ -81,7 +82,7 @@ class ListToMapMigrationTest {
deprecatedBookmarkedNewsResourceIds.addAll(listOf("7", "8", "9"))
}
// Assert that there are no bookmarks in the map yet
Assert.assertEquals(
assertEquals(
emptyMap<String, Boolean>(),
preMigrationUserPreferences.bookmarkedNewsResourceIdsMap
)
@ -91,12 +92,12 @@ class ListToMapMigrationTest {
ListToMapMigration.migrate(preMigrationUserPreferences)
// Assert the deprecated bookmarks have been migrated to the bookmarks map
Assert.assertEquals(
assertEquals(
mapOf("7" to true, "8" to true, "9" to true),
postMigrationUserPreferences.bookmarkedNewsResourceIdsMap
)
// Assert that the migration has been marked complete
Assert.assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
assertTrue(postMigrationUserPreferences.hasDoneListToMapMigration)
}
}

@ -17,9 +17,10 @@
package com.google.samples.apps.nowinandroid.core.datastore
import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferencesDataStore
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -40,13 +41,13 @@ class NiaPreferencesDataSourceTest {
@Test
fun shouldHideOnboardingIsFalseByDefault() = runTest {
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
fun userShouldHideOnboardingIsTrueWhenSet() = runTest {
subject.setShouldHideOnboarding(true)
assertEquals(true, subject.userDataStream.first().shouldHideOnboarding)
assertTrue(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -60,7 +61,7 @@ class NiaPreferencesDataSourceTest {
subject.toggleFollowedAuthorId("1", false)
// Then: onboarding should be shown again
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -74,7 +75,7 @@ class NiaPreferencesDataSourceTest {
subject.toggleFollowedTopicId("1", false)
// Then: onboarding should be shown again
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -88,7 +89,7 @@ class NiaPreferencesDataSourceTest {
subject.setFollowedAuthorIds(emptySet())
// Then: onboarding should be shown again
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -102,7 +103,7 @@ class NiaPreferencesDataSourceTest {
subject.setFollowedTopicIds(emptySet())
// Then: onboarding should be shown again
assertEquals(false, subject.userDataStream.first().shouldHideOnboarding)
assertFalse(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -117,7 +118,7 @@ class NiaPreferencesDataSourceTest {
subject.setFollowedTopicIds(emptySet())
// Then: onboarding should still be dismissed
assertEquals(true, subject.userDataStream.first().shouldHideOnboarding)
assertTrue(subject.userDataStream.first().shouldHideOnboarding)
}
@Test
@ -132,6 +133,6 @@ class NiaPreferencesDataSourceTest {
subject.setFollowedAuthorIds(emptySet())
// Then: onboarding should still be dismissed
assertEquals(true, subject.userDataStream.first().shouldHideOnboarding)
assertTrue(subject.userDataStream.first().shouldHideOnboarding)
}
}

@ -19,8 +19,8 @@ package com.google.samples.apps.nowinandroid.core.datastore
import androidx.datastore.core.CorruptionException
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import kotlin.test.assertEquals
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test
class UserPreferencesSerializerTest {

@ -36,7 +36,7 @@ import com.google.samples.apps.nowinandroid.core.designsystem.theme.LightDefault
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalBackgroundTheme
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import org.junit.Assert.assertEquals
import kotlin.test.assertEquals
import org.junit.Rule
import org.junit.Test

@ -22,9 +22,9 @@ 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 kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test

@ -24,10 +24,10 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test

@ -21,9 +21,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test

@ -20,13 +20,13 @@ import JvmUnitTestFakeAssetManager
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Codelab
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
import kotlin.test.assertEquals
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.serialization.json.Json
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

@ -17,8 +17,8 @@
package com.google.samples.apps.nowinandroid.core.network.model.util
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType
import kotlin.test.assertEquals
import kotlinx.serialization.json.Json
import org.junit.Assert.assertEquals
import org.junit.Test
class NewsResourceTypeSerializerTest {

@ -156,12 +156,12 @@ fun NewsResourceAuthors(
authors: List<Author>
) {
if (authors.isNotEmpty()) {
// Only display first author for now
val author = authors[0]
// display all authors
val authorNameFormatted =
authors.joinToString(separator = ", ") { author -> author.name }
.uppercase(Locale.getDefault())
val authorNameFormatted = author.name.uppercase(Locale.getDefault())
val authorImageUrl = author.imageUrl
val authorImageUrl = authors[0].imageUrl
val authorImageModifier = Modifier
.clip(CircleShape)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 558 KiB

@ -28,6 +28,9 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.author.navigation.authorIdArg
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlin.test.assertTrue
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
@ -35,8 +38,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -83,15 +84,14 @@ class AuthorViewModelTest {
userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
val item = viewModel.authorUiState.value
assertTrue(item is AuthorUiState.Success)
assertIs<AuthorUiState.Success>(item)
val successAuthorUiState = item as AuthorUiState.Success
val authorFromRepository = authorsRepository.getAuthorStream(
id = testInputAuthors[0].author.id
).first()
successAuthorUiState.followableAuthor.author
assertEquals(authorFromRepository, successAuthorUiState.followableAuthor.author)
item.followableAuthor.author
assertEquals(authorFromRepository, item.followableAuthor.author)
collectJob.cancel()
}
@ -132,8 +132,8 @@ class AuthorViewModelTest {
val authorState = viewModel.authorUiState.value
val newsUiState = viewModel.newsUiState.value
assertTrue(authorState is AuthorUiState.Success)
assertTrue(newsUiState is NewsUiState.Loading)
assertIs<AuthorUiState.Success>(authorState)
assertIs<NewsUiState.Loading>(newsUiState)
collectJob.cancel()
}
@ -155,8 +155,8 @@ class AuthorViewModelTest {
val authorState = viewModel.authorUiState.value
val newsUiState = viewModel.newsUiState.value
assertTrue(authorState is AuthorUiState.Success)
assertTrue(newsUiState is NewsUiState.Success)
assertIs<AuthorUiState.Success>(authorState)
assertIs<NewsUiState.Success>(newsUiState)
collectJob.cancel()
}

@ -34,8 +34,8 @@ import androidx.compose.ui.test.performScrollToNode
import com.google.samples.apps.nowinandroid.core.domain.model.SaveableNewsResource
import com.google.samples.apps.nowinandroid.core.model.data.previewNewsResources
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import org.junit.Rule
import org.junit.Test

@ -23,12 +23,12 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserData
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Loading
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -69,8 +69,8 @@ class BookmarksViewModelTest {
newsRepository.sendNewsResources(previewNewsResources)
userDataRepository.updateNewsResourceBookmark(previewNewsResources[0].id, true)
val item = viewModel.feedUiState.value
assertTrue(item is Success)
assertEquals((item as Success).feed.size, 1)
assertIs<Success>(item)
assertEquals(item.feed.size, 1)
collectJob.cancel()
}
@ -86,8 +86,8 @@ class BookmarksViewModelTest {
viewModel.removeFromSavedResources(previewNewsResources[0].id)
// Verify list of saved resources is now empty
val item = viewModel.feedUiState.value
assertTrue(item is Success)
assertEquals((item as Success).feed.size, 0)
assertIs<Success>(item)
assertEquals(item.feed.size, 0)
collectJob.cancel()
}

@ -16,7 +16,6 @@
package com.google.samples.apps.nowinandroid.feature.foryou
import androidx.compose.runtime.snapshotFlow
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
@ -33,6 +32,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
@ -67,7 +67,7 @@ class ForYouViewModel @Inject constructor(
userData.followedAuthors.isEmpty() &&
userData.followedTopics.isEmpty()
) {
snapshotFlow { NewsFeedUiState.Success(emptyList()) }
flowOf(NewsFeedUiState.Success(emptyList()))
} else {
getSaveableNewsResourcesStream(
filterTopicIds = userData.followedTopics,

@ -34,13 +34,13 @@ import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.core.testing.util.TestNetworkMonitor
import com.google.samples.apps.nowinandroid.core.testing.util.TestSyncStatusMonitor
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@ -28,11 +28,11 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserData
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.interests.InterestsUiState
import com.google.samples.apps.nowinandroid.feature.interests.InterestsViewModel
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@ -22,7 +22,7 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserData
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success
import junit.framework.Assert.assertEquals
import kotlin.test.assertEquals
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher

@ -28,6 +28,8 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRe
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicIdArg
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
@ -35,8 +37,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -77,14 +77,13 @@ class TopicViewModelTest {
topicsRepository.sendTopics(testInputTopics.map(FollowableTopic::topic))
userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
val item = viewModel.topicUiState.value
assertTrue(item is TopicUiState.Success)
assertIs<TopicUiState.Success>(item)
val successTopicState = item as TopicUiState.Success
val topicFromRepository = topicsRepository.getTopic(
testInputTopics[0].topic.id
).first()
assertEquals(topicFromRepository, successTopicState.followableTopic.topic)
assertEquals(topicFromRepository, item.followableTopic.topic)
collectJob.cancel()
}
@ -119,8 +118,8 @@ class TopicViewModelTest {
val topicUiState = viewModel.topicUiState.value
val newsUiState = viewModel.newUiState.value
assertTrue(topicUiState is TopicUiState.Success)
assertTrue(newsUiState is NewsUiState.Loading)
assertIs<TopicUiState.Success>(topicUiState)
assertIs<NewsUiState.Loading>(newsUiState)
collectJob.cancel()
}
@ -141,8 +140,8 @@ class TopicViewModelTest {
val topicUiState = viewModel.topicUiState.value
val newsUiState = viewModel.newUiState.value
assertTrue(topicUiState is TopicUiState.Success)
assertTrue(newsUiState is NewsUiState.Success)
assertIs<TopicUiState.Success>(topicUiState)
assertIs<NewsUiState.Success>(newsUiState)
collectJob.cancel()
}

@ -4,7 +4,7 @@ androidDesugarJdkLibs = "1.2.0"
androidGradlePlugin = "7.3.1"
androidxActivity = "1.6.1"
androidxAppCompat = "1.5.1"
androidxComposeBom = "2022.10.00"
androidxComposeBom = "2022.11.00"
androidxComposeCompiler = "1.3.2"
androidxComposeRuntimeTracing = "1.0.0-alpha01"
androidxCore = "1.9.0"
@ -13,7 +13,7 @@ androidxDataStore = "1.0.0"
androidxEspresso = "3.5.0"
androidxHiltNavigationCompose = "1.0.0"
androidxLifecycle = "2.6.0-alpha03"
androidxMacroBenchmark = "1.1.0"
androidxMacroBenchmark = "1.1.1"
androidxNavigation = "2.5.3"
androidxMetrics = "1.0.0-alpha03"
androidxProfileinstaller = "1.2.0"
@ -27,7 +27,7 @@ androidxTracing = "1.1.0"
androidxUiAutomator = "2.2.0"
androidxWork = "2.7.1"
coil = "2.2.2"
hilt = "2.44"
hilt = "2.44.2"
hiltExt = "1.0.0"
jacoco = "0.8.7"
junit4 = "4.13.2"
@ -35,14 +35,14 @@ kotlin = "1.7.20"
kotlinxCoroutines = "1.6.4"
kotlinxDatetime = "0.4.0"
kotlinxSerializationJson = "1.4.1"
ksp = "1.7.20-1.0.8"
ksp = "1.7.21-1.0.8"
lint = "30.3.1"
okhttp = "4.10.0"
protobuf = "3.21.9"
protobufPlugin = "0.8.19"
retrofit = "2.9.0"
retrofitKotlinxSerializationJson = "0.8.0"
room = "2.5.0-beta01"
room = "2.5.0-beta02"
secrets = "2.0.1"
turbine = "0.12.1"

@ -33,7 +33,7 @@ dependencyResolutionManagement {
rootProject.name = "nowinandroid"
include(":app")
include(":app-nia-catalog")
include(":benchmark")
include(":benchmarks")
include(":core:common")
include(":core:data")
include(":core:data-test")

@ -1,3 +1,3 @@
# :sync module
![Dependency graph](../docs/images/graphs/dep_graph_lint.png)
![Dependency graph](../docs/images/graphs/dep_graph_sync.png)

@ -25,7 +25,7 @@ import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Assert.assertEquals
import kotlin.test.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test

Loading…
Cancel
Save