From d2db9df192760b9e0733a2ecb6301986dd188e1d Mon Sep 17 00:00:00 2001 From: "Mr. 17" Date: Wed, 24 Jul 2024 20:50:25 +0530 Subject: [PATCH] Fix part of #5344: Add coming soon topic list UI & fix recommendation logic tests (#5460) ## Explanation Fixes part of #5344 This PR adds the coming soon topic list UI and fixes previously ignored promoted stories UI tests by correcting the test setup. ## Screenshots ### Phone |Portrait|Landscape| |--|--| |![image](https://github.com/oppia/oppia-android/assets/84731134/554eeab5-2d9e-40a5-ab01-51c8a0a69661)|![image](https://github.com/oppia/oppia-android/assets/84731134/51a2c638-065e-4d75-92c4-046f8d0609d7)| ### Tablet |Portrait|Landscape| |--|--| |![image](https://github.com/oppia/oppia-android/assets/84731134/1ddd19d6-df04-44dd-8073-f9b77554b2d7)|![image](https://github.com/oppia/oppia-android/assets/84731134/dd680415-c9a5-4996-ae9f-55167cc0f0df)| ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - For PRs introducing new UI elements or color changes, both light and dark mode screenshots must be included - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --------- Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com> --- .../ClassroomListFragmentPresenter.kt | 10 + .../promotedlist/ComingSoonTopicList.kt | 181 ++++++++++++++++++ .../{PromotedList.kt => PromotedStoryList.kt} | 0 app/src/main/res/values-land/dimens.xml | 4 + .../main/res/values-sw600dp-land/dimens.xml | 4 + .../main/res/values-sw600dp-port/dimens.xml | 4 + app/src/main/res/values/dimens.xml | 13 ++ .../classroom/ClassroomListFragmentTest.kt | 159 +++++++++++---- scripts/assets/test_file_exemptions.textproto | 6 +- 9 files changed, 343 insertions(+), 38 deletions(-) create mode 100644 app/src/main/java/org/oppia/android/app/classroom/promotedlist/ComingSoonTopicList.kt rename app/src/main/java/org/oppia/android/app/classroom/promotedlist/{PromotedList.kt => PromotedStoryList.kt} (100%) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index ba75fda470a..4b70fdddc67 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -30,6 +30,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import org.oppia.android.R import org.oppia.android.app.classroom.classroomlist.ClassroomList +import org.oppia.android.app.classroom.promotedlist.ComingSoonTopicList import org.oppia.android.app.classroom.promotedlist.PromotedStoryList import org.oppia.android.app.classroom.topiclist.AllTopicsHeaderText import org.oppia.android.app.classroom.topiclist.TopicCard @@ -38,6 +39,7 @@ import org.oppia.android.app.home.HomeItemViewModel import org.oppia.android.app.home.RouteToTopicPlayStoryListener import org.oppia.android.app.home.WelcomeViewModel import org.oppia.android.app.home.classroomlist.ClassroomSummaryViewModel +import org.oppia.android.app.home.promotedlist.ComingSoonTopicListViewModel import org.oppia.android.app.home.promotedlist.PromotedStoryListViewModel import org.oppia.android.app.home.topiclist.AllTopicsViewModel import org.oppia.android.app.home.topiclist.TopicSummaryViewModel @@ -213,6 +215,14 @@ class ClassroomListFragmentPresenter @Inject constructor( ) } } + ComingSoonTopicListViewModel::class -> items.forEach { item -> + item { + ComingSoonTopicList( + comingSoonTopicListViewModel = item as ComingSoonTopicListViewModel, + machineLocale = machineLocale, + ) + } + } ClassroomSummaryViewModel::class -> stickyHeader { ClassroomList( classroomSummaryList = items.map { it as ClassroomSummaryViewModel }, diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/ComingSoonTopicList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/ComingSoonTopicList.kt new file mode 100644 index 00000000000..0d9de4ef7b0 --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/ComingSoonTopicList.kt @@ -0,0 +1,181 @@ +package org.oppia.android.app.classroom.promotedlist + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Card +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.oppia.android.R +import org.oppia.android.app.classroom.getDrawableResource +import org.oppia.android.app.home.promotedlist.ComingSoonTopicListViewModel +import org.oppia.android.app.home.promotedlist.ComingSoonTopicsViewModel +import org.oppia.android.util.locale.OppiaLocale + +/** Test tag for the header of the promoted story list. */ +const val COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG = "TEST_TAG.coming_soon_topic_list_header" + +/** Test tag for the promoted story list. */ +const val COMING_SOON_TOPIC_LIST_TEST_TAG = "TEST_TAG.coming_soon_topic_list" + +/** Displays a list of topics to be published soon. */ +@Composable +fun ComingSoonTopicList( + comingSoonTopicListViewModel: ComingSoonTopicListViewModel, + machineLocale: OppiaLocale.MachineLocale, +) { + Text( + text = stringResource(id = R.string.coming_soon), + color = colorResource(id = R.color.component_color_shared_primary_text_color), + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = dimensionResource(id = R.dimen.coming_soon_topic_list_header_text_size).value.sp, + modifier = Modifier + .padding( + start = dimensionResource(id = R.dimen.coming_soon_topic_list_layout_margin_start), + top = dimensionResource(id = R.dimen.coming_soon_topic_list_layout_margin_top), + end = dimensionResource(id = R.dimen.coming_soon_topic_list_layout_margin_end), + ) + .testTag(COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG), + ) + LazyRow( + modifier = Modifier + .padding( + top = dimensionResource(id = R.dimen.coming_soon_topic_list_padding) + ) + .testTag(COMING_SOON_TOPIC_LIST_TEST_TAG), + contentPadding = PaddingValues( + start = dimensionResource(id = R.dimen.coming_soon_topic_list_layout_margin_start), + end = dimensionResource(id = R.dimen.home_padding_end), + ), + ) { + items(comingSoonTopicListViewModel.comingSoonTopicList) { + ComingSoonTopicCard( + comingSoonTopicsViewModel = it, + machineLocale = machineLocale, + ) + } + } +} + +/** Displays a card with the coming soon topic summary information. */ +@Composable +fun ComingSoonTopicCard( + comingSoonTopicsViewModel: ComingSoonTopicsViewModel, + machineLocale: OppiaLocale.MachineLocale, +) { + Card( + modifier = Modifier + .width(dimensionResource(id = R.dimen.coming_soon_topic_card_width)) + .padding( + start = dimensionResource(id = R.dimen.coming_soon_topic_card_layout_margin_start), + end = dimensionResource(id = R.dimen.coming_soon_topic_card_layout_margin_end), + bottom = dimensionResource(id = R.dimen.coming_soon_topic_card_layout_margin_bottom), + ), + elevation = dimensionResource(id = R.dimen.topic_card_elevation), + ) { + Box( + contentAlignment = Alignment.TopEnd + ) { + Column( + verticalArrangement = Arrangement.Center, + ) { + Image( + painter = painterResource( + id = comingSoonTopicsViewModel.topicSummary.lessonThumbnail.getDrawableResource() + ), + contentDescription = "Picture of a " + + "${comingSoonTopicsViewModel.topicSummary.lessonThumbnail.thumbnailGraphic.name}.", + modifier = Modifier + .aspectRatio(4f / 3f) + .background( + Color( + ( + 0xff000000L or + comingSoonTopicsViewModel + .topicSummary.lessonThumbnail.backgroundColorRgb.toLong() + ).toInt() + ) + ) + ) + ComingSoonTopicCardTextSection(comingSoonTopicsViewModel) + } + Text( + text = machineLocale + .run { stringResource(id = R.string.coming_soon).toMachineUpperCase() }, + modifier = Modifier + .background( + color = colorResource( + id = R.color.component_color_coming_soon_rect_background_start_color + ), + shape = RoundedCornerShape(topEnd = 4.dp, bottomStart = 12.dp), + ) + .padding( + horizontal = dimensionResource(id = R.dimen.coming_soon_text_padding_horizontal), + vertical = dimensionResource(id = R.dimen.coming_soon_text_padding_vertical), + ), + fontSize = 12.sp, + color = colorResource(id = R.color.component_color_shared_secondary_4_text_color), + fontFamily = FontFamily.SansSerif, + textAlign = TextAlign.End, + ) + } + } +} + +/** Displays the topic title. */ +@Composable +fun ComingSoonTopicCardTextSection(comingSoonTopicsViewModel: ComingSoonTopicsViewModel) { + Column( + modifier = Modifier + .fillMaxWidth() + .background( + color = colorResource( + id = R.color.component_color_shared_topic_card_item_background_color + ) + ), + verticalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = comingSoonTopicsViewModel.topicTitle, + modifier = Modifier + .fillMaxWidth() + .padding( + start = dimensionResource(id = R.dimen.coming_soon_topic_card_text_padding), + top = dimensionResource(id = R.dimen.coming_soon_topic_card_text_padding), + end = dimensionResource(id = R.dimen.coming_soon_topic_card_text_padding), + bottom = dimensionResource(id = R.dimen.coming_soon_topic_card_text_padding_bottom), + ), + color = colorResource(id = R.color.component_color_shared_secondary_4_text_color), + fontFamily = FontFamily.SansSerif, + fontSize = dimensionResource(id = R.dimen.topic_list_item_text_size).value.sp, + textAlign = TextAlign.Start, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } +} diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt similarity index 100% rename from app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt rename to app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 49afd330bdf..b3f06ca1eea 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -281,6 +281,10 @@ 16dp 0dp 0dp + 72dp + 72dp + 8dp + 8dp 16dp diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml index 47caee25f05..41ab69599ed 100644 --- a/app/src/main/res/values-sw600dp-land/dimens.xml +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -290,6 +290,10 @@ 20dp 0dp 0dp + 72dp + 72dp + 0dp + 32dp 24dp diff --git a/app/src/main/res/values-sw600dp-port/dimens.xml b/app/src/main/res/values-sw600dp-port/dimens.xml index d2c15feccbc..3968e41fee3 100644 --- a/app/src/main/res/values-sw600dp-port/dimens.xml +++ b/app/src/main/res/values-sw600dp-port/dimens.xml @@ -295,6 +295,10 @@ 12dp 0dp 0dp + 60dp + 60dp + 8dp + 24dp 24dp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0b06f5569ba..bcf1a4acd85 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -468,6 +468,19 @@ 4dp 28dp 28dp + 18sp + 28dp + 24dp + 28dp + 12dp + 8dp + 8dp + 8dp + 160dp + 8dp + 30dp + 6dp + 12dp 36dp diff --git a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt index eb9f0f41cc8..4a3fe4c6360 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt @@ -28,7 +28,6 @@ import org.hamcrest.Matcher import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -44,6 +43,8 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.classroom.classroomlist.CLASSROOM_HEADER_TEST_TAG import org.oppia.android.app.classroom.classroomlist.CLASSROOM_LIST_TEST_TAG +import org.oppia.android.app.classroom.promotedlist.COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG +import org.oppia.android.app.classroom.promotedlist.COMING_SOON_TOPIC_LIST_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_HEADER_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_TEST_TAG import org.oppia.android.app.classroom.topiclist.ALL_TOPICS_HEADER_TEST_TAG @@ -223,8 +224,8 @@ class ClassroomListFragmentTest { fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_FIXED_FAKE_TIME) fakeOppiaClock.setCurrentTimeToSameDateTime(EVENING_TIMESTAMP) - composeRule.activity.recreate() - testCoroutineDispatchers.runCurrent() + // Refresh the welcome text content. + logIntoAdmin() onView(isRoot()).perform(orientationLandscape()) @@ -238,8 +239,8 @@ class ClassroomListFragmentTest { fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_FIXED_FAKE_TIME) fakeOppiaClock.setCurrentTimeToSameDateTime(MORNING_TIMESTAMP) - composeRule.activity.recreate() - testCoroutineDispatchers.runCurrent() + // Refresh the welcome text content. + logIntoAdmin() composeRule.onNodeWithTag(WELCOME_TEST_TAG) .assertTextContains("Good morning, Admin!") @@ -251,8 +252,8 @@ class ClassroomListFragmentTest { fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_FIXED_FAKE_TIME) fakeOppiaClock.setCurrentTimeToSameDateTime(AFTERNOON_TIMESTAMP) - composeRule.activity.recreate() - testCoroutineDispatchers.runCurrent() + // Refresh the welcome text content. + logIntoAdmin() composeRule.onNodeWithTag(WELCOME_TEST_TAG) .assertTextContains("Good afternoon, Admin!") @@ -264,8 +265,8 @@ class ClassroomListFragmentTest { fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_FIXED_FAKE_TIME) fakeOppiaClock.setCurrentTimeToSameDateTime(EVENING_TIMESTAMP) - composeRule.activity.recreate() - testCoroutineDispatchers.runCurrent() + // Refresh the welcome text content. + logIntoAdmin() composeRule.onNodeWithTag(WELCOME_TEST_TAG) .assertTextContains("Good evening, Admin!") @@ -280,6 +281,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_recentlyPlayedStoriesTextIsDisplayed() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, @@ -289,7 +291,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recently_played_stories)) @@ -298,6 +299,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_viewAllTextIsDisplayed() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, @@ -311,7 +313,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(1) .assertTextContains( @@ -322,6 +323,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_storiesPlayedOneWeekAgo_displaysLastPlayedStoriesText() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, @@ -332,7 +334,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = true ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.last_played_stories)) @@ -341,12 +342,12 @@ class ClassroomListFragmentTest { @Test fun testFragment_markStory0DoneForFraction_displaysRecommendedStories() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedFractionsTopic( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recommended_stories)) @@ -369,12 +370,12 @@ class ClassroomListFragmentTest { @Test fun testFragment_markCompletedRatiosStory0_recommendsFractions() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedRatiosStory0( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recommended_stories)) @@ -412,21 +413,20 @@ class ClassroomListFragmentTest { @Test fun testFragment_forPromotedActivityList_hideViewAll() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(1) .assertDoesNotExist() } @Test - @Ignore("Temporarily ignored as the test is failing.") - // TODO(#5344): Update the logic or fix the test. - fun testFragment_markStory0DoneForRatiosAndFirstTestTopic_displaysRecommendedStories() { + fun testFragment_markStory0DoneForRatiosAndFirstTestTopic_displaysSuggestedStories() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedTestTopic0Story0( profileId = profileId, @@ -436,7 +436,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recommended_stories)) @@ -469,6 +468,7 @@ class ClassroomListFragmentTest { */ @Test fun testFragment_markStory0DonePlayStory1FirstTestTopic_playFractionsTopic_orderIsCorrect() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedTestTopic0Story0( profileId = profileId, @@ -482,7 +482,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.stories_for_you)) @@ -501,28 +500,29 @@ class ClassroomListFragmentTest { .assertTextContains("MATHS") .assertIsDisplayed() - // TODO(#5344): 'What is a Ratio?' story should be promoted. - onChildAt(2) - .assertDoesNotExist() + performScrollToIndex(2) + onChildAt(1) + .assertTextContains("What is a Ratio?") + .assertTextContains("RATIOS AND PROPORTIONAL REASONING") + .assertTextContains("MATHS") + .assertIsDisplayed() } } @Test - @Ignore - // TODO(#5344): Update logic or fix the test. - fun testFragment_markStory0DoneFirstTestTopic_recommendedStoriesIsCorrect() { + fun testFragment_markStory0DoneFirstTestTopic_suggestedStoriesIsCorrect() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedTestTopic0Story0( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recommended_stories)) .assertIsDisplayed() - composeRule.onNodeWithTag(PROMOTED_STORY_LIST_TEST_TAG).onChildAt(1) + composeRule.onNodeWithTag(PROMOTED_STORY_LIST_TEST_TAG).onChildAt(0) .assertTextContains("What is a Ratio?") .assertTextContains("RATIOS AND PROPORTIONAL REASONING") .assertTextContains("MATHS") @@ -531,15 +531,12 @@ class ClassroomListFragmentTest { @Test fun testFragment_markStory0DoneForFractions_recommendedStoriesIsCorrect() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markCompletedFractionsStory0( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() - - composeRule.activity.recreate() - testCoroutineDispatchers.runCurrent() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.recommended_stories)) @@ -562,6 +559,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_clickViewAll_opensRecentlyPlayedActivity() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, @@ -575,7 +573,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(1) .assertIsDisplayed() @@ -586,6 +583,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_markFullProgressForFractions_playRatios_displaysRecommendedStories() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedRatiosStory0Exp0( profileId = profileId, @@ -595,7 +593,6 @@ class ClassroomListFragmentTest { profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).onChildAt(0) .assertTextContains(context.getString(R.string.stories_for_you)) @@ -616,14 +613,98 @@ class ClassroomListFragmentTest { } } + @Test + fun testFragment_markAtLeastOneStoryCompletedForAllTopics_displaysComingSoonTopicsList() { + logIntoAdminTwice() + fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) + storyProgressTestHelper.markCompletedFractionsTopic( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markCompletedTestTopic0( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markCompletedRatiosStory0( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markCompletedTestTopic1( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG) + .assertTextContains(context.getString(R.string.coming_soon)) + .assertIsDisplayed() + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_TEST_TAG) + .onChildAt(0) + .onChildAt(1) + .assertTextContains("Third Test Topic") + .assertIsDisplayed() + } + + @Test + fun testFragment_markFullProgressForSecondTestTopic_displaysComingSoonTopicsText() { + logIntoAdminTwice() + fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) + storyProgressTestHelper.markCompletedTestTopic1( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG) + .assertTextContains(context.getString(R.string.coming_soon)) + .assertIsDisplayed() + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_TEST_TAG) + .onChildAt(0) + .onChildAt(1) + .assertTextContains("Third Test Topic") + .assertIsDisplayed() + } + + @Test + fun testFragment_markStory0OfRatiosAndTestTopics0And1Done_playTestTopicStory0_noPromotions() { + logIntoAdminTwice() + fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) + storyProgressTestHelper.markCompletedRatiosStory0( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markCompletedTestTopic1( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markCompletedTestTopic0Story0( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + storyProgressTestHelper.markInProgressSavedTestTopic0Story0( + profileId = profileId, + timestampOlderThanOneWeek = false + ) + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_HEADER_TEST_TAG) + .assertTextContains(context.getString(R.string.coming_soon)) + .assertIsDisplayed() + + composeRule.onNodeWithTag(COMING_SOON_TOPIC_LIST_TEST_TAG) + .onChildAt(0) + .onChildAt(1) + .assertTextContains("Third Test Topic") + .assertIsDisplayed() + } + @Test fun testFragment_clickPromotedStory_opensTopicActivity() { + logIntoAdminTwice() fakeOppiaClock.setFakeTimeMode(FakeOppiaClock.FakeTimeMode.MODE_UPTIME_MILLIS) storyProgressTestHelper.markInProgressSavedFractionsStory0Exp0( profileId = profileId, timestampOlderThanOneWeek = false ) - logIntoAdminTwice() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_TEST_TAG).onChildAt(0) .assertIsDisplayed() @@ -770,11 +851,15 @@ class ClassroomListFragmentTest { .assertIsDisplayed() } - private fun logIntoAdminTwice() { - dataProviderTestMonitor.waitForNextSuccessfulResult(profileTestHelper.logIntoAdmin()) + private fun logIntoAdmin() { dataProviderTestMonitor.waitForNextSuccessfulResult(profileTestHelper.logIntoAdmin()) } + private fun logIntoAdminTwice() { + logIntoAdmin() + logIntoAdmin() + } + private fun setUpTestApplicationComponent() { ApplicationProvider.getApplicationContext().inject(this) } diff --git a/scripts/assets/test_file_exemptions.textproto b/scripts/assets/test_file_exemptions.textproto index d1ff255fc64..7ff7c89edd6 100644 --- a/scripts/assets/test_file_exemptions.textproto +++ b/scripts/assets/test_file_exemptions.textproto @@ -275,7 +275,11 @@ test_file_exemption { test_file_not_required: true } test_file_exemption { - exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt" + exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/promotedlist/ComingSoonTopicList.kt" + test_file_not_required: true +} +test_file_exemption { + exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt" test_file_not_required: true } test_file_exemption {