Skip to content

Commit

Permalink
Fix #5485 Create means for verifying Fragment Arguments (#5527)
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
Fixes #5485
Added test for 10 fragments arguments and saveInstanceState.

## 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: Mr. 17 <[email protected]>
  • Loading branch information
subhajitxyz and theMr17 authored Sep 16, 2024
1 parent c82b71b commit 65197bf
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class ReadingTextSizeFragment : InjectableFragment(), TextSizeRadioButtonListene
readingTextSizeFragmentPresenter.onTextSizeSelected(selectedTextSize)
}

private fun retrieveFragmentArguments(): ReadingTextSizeFragmentArguments {
/** Returns the [ReadingTextSizeFragmentArguments] stored in the fragment's arguments. */
fun retrieveFragmentArguments(): ReadingTextSizeFragmentArguments {
return checkNotNull(arguments) {
"Expected arguments to be passed to ReadingTextSizeFragment"
}.getProto(FRAGMENT_ARGUMENTS_KEY, ReadingTextSizeFragmentArguments.getDefaultInstance())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isChecked
import androidx.test.espresso.matcher.ViewMatchers.isRoot
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.TypeSafeMatcher
Expand All @@ -37,6 +38,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.ProfileId
import org.oppia.android.app.model.ReadingTextSize.MEDIUM_TEXT_SIZE
import org.oppia.android.app.model.ReadingTextSize.SMALL_TEXT_SIZE
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView
Expand Down Expand Up @@ -194,6 +196,47 @@ class ReadingTextSizeFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
launch<ReadingTextSizeActivity>(createReadingTextSizeActivityIntent()).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val readingTextSizeFragment = activity.supportFragmentManager
.findFragmentById(R.id.reading_text_size_container) as ReadingTextSizeFragment
val receivedReadingTextSize = readingTextSizeFragment.retrieveFragmentArguments()
.readingTextSize

assertThat(receivedReadingTextSize).isEqualTo(SMALL_TEXT_SIZE)
}
}
}

@Test
fun testFragment_saveInstanceState_verifyCorrectStateRestored() {
launch<ReadingTextSizeActivity>(createReadingTextSizeActivityIntent()).use { scenario ->
testCoroutineDispatchers.runCurrent()

scenario.onActivity { activity ->
val readingTextSizeFragment = activity.supportFragmentManager
.findFragmentById(R.id.reading_text_size_container) as ReadingTextSizeFragment
readingTextSizeFragment.readingTextSizeFragmentPresenter
.onTextSizeSelected(MEDIUM_TEXT_SIZE)
}

scenario.recreate()

scenario.onActivity { activity ->
val newReadingTextSizeFragment = activity.supportFragmentManager
.findFragmentById(R.id.reading_text_size_container) as ReadingTextSizeFragment
val restoredTopicIdList =
newReadingTextSizeFragment.readingTextSizeFragmentPresenter.getTextSizeSelected()

assertThat(restoredTopicIdList).isEqualTo(MEDIUM_TEXT_SIZE)
}
}
}

private fun createReadingTextSizeActivityIntent() =
ReadingTextSizeActivity.createReadingTextSizeActivityIntent(context, SMALL_TEXT_SIZE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.oppia.android.app.model.ExplorationActivityParams
import org.oppia.android.app.model.ExplorationCheckpoint
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.ReadingTextSize
import org.oppia.android.app.model.ResumeLessonFragmentArguments
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule
Expand Down Expand Up @@ -99,6 +100,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
Expand Down Expand Up @@ -273,6 +275,41 @@ class ResumeLessonFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
launch<ResumeLessonActivity>(createResumeLessonActivityIntent()).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val resumeLessonFragment = activity.supportFragmentManager
.findFragmentById(R.id.resume_lesson_fragment_placeholder) as ResumeLessonFragment
val args = checkNotNull(resumeLessonFragment.arguments) {
"Expected arguments to be provided for fragment."
}.getProto(
ResumeLessonFragment.RESUME_LESSON_FRAGMENT_ARGUMENTS_KEY,
ResumeLessonFragmentArguments.getDefaultInstance()
)
val receivedProfileId = args.profileId
val receivedClassroomId = args.classroomId
val receivedTopicId = args.topicId
val receivedStoryId = args.storyId
val receivedExplorationId = args.explorationId
val receivedParentScreen = args.parentScreen
val receivedCheckpoint = args.checkpoint

assertThat(receivedProfileId)
.isEqualTo(ProfileId.newBuilder().apply { internalId = 1 }.build())
assertThat(receivedClassroomId).isEqualTo(TEST_CLASSROOM_ID_1)
assertThat(receivedTopicId).isEqualTo(FRACTIONS_TOPIC_ID)
assertThat(receivedStoryId).isEqualTo(FRACTIONS_STORY_ID_0)
assertThat(receivedExplorationId).isEqualTo(FRACTIONS_EXPLORATION_ID_0)
assertThat(receivedParentScreen)
.isEqualTo(ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED)
assertThat(receivedCheckpoint).isEqualTo(ExplorationCheckpoint.getDefaultInstance())
}
}
}

private fun createResumeLessonActivityIntent(): Intent {
return ResumeLessonActivity.createResumeLessonActivityIntent(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,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.not
import org.junit.After
Expand All @@ -37,6 +38,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.ProfileListFragmentArguments
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView
Expand Down Expand Up @@ -86,6 +88,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
Expand Down Expand Up @@ -367,6 +370,30 @@ class ProfileListFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
profileTestHelper.initializeProfiles()
launch(ProfileListActivity::class.java).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val profileListFragment = activity.supportFragmentManager
.findFragmentById(R.id.profile_list_container) as ProfileListFragment

val arguments = checkNotNull(profileListFragment.arguments) {
"Expected variables to be passed to ProfileListFragment"
}
val args = arguments.getProto(
ProfileListFragment.PROFILE_LIST_FRAGMENT_ARGUMENTS_KEY,
ProfileListFragmentArguments.getDefaultInstance()
)
val receivedIsMultipane = args.isMultipane

assertThat(receivedIsMultipane).isEqualTo(false)
}
}
}

// TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them.
@Singleton
@Component(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.google.common.truth.Truth.assertThat
import dagger.Component
import org.hamcrest.CoreMatchers.not
import org.hamcrest.core.AllOf.allOf
Expand Down Expand Up @@ -102,6 +103,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
Expand Down Expand Up @@ -441,6 +443,30 @@ class ProfileRenameFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
ActivityScenario.launch<ProfileRenameActivity>(
ProfileRenameActivity.createProfileRenameActivity(
context = context,
internalProfileId = 1
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val profileRenameFragment = activity.supportFragmentManager
.findFragmentById(R.id.profile_rename_fragment_placeholder) as ProfileRenameFragment
val args =
checkNotNull(profileRenameFragment.arguments) {
"Expected arguments to be passed to ProfileRenameFragment"
}
val receivedProfileId = args.extractCurrentUserProfileId().internalId

assertThat(receivedProfileId).isEqualTo(1)
}
}
}

// TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them.
@Singleton
@Component(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.google.common.truth.Truth.assertThat
import dagger.Component
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.not
Expand All @@ -42,6 +43,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.ProfileResetPinFragmentArguments
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule
Expand Down Expand Up @@ -92,6 +94,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
Expand Down Expand Up @@ -1006,6 +1009,70 @@ class ProfileResetPinFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
ActivityScenario.launch<ProfileResetPinActivity>(
ProfileResetPinActivity.createProfileResetPinActivity(
context = context,
profileId = 0,
isAdmin = true
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val profileResetPinFragment = activity.supportFragmentManager
.findFragmentById(R.id.profile_reset_pin_fragment_placeholder) as ProfileResetPinFragment

val arguments = checkNotNull(profileResetPinFragment.arguments) {
"Expected arguments to be passed to ProfileResetPinFragment"
}
val args =
arguments.getProto(
ProfileResetPinFragment.PROFILE_RESET_PIN_FRAGMENT_ARGUMENTS_KEY,
ProfileResetPinFragmentArguments.getDefaultInstance()
)
val receivedProfileResetPinProfileId = args.internalProfileId
val receivedProfileResetPinIsAdmin = args.isAdmin

assertThat(receivedProfileResetPinProfileId).isEqualTo(0)
assertThat(receivedProfileResetPinIsAdmin).isEqualTo(true)
}
}
}

@Test
fun testFragment_fragmentLoaded_whenIsAdminFalse_verifyCorrectArgumentsPassed() {
ActivityScenario.launch<ProfileResetPinActivity>(
ProfileResetPinActivity.createProfileResetPinActivity(
context = context,
profileId = 0,
isAdmin = false
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val profileResetPinFragment = activity.supportFragmentManager
.findFragmentById(R.id.profile_reset_pin_fragment_placeholder) as ProfileResetPinFragment

val arguments = checkNotNull(profileResetPinFragment.arguments) {
"Expected arguments to be passed to ProfileResetPinFragment"
}
val args =
arguments.getProto(
ProfileResetPinFragment.PROFILE_RESET_PIN_FRAGMENT_ARGUMENTS_KEY,
ProfileResetPinFragmentArguments.getDefaultInstance()
)
val receivedProfileResetPinProfileId = args.internalProfileId
val receivedProfileResetPinIsAdmin = args.isAdmin

assertThat(receivedProfileResetPinProfileId).isEqualTo(0)
assertThat(receivedProfileResetPinIsAdmin).isEqualTo(false)
}
}
}

// TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them.
@Singleton
@Component(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
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.junit.After
import org.junit.Before
Expand Down Expand Up @@ -93,6 +94,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 @@ -339,6 +341,25 @@ class SpotlightFragmentTest {
}
}

@Test
fun testFragment_fragmentLoaded_verifyCorrectArgumentsPassed() {
TestPlatformParameterModule.forceEnableSpotlightUi(true)
launch<SpotlightFragmentTestActivity>(
createSpotlightFragmentTestActivity(context)
).use { scenario ->
testCoroutineDispatchers.runCurrent()

scenario.onActivity { activity ->
val spotlightFragment = activity.supportFragmentManager
.findFragmentByTag(SpotlightManager.SPOTLIGHT_FRAGMENT_TAG) as SpotlightFragment
val receivedInternalProfileId = spotlightFragment
.arguments?.extractCurrentUserProfileId()?.internalId ?: -1

assertThat(receivedInternalProfileId).isEqualTo(0)
}
}
}

private fun setUpTestApplicationComponent() {
ApplicationProvider.getApplicationContext<TestApplication>().inject(this)
}
Expand Down
Loading

0 comments on commit 65197bf

Please sign in to comment.