diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt index e23b57333..41c0eb407 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt @@ -109,7 +109,7 @@ fun NiaApp( LaunchedEffect(stateMessage) { stateMessage?.let { message -> - //Text and Duration values dictated by the UI + // Text and Duration values dictated by the UI val (text, duration) = getSnackbarValues(context, message) // Determine whether user clicked action button @@ -301,4 +301,4 @@ private fun getSnackbarValues(context: Context, message: MessageData): Pair (message.type as MESSAGE).value to SnackbarDuration.Long UNKNOWN -> context.getString(R.string.unknown_error) to SnackbarDuration.Short } -} \ No newline at end of file +} diff --git a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppScreenSizesScreenshotTests.kt b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppScreenSizesScreenshotTests.kt index 9c9488fde..47bd1baf3 100644 --- a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppScreenSizesScreenshotTests.kt +++ b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppScreenSizesScreenshotTests.kt @@ -32,6 +32,7 @@ import com.github.takahirom.roborazzi.captureRoboImage import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme @@ -80,6 +81,9 @@ class NiaAppScreenSizesScreenshotTests { @Inject lateinit var networkMonitor: NetworkMonitor + @Inject + lateinit var errorMonitor: ErrorMonitor + @Inject lateinit var timeZoneMonitor: TimeZoneMonitor @@ -123,6 +127,7 @@ class NiaAppScreenSizesScreenshotTests { NiaTheme { val fakeAppState = rememberNiaAppState( networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) diff --git a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppStateTest.kt b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppStateTest.kt index c6ddb54fb..1dba37a6b 100644 --- a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppStateTest.kt +++ b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppStateTest.kt @@ -27,8 +27,10 @@ import androidx.navigation.compose.composable import androidx.navigation.createGraph import androidx.navigation.testing.TestNavHostController import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor 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.TestErrorMonitor import com.google.samples.apps.nowinandroid.core.testing.util.TestNetworkMonitor import com.google.samples.apps.nowinandroid.core.testing.util.TestTimeZoneMonitor import dagger.hilt.android.testing.HiltAndroidTest @@ -43,6 +45,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import javax.inject.Inject import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -60,6 +63,8 @@ class NiaAppStateTest { // Create the test dependencies. private val networkMonitor = TestNetworkMonitor() + private var errorMonitor = TestErrorMonitor() + private val timeZoneMonitor = TestTimeZoneMonitor() private val userNewsResourceRepository = @@ -79,6 +84,7 @@ class NiaAppStateTest { navController = navController, coroutineScope = backgroundScope, networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) @@ -101,6 +107,7 @@ class NiaAppStateTest { composeTestRule.setContent { state = rememberNiaAppState( networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) @@ -119,6 +126,7 @@ class NiaAppStateTest { navController = NavHostController(LocalContext.current), coroutineScope = backgroundScope, networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) @@ -139,6 +147,7 @@ class NiaAppStateTest { navController = NavHostController(LocalContext.current), coroutineScope = backgroundScope, networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) diff --git a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarInsetsScreenshotTests.kt b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarInsetsScreenshotTests.kt index 78f568e03..e464eaffe 100644 --- a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarInsetsScreenshotTests.kt +++ b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarInsetsScreenshotTests.kt @@ -63,6 +63,7 @@ import com.github.takahirom.roborazzi.captureRoboImage import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeUserDataRepository +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme @@ -113,6 +114,9 @@ class SnackbarInsetsScreenshotTests { @Inject lateinit var networkMonitor: NetworkMonitor + @Inject + lateinit var errorMonitor: ErrorMonitor + @Inject lateinit var timeZoneMonitor: TimeZoneMonitor @@ -254,6 +258,7 @@ class SnackbarInsetsScreenshotTests { NiaTheme { val appState = rememberNiaAppState( networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) diff --git a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarScreenshotTests.kt b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarScreenshotTests.kt index b9b1047c1..284ccc90d 100644 --- a/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarScreenshotTests.kt +++ b/app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/SnackbarScreenshotTests.kt @@ -36,6 +36,7 @@ import com.github.takahirom.roborazzi.captureRoboImage import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeUserDataRepository +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme @@ -86,6 +87,9 @@ class SnackbarScreenshotTests { @Inject lateinit var networkMonitor: NetworkMonitor + @Inject + lateinit var errorMonitor: ErrorMonitor + @Inject lateinit var timeZoneMonitor: TimeZoneMonitor @@ -203,6 +207,7 @@ class SnackbarScreenshotTests { NiaTheme { val appState = rememberNiaAppState( networkMonitor = networkMonitor, + errorMonitor = errorMonitor, userNewsResourceRepository = userNewsResourceRepository, timeZoneMonitor = timeZoneMonitor, ) diff --git a/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/EmptyErrorMonitor.kt b/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/EmptyErrorMonitor.kt new file mode 100644 index 000000000..f12ba0690 --- /dev/null +++ b/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/EmptyErrorMonitor.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 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.data.test + +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor +import com.google.samples.apps.nowinandroid.core.model.data.MessageData +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import javax.inject.Inject + +class EmptyErrorMonitor @Inject constructor(): ErrorMonitor { + + override fun addMessageByString(message: String): MessageData { + TODO("Not yet implemented") + } + + override fun addMessageByData(message: MessageData) { + TODO("Not yet implemented") + } + + override fun clearMessage(message: MessageData) { + TODO("Not yet implemented") + } + + override fun clearAllMessages() { + TODO("Not yet implemented") + } + + override val messages: Flow> + get() = flowOf(emptyList()) + +} \ No newline at end of file diff --git a/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt b/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt index 46158479c..4d48123bc 100644 --- a/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt +++ b/core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt @@ -27,6 +27,7 @@ import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeRecent import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeSearchContentsRepository import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeTopicsRepository import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeUserDataRepository +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import dagger.Binds @@ -70,6 +71,11 @@ internal interface TestDataModule { networkMonitor: AlwaysOnlineNetworkMonitor, ): NetworkMonitor + @Binds + fun bindsErrorMonitor( + errorMonitor: EmptyErrorMonitor, + ): ErrorMonitor + @Binds fun binds(impl: DefaultZoneIdTimeZoneMonitor): TimeZoneMonitor } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestErrorMonitor.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestErrorMonitor.kt new file mode 100644 index 000000000..64840337a --- /dev/null +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestErrorMonitor.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2025 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.testing.util + +import com.google.samples.apps.nowinandroid.core.data.util.ErrorMonitor +import com.google.samples.apps.nowinandroid.core.model.data.MessageData +import com.google.samples.apps.nowinandroid.core.model.data.MessageType +import com.google.samples.apps.nowinandroid.core.model.data.MessageType.MESSAGE +import com.google.samples.apps.nowinandroid.core.model.data.MessageType.OFFLINE +import com.google.samples.apps.nowinandroid.core.model.data.MessageType.UNKNOWN +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flowOf + +class TestErrorMonitor : ErrorMonitor { + + private val _messages = MutableStateFlow>(emptyList()) + + override fun addMessageByString(message: String): MessageData { + TODO("Not yet implemented") + } + + override fun addMessageByData(message: MessageData) { + TODO("Not yet implemented") + } + + override fun clearMessage(message: MessageData) { + TODO("Not yet implemented") + } + + override fun clearAllMessages() { + _messages.value = emptyList() + } + + override val messages: Flow> + get() = _messages + + /** + * Test-only API to add message types + */ + + fun setOfflineMessage(){ + _messages.value = listOf(OFFLINE_MESSAGE) + } + + fun addMessage(){ + _messages.value.plus(MESSAGE_MESSAGE) + } + + fun addUnknownMessage(){ + _messages.value.plus(UNKNOWN_MESSAGE) + } + + companion object{ + val OFFLINE_MESSAGE = MessageData(OFFLINE) + val MESSAGE_MESSAGE = MessageData(MESSAGE("Message"), "Title", {}, {}) + val UNKNOWN_MESSAGE = MessageData(UNKNOWN) + } +} \ No newline at end of file