Skip to content

Commit

Permalink
Fix part of #5485: Create means for verifying Fragment Arguments (#5606)
Browse files Browse the repository at this point in the history
<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
Fix part of #5485

Added tests for 11 fragment arguments and 'saveInstanceState'.

I have not added tests for the following:

 1. onSaveInstanceState of StateFragment.
 2. OptionsFragment.
 
Problems:

1. When trying to recreate StateFragment, an error occurs: "State has
not been initialized."
2. In the OptionsFragmentTest class, when I try to run the test on
Robolectric, it shows "No tests were found.

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [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: ...".)
- [ ] 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
<!-- Delete these section if this PR does not include UI-related
changes. -->
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: Sneha Datta <[email protected]>
Co-authored-by: Adhiambo Peres <[email protected]>
Co-authored-by: Mr. 17 <[email protected]>
Co-authored-by: Ben Henning <[email protected]>
Co-authored-by: RD Rama Devi <[email protected]>
Co-authored-by: Tobiloba Oyelekan <[email protected]>
  • Loading branch information
7 people authored Jan 21, 2025
1 parent fc92932 commit f3c6dff
Show file tree
Hide file tree
Showing 15 changed files with 552 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ class LicenseTextViewerFragment : InjectableFragment() {

companion object {
/** Argument key for LicenseTextViewerFragment. */
private const val LICENSE_TEXT_VIEWER_FRAGMENT_ARGUMENTS_KEY =
"LicenseTextViewerFragment.arguments"
const val LICENSE_TEXT_VIEWER_FRAGMENT_ARGUMENTS_KEY = "LicenseTextViewerFragment.arguments"

/** Returns an instance of [LicenseTextViewerFragment]. */
fun newInstance(dependencyIndex: Int, licenseIndex: Int): LicenseTextViewerFragment {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.extensions.putProto
import javax.inject.Inject

private const val POLICIES_FRAGMENT_POLICY_PAGE_ARGUMENT_PROTO = "PoliciesFragment.policy_page"
/** Argument key for PoliciesFragment. */
const val POLICIES_FRAGMENT_POLICY_PAGE_ARGUMENT_PROTO = "PoliciesFragment.policy_page"

/** Fragment that contains policies flow of the app. */
class PoliciesFragment : InjectableFragment() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.view.ViewParent
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.NestedScrollView
import androidx.drawerlayout.widget.DrawerLayout
import androidx.test.core.app.ActivityScenario.launch
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
Expand All @@ -23,6 +24,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isClickable
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.util.HumanReadables
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import dagger.Component
import org.hamcrest.Matcher
import org.hamcrest.Matchers
Expand All @@ -44,6 +46,7 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule
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.AdministratorControlsFragmentArguments
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.scrollToPosition
Expand Down Expand Up @@ -98,6 +101,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.LoggerModule
Expand Down Expand Up @@ -433,6 +437,35 @@ class AdministratorControlsFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<AdministratorControlsFragmentTestActivity>(
createAdministratorControlsFragmentTestActivityIntent(
profileId = internalProfileId
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val administratorControlsFragment = activity.supportFragmentManager
.findFragmentById(R.id.administrator_controls_fragment_test_activity_fragment_container)
as AdministratorControlsFragment
val isMultipane = activity
.findViewById<DrawerLayout>(R.id.administrator_controls_activity_drawer_layout) != null

val arguments = checkNotNull(administratorControlsFragment.arguments) {
"Expected arguments to be passed to AdministratorControlsFragment"
}.getProto(
ADMINISTRATOR_CONTROLS_FRAGMENT_ARGUMENTS_KEY,
AdministratorControlsFragmentArguments.getDefaultInstance()
)
val receivedIsMultipane = arguments.isMultipane

assertThat(receivedIsMultipane).isEqualTo(isMultipane)
}
}
}

private fun clickAutoUpdateTopicContainer() {
onView(
atPositionOnView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ import org.oppia.android.util.networking.NetworkConnectionDebugUtilModule
import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule
import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule
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
Expand Down Expand Up @@ -1649,6 +1650,31 @@ class RecentlyPlayedFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
ActivityScenario.launch<RecentlyPlayedActivity>(
createRecentlyPlayedActivityIntent(
internalProfileId = internalProfileId,
RecentlyPlayedActivityTitle.STORIES_FOR_YOU
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val recentlyPlayedFragment = activity.supportFragmentManager
.findFragmentById(R.id.recently_played_fragment_placeholder) as RecentlyPlayedFragment

val arguments = checkNotNull(recentlyPlayedFragment.arguments) {
"Expected arguments to be passed to RecentlyPlayedFragment"
}
val profileId = arguments.extractCurrentUserProfileId()
val receivedInternalProfileId = profileId.internalId

assertThat(receivedInternalProfileId).isEqualTo(internalProfileId)
}
}
}

private fun setUpTestFragment(activity: RecentlyPlayedActivity) {
activity.supportFragmentManager
.beginTransaction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.oppia.android.app.options
import android.app.Application
import android.content.Context
import android.content.Intent
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import androidx.test.core.app.ActivityScenario
Expand All @@ -21,6 +22,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.Matchers.allOf
import org.junit.After
Expand All @@ -44,6 +46,7 @@ import org.oppia.android.app.model.AppLanguageActivityParams
import org.oppia.android.app.model.AudioLanguage
import org.oppia.android.app.model.AudioLanguageActivityParams
import org.oppia.android.app.model.OppiaLanguage
import org.oppia.android.app.model.OptionsFragmentArguments
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.ReadingTextSize
import org.oppia.android.app.model.ReadingTextSizeActivityParams
Expand Down Expand Up @@ -99,6 +102,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.LoggerModule
Expand Down Expand Up @@ -559,6 +563,39 @@ class OptionsFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<OptionsActivity>(
createOptionActivityIntent(
internalProfileId = 0,
isFromNavigationDrawer = true
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val optionsFragment = activity.supportFragmentManager
.findFragmentById(R.id.options_fragment_placeholder) as OptionsFragment

val args = optionsFragment.arguments?.getProto(
OPTIONS_FRAGMENT_ARGUMENTS_KEY,
OptionsFragmentArguments.getDefaultInstance()
)

val isMultipane =
activity.findViewById<FrameLayout>(R.id.multipane_options_container) != null

val receivedIsMultipane = args?.isMultipane
val receivedIsFirstOpen = args?.isFirstOpen
val receivedSelectedFragment = checkNotNull(args?.selectedFragment)

assertThat(receivedIsMultipane).isEqualTo(isMultipane)
assertThat(receivedIsFirstOpen).isEqualTo(true)
assertThat(receivedSelectedFragment).isEqualTo(READING_TEXT_SIZE_FRAGMENT)
}
}
}

private fun rotateToLandscape() {
onView(isRoot()).perform(orientationLandscape())
testCoroutineDispatchers.runCurrent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ 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.model.ProfileId
import org.oppia.android.app.model.StateFragmentArguments
import org.oppia.android.app.model.WrittenTranslationLanguageSelection
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel
Expand Down Expand Up @@ -178,6 +179,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.LoggerModule
Expand Down Expand Up @@ -5238,6 +5240,38 @@ class StateFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
setUpTestWithLanguageSwitchingFeatureOff()
launchForExploration(
FRACTIONS_EXPLORATION_ID_1,
shouldSavePartialProgress = false
).use { scenario ->
startPlayingExploration()

scenario.onActivity { activity ->
val stateFragment = activity.supportFragmentManager
.findFragmentById(R.id.state_fragment_placeholder) as StateFragment

val args =
stateFragment.arguments?.getProto(
StateFragment.STATE_FRAGMENT_ARGUMENTS_KEY,
StateFragmentArguments.getDefaultInstance()
)

val receivedInternalProfileId = args?.internalProfileId ?: -1
val receivedTopicId = args?.topicId!!
val receivedStoryId = args.storyId!!
val reveivedExplorationId = args.explorationId!!

assertThat(receivedInternalProfileId).isEqualTo(profileId.internalId)
assertThat(receivedTopicId).isEqualTo(TEST_TOPIC_ID_0)
assertThat(receivedStoryId).isEqualTo(TEST_STORY_ID_0)
assertThat(reveivedExplorationId).isEqualTo(FRACTIONS_EXPLORATION_ID_1)
}
}
}

private fun playThroughRatioExplorationState1() {
clickContinueInteractionButton()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule
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.PoliciesActivityParams
import org.oppia.android.app.model.PoliciesFragmentArguments
import org.oppia.android.app.model.PolicyPage
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
Expand Down Expand Up @@ -101,6 +103,8 @@ 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.extensions.getProtoExtra
import org.oppia.android.util.gcsresource.DefaultResourceBucketName
import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
Expand Down Expand Up @@ -324,6 +328,44 @@ class PoliciesFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<PoliciesFragmentTestActivity>(
createPoliciesFragmentTestIntent(
getApplicationContext(),
PolicyPage.TERMS_OF_SERVICE
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val policiesFragment = activity.supportFragmentManager
.findFragmentById(R.id.policies_fragment_placeholder) as PoliciesFragment

val policiesActivityParams = activity.intent.getProtoExtra(
PoliciesFragmentTestActivity.POLICIES_FRAGMENT_TEST_POLICY_PAGE_PARAMS_PROTO,
PoliciesActivityParams.getDefaultInstance()
)
val policiesFragmentArguments =
PoliciesFragmentArguments
.newBuilder()
.setPolicyPage(policiesActivityParams.policyPage)
.build()

val args = checkNotNull(policiesFragment.arguments) {
"Expected arguments to be passed to PoliciesFragment"
}
val receivedPolicies =
args.getProto(
POLICIES_FRAGMENT_POLICY_PAGE_ARGUMENT_PROTO,
PoliciesFragmentArguments.getDefaultInstance()
)

assertThat(receivedPolicies.policyPage).isEqualTo(policiesFragmentArguments.policyPage)
}
}
}

private fun setUpTestApplicationComponent() {
getApplicationContext<TestApplication>().inject(this)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,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.oppia.android.util.profile.PROFILE_ID_INTENT_DECORATOR
import org.robolectric.annotation.Config
import org.robolectric.annotation.LooperMode
Expand Down Expand Up @@ -825,6 +826,27 @@ class ProfileProgressFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<ProfileProgressActivity>(
createProfileProgressActivityIntent(internalProfileId)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val profileProgressFragment = activity.supportFragmentManager
.findFragmentById(R.id.profile_progress_fragment_placeholder) as ProfileProgressFragment

val args = checkNotNull(profileProgressFragment.arguments) {
"Expected arguments to be passed to ProfileProgressFragment"
}
val receivedInternalProfileId = args.extractCurrentUserProfileId().internalId

assertThat(receivedInternalProfileId).isEqualTo(internalProfileId)
}
}
}

private fun createGalleryPickActivityResultStub(): Instrumentation.ActivityResult {
val resources: Resources = context.resources
val imageUri = Uri.parse(
Expand Down
Loading

0 comments on commit f3c6dff

Please sign in to comment.