From 16082aac839fc3e0a4c245bbc16e4b5f1a1dfe57 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:02:41 +0530 Subject: [PATCH] Fix #5485 Create means for verifying Fragment Arguments (#5522) ## Explanation Feature Request part1 #5485 Added test for 10 fragments arguments and saveInstanceState. ## 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 --- .../app/options/AppLanguageFragment.kt | 3 +- .../app/options/AudioLanguageFragment.kt | 3 +- .../MarkChaptersCompletedFragmentTest.kt | 67 +++++++++++++++++++ .../MarkStoriesCompletedFragmentTest.kt | 54 +++++++++++++++ .../MarkTopicsCompletedFragmentTest.kt | 52 ++++++++++++++ .../android/app/help/HelpFragmentTest.kt | 32 +++++++++ .../app/options/AppLanguageFragmentTest.kt | 46 +++++++++++++ .../app/options/AudioLanguageFragmentTest.kt | 62 +++++++++++++++-- .../app/player/audio/AudioFragmentTest.kt | 20 ++++++ .../profile/ProfileEditFragmentTest.kt | 34 ++++++++++ .../app/thirdparty/LicenseListFragmentTest.kt | 30 +++++++++ .../conceptcard/ConceptCardFragmentTest.kt | 35 ++++++++++ 12 files changed, 431 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AppLanguageFragment.kt b/app/src/main/java/org/oppia/android/app/options/AppLanguageFragment.kt index b946c93555b..477b78c49fd 100644 --- a/app/src/main/java/org/oppia/android/app/options/AppLanguageFragment.kt +++ b/app/src/main/java/org/oppia/android/app/options/AppLanguageFragment.kt @@ -42,7 +42,8 @@ class AppLanguageFragment : InjectableFragment(), AppLanguageRadioButtonListener } } - private fun Bundle.retrieveLanguageFromArguments(): OppiaLanguage { + /** Returns the [OppiaLanguage] stored in the fragment's arguments. */ + fun Bundle.retrieveLanguageFromArguments(): OppiaLanguage { return getProto( FRAGMENT_ARGUMENTS_KEY, AppLanguageFragmentArguments.getDefaultInstance() ).oppiaLanguage diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt index 71ea48ca09e..4cb067f8cc7 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt @@ -84,7 +84,8 @@ class AudioLanguageFragment : InjectableFragment(), AudioLanguageRadioButtonList } } - private fun Bundle.retrieveLanguageFromArguments(): AudioLanguage { + /** Returns the [AudioLanguage] stored in the fragment's arguments. */ + fun Bundle.retrieveLanguageFromArguments(): AudioLanguage { return getProto( FRAGMENT_ARGUMENTS_KEY, AudioLanguageFragmentArguments.getDefaultInstance() ).audioLanguage diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt index 8c79da699c3..2ce4a9323ab 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt @@ -40,8 +40,10 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule +import org.oppia.android.app.devoptions.markchapterscompleted.MarkChaptersCompletedFragment import org.oppia.android.app.devoptions.markchapterscompleted.testing.MarkChaptersCompletedTestActivity import org.oppia.android.app.model.ChapterPlayState +import org.oppia.android.app.model.MarkChaptersCompletedFragmentArguments import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView @@ -94,6 +96,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProto import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -901,6 +904,70 @@ class MarkChaptersCompletedFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launchMarkChaptersCompletedFragmentTestActivity( + internalProfileId, showConfirmationNotice = true + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + val fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_chapters_completed_container) as MarkChaptersCompletedFragment + val arguments = + checkNotNull(fragment.arguments) { + "Expected arguments to be passed to MarkChaptersCompletedFragment" + } + val args = arguments.getProto( + "MarkChaptersCompletedFragment.arguments", + MarkChaptersCompletedFragmentArguments.getDefaultInstance() + ) + val receivedInternalProfileId = args?.internalProfileId + val receivedShowConfirmationNotice = args?.showConfirmationNotice + + assertThat(receivedInternalProfileId).isEqualTo(internalProfileId) + assertThat(receivedShowConfirmationNotice).isEqualTo(true) + } + } + } + + @Test + fun testFragment_saveInstanceState_verifyCorrectStateRestored() { + launchMarkChaptersCompletedFragmentTestActivity( + internalProfileId, showConfirmationNotice = true + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.mark_chapters_completed_all_check_box_container)).perform(click()) + var actualSelectedExplorationIds = ArrayList() + var actualSelectedExplorationTitles = ArrayList() + + scenario.onActivity { activity -> + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_chapters_completed_container) as MarkChaptersCompletedFragment + + actualSelectedExplorationIds = + fragment.markChaptersCompletedFragmentPresenter.serializableSelectedExplorationIds + actualSelectedExplorationTitles = + fragment.markChaptersCompletedFragmentPresenter.serializableSelectedExplorationTitles + } + + scenario.recreate() + + scenario.onActivity { activity -> + val newFragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_chapters_completed_container) as MarkChaptersCompletedFragment + + val receivedSelectedExplorationIds = + newFragment.markChaptersCompletedFragmentPresenter.serializableSelectedExplorationIds + val receivedSelectedExplorationTitles = + newFragment.markChaptersCompletedFragmentPresenter.serializableSelectedExplorationTitles + + assertThat(receivedSelectedExplorationIds).isEqualTo(actualSelectedExplorationIds) + assertThat(receivedSelectedExplorationTitles).isEqualTo(actualSelectedExplorationTitles) + } + } + } + private fun launchMarkChaptersCompletedFragmentTestActivity( internalProfileId: Int, showConfirmationNotice: Boolean = false diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt index 19836a42087..f8ab0bbacef 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt @@ -37,6 +37,7 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule +import org.oppia.android.app.devoptions.markstoriescompleted.MarkStoriesCompletedFragment import org.oppia.android.app.devoptions.markstoriescompleted.testing.MarkStoriesCompletedTestActivity import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule @@ -99,6 +100,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule import org.oppia.android.util.parser.image.GlideImageLoaderModule import org.oppia.android.util.parser.image.ImageParsingModule +import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import javax.inject.Inject @@ -469,6 +471,58 @@ class MarkStoriesCompletedFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launch( + createMarkStoriesCompletedTestActivityIntent(internalProfileId) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + val fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_stories_completed_container) as MarkStoriesCompletedFragment + + val arguments = + checkNotNull(fragment.arguments) { + "Expected arguments to be passed to MarkStoriesCompletedFragment" + } + val profileId = arguments.extractCurrentUserProfileId() + val receivedInternalProfileId = profileId.internalId + + assertThat(receivedInternalProfileId).isEqualTo(internalProfileId) + } + } + } + + @Test + fun testFragment_saveInstanceState_verifyCorrectStateRestored() { + launch( + createMarkStoriesCompletedTestActivityIntent(internalProfileId) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.mark_stories_completed_all_check_box_container)).perform(click()) + var actualSelectedStoryIdList = ArrayList() + + scenario.onActivity { activity -> + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_stories_completed_container) as MarkStoriesCompletedFragment + actualSelectedStoryIdList = + fragment.markStoriesCompletedFragmentPresenter.selectedStoryIdList + } + + scenario.recreate() + + scenario.onActivity { activity -> + val newFragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_stories_completed_container) as MarkStoriesCompletedFragment + val receivedSelectedStoryIdList = + newFragment.markStoriesCompletedFragmentPresenter.selectedStoryIdList + + assertThat(receivedSelectedStoryIdList).isEqualTo(actualSelectedStoryIdList) + } + } + } + private fun createMarkStoriesCompletedTestActivityIntent(internalProfileId: Int): Intent { return MarkStoriesCompletedTestActivity.createMarkStoriesCompletedTestIntent( context, internalProfileId diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt index dd17bbe74ba..91cc3ee71f2 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt @@ -37,6 +37,7 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule +import org.oppia.android.app.devoptions.marktopicscompleted.MarkTopicsCompletedFragment import org.oppia.android.app.devoptions.marktopicscompleted.testing.MarkTopicsCompletedTestActivity import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule @@ -99,6 +100,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule import org.oppia.android.util.parser.image.GlideImageLoaderModule import org.oppia.android.util.parser.image.ImageParsingModule +import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import javax.inject.Inject @@ -450,6 +452,56 @@ class MarkTopicsCompletedFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launch( + createMarkTopicsCompletedTestActivityIntent(internalProfileId) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_topics_completed_container) as MarkTopicsCompletedFragment + val arguments = + checkNotNull(fragment.arguments) { + "Expected arguments to be passed to MarkTopicsCompletedFragment" + } + val receivedProfileId = arguments.extractCurrentUserProfileId() + + assertThat(receivedProfileId).isEqualTo(profileId) + } + } + } + + @Test + fun testFragment_saveInstanceState_verifyCorrectStateRestored() { + launch( + createMarkTopicsCompletedTestActivityIntent(internalProfileId) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.mark_topics_completed_all_check_box_container)).perform(click()) + var actualSelectedTopicsList = ArrayList() + + scenario.onActivity { activity -> + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_topics_completed_container) as MarkTopicsCompletedFragment + actualSelectedTopicsList = + fragment.markTopicsCompletedFragmentPresenter.selectedTopicIdList + } + + scenario.recreate() + + scenario.onActivity { activity -> + val newFragment = activity.supportFragmentManager + .findFragmentById(R.id.mark_topics_completed_container) as MarkTopicsCompletedFragment + val restoredTopicIdList = + newFragment.markTopicsCompletedFragmentPresenter.selectedTopicIdList + + assertThat(restoredTopicIdList).isEqualTo(actualSelectedTopicsList) + } + } + } + private fun createMarkTopicsCompletedTestActivityIntent(internalProfileId: Int): Intent { return MarkTopicsCompletedTestActivity.createMarkTopicsCompletedTestIntent( context, internalProfileId diff --git a/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt index 508d72bdb2a..e378a684dd9 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt @@ -2,6 +2,7 @@ package org.oppia.android.app.help import android.app.Application import android.content.Intent +import android.widget.FrameLayout import androidx.appcompat.app.AppCompatActivity import androidx.drawerlayout.widget.DrawerLayout import androidx.recyclerview.widget.RecyclerView @@ -29,6 +30,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import dagger.Component import org.hamcrest.Matchers.equalTo import org.junit.After @@ -50,6 +52,7 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.faq.FAQListActivity import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity +import org.oppia.android.app.model.HelpFragmentArguments import org.oppia.android.app.model.PoliciesActivityParams import org.oppia.android.app.model.PolicyPage import org.oppia.android.app.model.ProfileId @@ -104,6 +107,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProto import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -1374,6 +1378,34 @@ class HelpFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.help_fragment_placeholder) as HelpFragment + val isMultipane = + activity.findViewById(R.id.multipane_options_container) != null + + val arguments = checkNotNull(fragment.arguments) { + "Expected arguments to be passed to HelpFragment" + } + val args = + arguments.getProto("HelpFragment.arguments", HelpFragmentArguments.getDefaultInstance()) + val receivedIsMultipane = args.isMultipane + + assertThat(receivedIsMultipane).isEqualTo(isMultipane) + } + } + } + private fun ActivityScenario.openNavigationDrawer() { onView(withContentDescription(R.string.drawer_open_content_description)) .check(matches(isCompletelyDisplayed())) diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt index 62749ba3863..074985b485b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt @@ -33,6 +33,7 @@ import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.OppiaLanguage +import org.oppia.android.app.options.AppLanguageFragment.Companion.retrieveLanguageFromArguments import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -95,6 +96,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule import org.oppia.android.util.parser.image.GlideImageLoaderModule import org.oppia.android.util.parser.image.ImageParsingModule +import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import javax.inject.Inject @@ -215,6 +217,50 @@ class AppLanguageFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launch(createAppLanguageActivityIntent(OppiaLanguage.ENGLISH)) + .use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + val appLanguageFragment = activity.supportFragmentManager + .findFragmentById(R.id.app_language_fragment_container) as AppLanguageFragment + val recievedLanguage = appLanguageFragment.arguments?.retrieveLanguageFromArguments() + val receivedProfileId = + appLanguageFragment.arguments?.extractCurrentUserProfileId()?.internalId + + assertThat(recievedLanguage).isEqualTo(OppiaLanguage.ENGLISH) + assertThat(receivedProfileId).isEqualTo(internalProfileId) + } + } + } + + @Test + fun testFragment_saveInstanceState_verifyCorrectStateRestored() { + launch(createAppLanguageActivityIntent(OppiaLanguage.ENGLISH)) + .use { scenario -> + testCoroutineDispatchers.runCurrent() + + scenario.onActivity { activity -> + var appLanguageFragment = activity.supportFragmentManager + .findFragmentById(R.id.app_language_fragment_container) as AppLanguageFragment + appLanguageFragment.appLanguageFragmentPresenter.onLanguageSelected(OppiaLanguage.ARABIC) + } + + scenario.recreate() + + scenario.onActivity { activity -> + val newAppLanguageFragment = activity.supportFragmentManager + .findFragmentById(R.id.app_language_fragment_container) as AppLanguageFragment + val restoredLanguage = + newAppLanguageFragment.appLanguageFragmentPresenter.getLanguageSelected() + + assertThat(restoredLanguage).isEqualTo(OppiaLanguage.ARABIC) + } + } + } + private fun verifyKiswahiliIsSelected(appLanguageActivity: AppLanguageActivity?) { checkSelectedLanguage(index = KISWAHILI_BUTTON_INDEX, expectedLanguageName = "Kiswahili") assertThat(appLanguageActivity?.appLanguageActivityPresenter?.getLanguageSelected()?.name) diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt index 7ad7462af04..b8aed771aaa 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt @@ -39,6 +39,7 @@ import org.oppia.android.app.model.AudioLanguage import org.oppia.android.app.model.AudioLanguage.BRAZILIAN_PORTUGUESE_LANGUAGE import org.oppia.android.app.model.AudioLanguage.ENGLISH_AUDIO_LANGUAGE import org.oppia.android.app.model.AudioLanguage.NIGERIAN_PIDGIN_LANGUAGE +import org.oppia.android.app.options.AudioLanguageFragment.Companion.retrieveLanguageFromArguments import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -117,12 +118,17 @@ class AudioLanguageFragmentTest { private const val NIGERIAN_PIDGIN_BUTTON_INDEX = 4 } - @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule() - @get:Rule val oppiaTestRule = OppiaTestRule() + @get:Rule + val initializeDefaultLocaleRule = InitializeDefaultLocaleRule() + @get:Rule + val oppiaTestRule = OppiaTestRule() - @Inject lateinit var context: Context - @Inject lateinit var profileTestHelper: ProfileTestHelper - @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers + @Inject + lateinit var context: Context + @Inject + lateinit var profileTestHelper: ProfileTestHelper + @Inject + lateinit var testCoroutineDispatchers: TestCoroutineDispatchers @After fun tearDown() { @@ -351,6 +357,52 @@ class AudioLanguageFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + initializeTestApplicationComponent(enableOnboardingFlowV2 = true) + launch( + createDefaultAudioActivityIntent(ENGLISH_AUDIO_LANGUAGE) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + val fragment = activity.supportFragmentManager + .findFragmentById(R.id.audio_language_fragment_container) as AudioLanguageFragment + val receivedAudioLanguage = fragment.arguments?.retrieveLanguageFromArguments() + + assertThat(ENGLISH_AUDIO_LANGUAGE).isEqualTo(receivedAudioLanguage) + } + } + } + + @Test + fun testFragment_saveInstanceState_verifyCorrectStateRestored() { + initializeTestApplicationComponent(enableOnboardingFlowV2 = true) + launch( + createDefaultAudioActivityIntent(ENGLISH_AUDIO_LANGUAGE) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + var language: AudioLanguage? = null + + scenario.onActivity { activity -> + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.audio_language_fragment_container) as AudioLanguageFragment + language = fragment.audioLanguageFragmentPresenterV1.getLanguageSelected() + } + + scenario.recreate() + + scenario.onActivity { activity -> + val newfragment = activity.supportFragmentManager + .findFragmentById(R.id.audio_language_fragment_container) as AudioLanguageFragment + val restoredAudioLanguage = + newfragment.audioLanguageFragmentPresenterV1.getLanguageSelected() + + assertThat(restoredAudioLanguage).isEqualTo(language) + } + } + } + private fun launchActivityWithLanguage( audioLanguage: AudioLanguage ): ActivityScenario { diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt index ed37473683f..382327eb863 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt @@ -23,6 +23,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import dagger.Component import org.hamcrest.Description import org.hamcrest.Matcher @@ -110,6 +111,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule import org.oppia.android.util.parser.image.GlideImageLoaderModule import org.oppia.android.util.parser.image.ImageParsingModule +import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import javax.inject.Inject @@ -343,6 +345,24 @@ class AudioFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + addMediaInfo() + launch( + createAudioFragmentTestIntent(internalProfileId) + ).use { scenario -> + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + val audioFragment = activity.supportFragmentManager + .findFragmentById(R.id.audio_fragment_placeholder) as AudioFragment + val receivedProfileId = audioFragment.arguments?.extractCurrentUserProfileId() + + assertThat(receivedProfileId).isEqualTo(profileId) + } + } + } + private fun withSeekBarPosition(position: Int) = object : TypeSafeMatcher() { override fun describeTo(description: Description) { description.appendText("SeekBar with progress same as $position") diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditFragmentTest.kt index 37992371629..811072493a6 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditFragmentTest.kt @@ -45,6 +45,8 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.devoptions.markchapterscompleted.MarkChaptersCompletedActivity import org.oppia.android.app.devoptions.markchapterscompleted.MarkChaptersCompletedActivity.Companion.MARK_CHAPTERS_COMPLETED_ACTIVITY_PARAMS import org.oppia.android.app.model.MarkChaptersCompletedActivityParams +import org.oppia.android.app.model.ProfileEditActivityParams +import org.oppia.android.app.model.ProfileEditFragmentArguments import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -100,6 +102,8 @@ import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule import org.oppia.android.util.data.DataProviders.Companion.toLiveData +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -473,6 +477,36 @@ class ProfileEditFragmentTest { assertThat(profile.allowInLessonQuickLanguageSwitching).isTrue() } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launchFragmentTestActivity(internalProfileId = 1).use { scenario -> + scenario.onActivity { activity -> + + val activityArgs = activity.intent.getProtoExtra( + ProfileEditActivity.PROFILE_EDIT_ACTIVITY_PARAMS_KEY, + ProfileEditActivityParams.getDefaultInstance() + ) + val isMultipane = activityArgs?.isMultipane ?: false + + val fragment = activity.supportFragmentManager + .findFragmentById(R.id.profile_edit_fragment_placeholder) as ProfileEditFragment + + val arguments = checkNotNull(fragment.arguments) { + "Expected variables to be passed to ProfileEditFragment" + } + val args = arguments.getProto( + ProfileEditFragment.PROFILE_EDIT_FRAGMENT_ARGUMENTS_KEY, + ProfileEditFragmentArguments.getDefaultInstance() + ) + val receivedInternalProfileId = args.internalProfileId + val receivedIsMultipane = args.isMultipane + + assertThat(receivedInternalProfileId).isEqualTo(1) + assertThat(receivedIsMultipane).isEqualTo(isMultipane) + } + } + } + private fun launchFragmentTestActivity(internalProfileId: Int) = launch( createProfileEditFragmentTestActivity(context, internalProfileId) diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt index 1e2bc4791a7..5e6a627b086 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt @@ -19,6 +19,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import dagger.Component import org.hamcrest.Matchers.allOf import org.junit.After @@ -39,7 +40,9 @@ import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseListActivity +import org.oppia.android.app.help.thirdparty.LicenseListFragment import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity +import org.oppia.android.app.model.LicenseListFragmentArguments import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.shim.ViewBindingShimModule @@ -87,6 +90,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProto import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -340,6 +344,32 @@ class LicenseListFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launch(createLicenseListActivity(2)).use { scenario -> + + testCoroutineDispatchers.runCurrent() + scenario.onActivity { activity -> + + var fragment = activity.supportFragmentManager + .findFragmentById(R.id.license_list_fragment_placeholder) as LicenseListFragment + + val arguments = checkNotNull(fragment.arguments) { + "Expected arguments to be passed to LicenseListFragment" + } + val args = arguments.getProto( + "LicenseListFragment.arguments", + LicenseListFragmentArguments.getDefaultInstance() + ) + val receivedDependencyIndex = args.dependencyIndex + val receivedIsMultipane = args.isMultipane + + assertThat(receivedDependencyIndex).isEqualTo(2) + assertThat(receivedIsMultipane).isEqualTo(false) + } + } + } + private fun createLicenseListActivity(dependencyIndex: Int): Intent { return LicenseListActivity.createLicenseListActivityIntent( ApplicationProvider.getApplicationContext(), diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt index c8ec2292371..ac21622d80e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt @@ -56,6 +56,7 @@ import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.fragment.InjectableDialogFragment +import org.oppia.android.app.model.ConceptCardFragmentArguments import org.oppia.android.app.model.OppiaLanguage import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.WrittenTranslationLanguageSelection @@ -116,6 +117,7 @@ import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.LoadImagesFromAssets import org.oppia.android.util.caching.LoadLessonProtosFromAssets +import org.oppia.android.util.extensions.getProto import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -127,6 +129,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule import org.oppia.android.util.parser.image.GlideImageLoaderModule import org.oppia.android.util.parser.image.ImageParsingModule +import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import javax.inject.Inject @@ -492,6 +495,38 @@ class ConceptCardFragmentTest { } } + @Test + fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() { + launchTestActivity().use { scenario -> + scenario.onActivity { activity -> + + ConceptCardFragment.bringToFrontOrCreateIfNew( + TEST_SKILL_ID_0, + profileId, + activity.supportFragmentManager + ) + val fragmentSkill0 = + activity.supportFragmentManager.fragments.filterIsInstance().single() + + val arguments = checkNotNull(fragmentSkill0.arguments) { + "Expected arguments to be passed to ConceptCardFragment" + } + val args = arguments.getProto( + ConceptCardFragment.CONCEPT_CARD_FRAGMENT_ARGUMENTS_KEY, + ConceptCardFragmentArguments.getDefaultInstance() + ) + val skillId = + checkNotNull(args.skillId) { + "Expected skillId to be passed to ConceptCardFragment" + } + val receivedProfileId = arguments.extractCurrentUserProfileId() + + assertThat(skillId).isEqualTo(TEST_SKILL_ID_0) + assertThat(receivedProfileId).isEqualTo(profileId) + } + } + } + private fun launchTestActivity(): ActivityScenario { val scenario = ActivityScenario.launch( ConceptCardFragmentTestActivity.createIntent(context, profileId)