diff --git a/feature/topic/api/src/main/res/values/strings.xml b/feature/topic/api/src/main/res/values/strings.xml index 1e3f376cf..a5f3c0d58 100644 --- a/feature/topic/api/src/main/res/values/strings.xml +++ b/feature/topic/api/src/main/res/values/strings.xml @@ -16,4 +16,6 @@ --> Loading topic + Unable to load topic + Unable to load news diff --git a/feature/topic/impl/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreenTest.kt b/feature/topic/impl/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreenTest.kt index 5f6782160..98582c44a 100644 --- a/feature/topic/impl/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreenTest.kt +++ b/feature/topic/impl/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreenTest.kt @@ -42,11 +42,13 @@ class TopicScreenTest { val composeTestRule = createAndroidComposeRule() private lateinit var topicLoading: String + private lateinit var topicError: String @Before fun setup() { composeTestRule.activity.apply { topicLoading = getString(R.string.feature_topic_api_loading) + topicError = getString(R.string.feature_topic_api_error) } } @@ -70,6 +72,26 @@ class TopicScreenTest { .assertExists() } + @Test + fun topicError_whenTopicIsError_isShown() { + composeTestRule.setContent { + TopicScreen( + topicUiState = TopicUiState.Error, + newsUiState = NewsUiState.Loading, + showBackButton = true, + onBackClick = {}, + onFollowClick = {}, + onTopicClick = {}, + onBookmarkChanged = { _, _ -> }, + onNewsResourceViewed = {}, + ) + } + + composeTestRule + .onNodeWithText(topicError) + .assertExists() + } + @Test fun topicTitle_whenTopicIsSuccess_isShown() { val testTopic = followableTopicTestData.first() diff --git a/feature/topic/impl/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreen.kt b/feature/topic/impl/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreen.kt index 5c802f225..7469c3a42 100644 --- a/feature/topic/impl/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreen.kt +++ b/feature/topic/impl/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/impl/TopicScreen.kt @@ -129,7 +129,17 @@ internal fun TopicScreen( ) } - TopicUiState.Error -> TODO() + TopicUiState.Error -> { + item { + TopicErrorToolbar( + showBackButton = showBackButton, + onBackClick = onBackClick, + ) + } + item { + TopicErrorState() + } + } is TopicUiState.Success -> { item { TopicToolbar( @@ -177,12 +187,12 @@ private fun topicItemsSize( topicUiState: TopicUiState, newsUiState: NewsUiState, ) = when (topicUiState) { - TopicUiState.Error -> 0 // Nothing + TopicUiState.Error -> 2 // Toolbar and error message TopicUiState.Loading -> 1 // Loading bar is TopicUiState.Success -> when (newsUiState) { - NewsUiState.Error -> 0 // Nothing - NewsUiState.Loading -> 1 // Loading bar - is NewsUiState.Success -> 2 + newsUiState.news.size // Toolbar, header + NewsUiState.Error -> 3 // Toolbar, header, and error message + NewsUiState.Loading -> 3 // Toolbar, header, and loading indicator + is NewsUiState.Success -> 2 + newsUiState.news.size // Toolbar, header, and news items } } @@ -250,7 +260,11 @@ private fun LazyListScope.userNewsResourceCards( } else -> item { - Text("Error") // TODO + Text( + text = stringResource(id = TopicR.string.feature_topic_api_news_error), + modifier = Modifier.padding(24.dp), + style = MaterialTheme.typography.bodyLarge, + ) } } } @@ -273,6 +287,44 @@ private fun TopicBodyPreview() { } } +@Composable +private fun TopicErrorState(modifier: Modifier = Modifier) { + Text( + text = stringResource(id = TopicR.string.feature_topic_api_error), + modifier = modifier + .fillMaxWidth() + .padding(24.dp) + .testTag("topic:error"), + style = MaterialTheme.typography.bodyLarge, + ) +} + +@Composable +private fun TopicErrorToolbar( + showBackButton: Boolean, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .fillMaxWidth() + .padding(bottom = 32.dp), + ) { + if (showBackButton) { + IconButton(onClick = onBackClick) { + Icon( + imageVector = NiaIcons.ArrowBack, + contentDescription = stringResource( + id = UiR.string.core_ui_back, + ), + ) + } + } + } +} + @Composable private fun TopicToolbar( uiState: FollowableTopic,