diff --git a/app/src/main/java/org/oppia/android/app/drawer/Argument.kt b/app/src/main/java/org/oppia/android/app/drawer/Argument.kt new file mode 100644 index 00000000000..51b99699c8e --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/drawer/Argument.kt @@ -0,0 +1,6 @@ +package org.oppia.android.app.drawer + +sealed class Argument { + class LastCheckedMenuItem(val navigationDrawerItem: NavigationDrawerItem) : Argument() + class IsAdministratorControlsSelected(val value: Boolean) : Argument() +} diff --git a/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogFragment.kt b/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogFragment.kt index 66b005b4622..9a0fa991927 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogFragment.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogFragment.kt @@ -8,42 +8,76 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.view.ContextThemeWrapper import androidx.fragment.app.DialogFragment import org.oppia.android.R +import org.oppia.android.app.model.ExitProfileDialogArguments import org.oppia.android.app.profile.ProfileChooserActivity +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.putProto /** [DialogFragment] that gives option to either cancel or exit current profile. */ class ExitProfileDialogFragment : DialogFragment() { companion object { // TODO(#1655): Re-restrict access to fields in tests post-Gradle. - const val BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY = - "BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY" + const val EXIT_PROFILE_DIALOG_ARGUMENTS_PROTO = "EXIT_PROFILE_DIALOG_ARGUMENTS_PROTO" /** * This function is responsible for displaying content in DialogFragment. * * @return [ExitProfileDialogFragment]: DialogFragment */ - fun newInstance(isFromNavigationDrawer: Boolean): ExitProfileDialogFragment { + fun newInstance( + restoreLastCheckedMenuItem: Boolean, + argument: Argument + ): ExitProfileDialogFragment { val exitProfileDialogFragment = ExitProfileDialogFragment() val args = Bundle() - args.putBoolean(BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY, isFromNavigationDrawer) + val exitProfileDialogArguments = createExitProfileDialogFragmentProto( + argument = argument, + restoreLastCheckedMenuItem = restoreLastCheckedMenuItem + ) + + args.putProto(EXIT_PROFILE_DIALOG_ARGUMENTS_PROTO, exitProfileDialogArguments) + exitProfileDialogFragment.arguments = args return exitProfileDialogFragment } + + private fun createExitProfileDialogFragmentProto( + argument: Argument, + restoreLastCheckedMenuItem: Boolean + ): ExitProfileDialogArguments { + return when (argument) { + is Argument.IsAdministratorControlsSelected -> { + ExitProfileDialogArguments.newBuilder() + .setRestoreLastCheckedMenuItem(restoreLastCheckedMenuItem) + .setIsAdministratorControlsSelected(argument.value) + .build() + } + is Argument.LastCheckedMenuItem -> { + ExitProfileDialogArguments.newBuilder() + .setRestoreLastCheckedMenuItem(restoreLastCheckedMenuItem) + .setLastCheckedMenuItemValue(argument.navigationDrawerItem.value) + .build() + } + } + } } - lateinit var exitProfileDialogInterface: ExitProfileDialogInterface + private lateinit var exitProfileDialogInterface: ExitProfileDialogInterface override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val args = checkNotNull(arguments) { "Expected arguments to be pass to ExitProfileDialogFragment" } - val isFromNavigationDrawer = args.getBoolean( - BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY, - false + val exitProfileDialogArguments = args.getProto( + EXIT_PROFILE_DIALOG_ARGUMENTS_PROTO, + ExitProfileDialogArguments.getDefaultInstance() ) - if (isFromNavigationDrawer) { + val restoreLastCheckedMenuItem = exitProfileDialogArguments.restoreLastCheckedMenuItem + val argument = exitProfileDialogArguments.adminControlsOrNavDrawerItemsCase + + if (restoreLastCheckedMenuItem) { exitProfileDialogInterface = parentFragment as ExitProfileDialogInterface } @@ -52,19 +86,42 @@ class ExitProfileDialogFragment : DialogFragment() { .Builder(ContextThemeWrapper(activity as Context, R.style.AlertDialogTheme)) .setMessage(R.string.home_activity_back_dialog_message) .setNegativeButton(R.string.home_activity_back_dialog_cancel) { dialog, _ -> - if (isFromNavigationDrawer) { - exitProfileDialogInterface.markHomeMenuCloseDrawer() + if (restoreLastCheckedMenuItem) { + exitProfileDialogInterface.checkLastCheckedItemAndCloseDrawer( + when (argument.number) { + 2 -> Argument.IsAdministratorControlsSelected( + exitProfileDialogArguments.isAdministratorControlsSelected + ) + else -> Argument.LastCheckedMenuItem( + getNavigationDrawerItem( + exitProfileDialogArguments.lastCheckedMenuItemValue + ) + ) + } + ) + exitProfileDialogInterface.unCheckSwitchProfileItemAndCloseDrawer() } dialog.dismiss() } .setPositiveButton(R.string.home_activity_back_dialog_exit) { _, _ -> // TODO(#322): Need to start intent for ProfileChooserActivity to get update. Change to finish when live data bug is fixed. val intent = ProfileChooserActivity.createProfileChooserActivity(activity!!) - if (!isFromNavigationDrawer) { + if (!restoreLastCheckedMenuItem) { intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } activity!!.startActivity(intent) } .create() } + + private fun getNavigationDrawerItem(value: Int): NavigationDrawerItem { + return when (value) { + 0 -> NavigationDrawerItem.HOME + 1 -> NavigationDrawerItem.OPTIONS + 2 -> NavigationDrawerItem.HELP + 3 -> NavigationDrawerItem.DOWNLOADS + 4 -> NavigationDrawerItem.SWITCH_PROFILE + else -> NavigationDrawerItem.HOME + } + } } diff --git a/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogInterface.kt b/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogInterface.kt index 3fbbcc4daab..2b23e650a0f 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogInterface.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/ExitProfileDialogInterface.kt @@ -2,5 +2,7 @@ package org.oppia.android.app.drawer /** Interface to handle option selection in [ExitProfileDialogFragment]. */ interface ExitProfileDialogInterface { - fun markHomeMenuCloseDrawer() + fun checkLastCheckedItemAndCloseDrawer(argument: Argument) + + fun unCheckSwitchProfileItemAndCloseDrawer() } diff --git a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt index cad40d9d4a2..84067bbcffb 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt @@ -40,7 +40,11 @@ class NavigationDrawerFragment : navigationDrawerFragmentPresenter.openProfileProgress(profileId) } - override fun markHomeMenuCloseDrawer() { - navigationDrawerFragmentPresenter.markHomeMenuCloseDrawer() + override fun checkLastCheckedItemAndCloseDrawer(argument: Argument) { + navigationDrawerFragmentPresenter.checkLastCheckedItemAndCloseDrawer(argument) + } + + override fun unCheckSwitchProfileItemAndCloseDrawer() { + navigationDrawerFragmentPresenter.uncheckSwitchProfileItemAndCloseDrawer() } } diff --git a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt index 7032676f0e8..1ac6ce94c4e 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt @@ -59,7 +59,7 @@ class NavigationDrawerFragmentPresenter @Inject constructor( private var previousMenuItemId: Int? = null private var internalProfileId: Int = -1 - fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { + fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View { binding = DrawerFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) binding.fragmentDrawerNavView.setNavigationItemSelectedListener(this) @@ -105,9 +105,7 @@ class NavigationDrawerFragmentPresenter @Inject constructor( return@setOnClickListener } - binding.fragmentDrawerNavView.menu.forEach { menuItem -> - menuItem.isCheckable = false - } + uncheckAllMenuItemsWhenAdministratorControlsIsChecked() drawerLayout.closeDrawers() getFooterViewModel().isAdministratorControlsSelected.set(true) @@ -199,7 +197,6 @@ class NavigationDrawerFragmentPresenter @Inject constructor( } private fun openActivityByMenuItemId(menuItemId: Int) { - getFooterViewModel().isAdministratorControlsSelected.set(false) if (previousMenuItemId != menuItemId) { when (NavigationDrawerItem.valueFromNavId(menuItemId)) { NavigationDrawerItem.HOME -> { @@ -244,8 +241,30 @@ class NavigationDrawerFragmentPresenter @Inject constructor( if (previousFragment != null) { fragment.childFragmentManager.beginTransaction().remove(previousFragment).commitNow() } + val argument: Argument = + if (getFooterViewModel().isAdministratorControlsSelected.get() == true) { + getFooterViewModel().isAdministratorControlsSelected.set(false) + Argument.IsAdministratorControlsSelected(value = true) + } else { + Argument.LastCheckedMenuItem( + navigationDrawerItem = when (previousMenuItemId) { + 0 -> NavigationDrawerItem.HOME + 1 -> NavigationDrawerItem.OPTIONS + 2 -> NavigationDrawerItem.HELP + 3 -> NavigationDrawerItem.DOWNLOADS + 4 -> NavigationDrawerItem.SWITCH_PROFILE + else -> NavigationDrawerItem.HOME + } + ) + } + binding.fragmentDrawerNavView.menu.getItem( + NavigationDrawerItem.SWITCH_PROFILE.ordinal + ).isChecked = true val dialogFragment = ExitProfileDialogFragment - .newInstance(isFromNavigationDrawer = true) + .newInstance( + restoreLastCheckedMenuItem = true, + argument = argument + ) dialogFragment.showNow(fragment.childFragmentManager, TAG_SWITCH_PROFILE_DIALOG) } } @@ -263,12 +282,31 @@ class NavigationDrawerFragmentPresenter @Inject constructor( ) } - fun markHomeMenuCloseDrawer() { + fun checkLastCheckedItemAndCloseDrawer(argument: Argument) { + when (argument) { + is Argument.IsAdministratorControlsSelected -> { + getFooterViewModel().isAdministratorControlsSelected.set(argument.value) + uncheckAllMenuItemsWhenAdministratorControlsIsChecked() + } + is Argument.LastCheckedMenuItem -> { + binding.fragmentDrawerNavView.menu + .getItem(argument.navigationDrawerItem.ordinal).isChecked = true + } + } + drawerLayout.closeDrawers() + } + + fun uncheckSwitchProfileItemAndCloseDrawer() { binding.fragmentDrawerNavView.menu.getItem( - NavigationDrawerItem.HOME.ordinal + NavigationDrawerItem.SWITCH_PROFILE.ordinal ).isChecked = - true - drawerLayout.closeDrawers() + false + } + + private fun uncheckAllMenuItemsWhenAdministratorControlsIsChecked() { + binding.fragmentDrawerNavView.menu.forEach { item -> + item.isCheckable = false + } } /** @@ -345,6 +383,7 @@ class NavigationDrawerFragmentPresenter @Inject constructor( } else { // For showing navigation drawer in AdministratorControlsActivity getFooterViewModel().isAdministratorControlsSelected.set(true) + uncheckAllMenuItemsWhenAdministratorControlsIsChecked() this.drawerLayout = drawerLayout drawerToggle = object : ActionBarDrawerToggle( fragment.activity, diff --git a/app/src/main/java/org/oppia/android/app/home/HomeActivity.kt b/app/src/main/java/org/oppia/android/app/home/HomeActivity.kt index 164af1622e7..745445e1887 100644 --- a/app/src/main/java/org/oppia/android/app/home/HomeActivity.kt +++ b/app/src/main/java/org/oppia/android/app/home/HomeActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import org.oppia.android.R import org.oppia.android.app.activity.InjectableAppCompatActivity +import org.oppia.android.app.drawer.Argument import org.oppia.android.app.drawer.ExitProfileDialogFragment import org.oppia.android.app.drawer.KEY_NAVIGATION_PROFILE_ID import org.oppia.android.app.drawer.TAG_SWITCH_PROFILE_DIALOG @@ -48,8 +49,12 @@ class HomeActivity : if (previousFragment != null) { supportFragmentManager.beginTransaction().remove(previousFragment).commitNow() } + val argument = Argument.IsAdministratorControlsSelected(false) val dialogFragment = ExitProfileDialogFragment - .newInstance(isFromNavigationDrawer = false) + .newInstance( + restoreLastCheckedMenuItem = false, + argument = argument + ) dialogFragment.showNow(supportFragmentManager, TAG_SWITCH_PROFILE_DIALOG) } diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityTest.kt index ac38474ccdc..f0472b12c3e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityTest.kt @@ -27,6 +27,7 @@ import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA @@ -37,9 +38,12 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.util.HumanReadables import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.android.material.navigation.NavigationView import dagger.Component +import org.hamcrest.Description import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.not +import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Ignore @@ -55,6 +59,7 @@ import org.oppia.android.app.application.ApplicationInjector 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.drawer.NavigationDrawerItem import org.oppia.android.app.help.HelpActivity import org.oppia.android.app.model.ProfileId import org.oppia.android.app.mydownloads.MyDownloadsActivity @@ -161,7 +166,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_openNavDrawer_navDrawerIsOpened() { + fun testNavDrawer_openNavDrawer_navDrawerIsOpened() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withId(R.id.home_fragment_placeholder)).check(matches(isCompletelyDisplayed())) @@ -170,7 +175,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_openNavDrawer_changeConfig_navDrawerIsDisplayed() { + fun testNavDrawer_openNavDrawer_configChange_navDrawerIsDisplayed() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(isRoot()).perform(orientationLandscape()) @@ -179,7 +184,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withAdminProfile_openNavDrawer_profileNameIsDisplayed() { + fun testNavDrawer_withAdminProfile_openNavDrawer_profileNameIsDisplayed() { launch( createNavigationDrawerActivityIntent( internalProfileId @@ -197,7 +202,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withAdminProfile_changeConfig_profileNameIsDisplayed() { + fun testNavDrawer_withAdminProfile_configChange_profileNameIsDisplayed() { launch( createNavigationDrawerActivityIntent( internalProfileId @@ -216,7 +221,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_openNavDrawer_profileProgressIsDisplayed() { + fun testNavDrawer_openNavDrawer_profileProgressIsDisplayed() { launch( createNavigationDrawerActivityIntent( internalProfileId @@ -234,7 +239,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withUserProfile_openNavDrawer_profileNameIsDisplayed() { + fun testNavDrawer_withUserProfile_openNavDrawer_profileNameIsDisplayed() { launch( createNavigationDrawerActivityIntent( internalProfileId1 @@ -252,7 +257,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_clickOnHeader_opensProfileProgressActivity() { + fun testNavDrawer_clickOnHeader_opensProfileProgressActivity() { launch( createNavigationDrawerActivityIntent( internalProfileId @@ -272,8 +277,185 @@ class NavigationDrawerActivityTest { } } + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_switchProfile_cancel_homeItemIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.HOME))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_options_switchProfile_cancel_optionsIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_options)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.OPTIONS))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_help_switchProfile_cancel_helpIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_help)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.HELP))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_admin_switchProfile_cancel_adminIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.administrator_controls)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + testCoroutineDispatchers.runCurrent() + onView( + allOf( + withText(R.string.administrator_controls), + isDescendantOfA(withId(R.id.administrator_controls_linear_layout)) + ) + ).check(matches(ViewMatchers.hasTextColor(R.color.highlightedNavMenuItem))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_switchProfile_cancel_configChange_homeIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.HOME))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_options_switchProfile_cancel_configChange_optionsIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_options)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.OPTIONS))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_help_switchProfile_cancel_configChange_helpIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.menu_help)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.fragment_drawer_nav_view)) + .check(matches(checkNavigationViewItemStatus(NavigationDrawerItem.HELP))) + } + } + + // TODO(#2535): Unable to open NavigationDrawer multiple times on Robolectric + @RunOn(TestPlatform.ESPRESSO) + @Test + fun testNavDrawer_openNavDrawer_admin_switchProfile_cancel_configChange_adminIsSelected() { + launch( + createNavigationDrawerActivityIntent(internalProfileId) + ).use { + it.openNavigationDrawer() + onView(withText(R.string.administrator_controls)).perform(click()) + it.openNavigationDrawer() + onView(withText(R.string.menu_switch_profile)).perform(click()) + onView(withText(R.string.home_activity_back_dialog_cancel)) + .inRoot(isDialog()) + .perform(click()) + it.openNavigationDrawer() + testCoroutineDispatchers.runCurrent() + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView( + allOf( + withText(R.string.administrator_controls), + isDescendantOfA(withId(R.id.administrator_controls_linear_layout)) + ) + ).check(matches(ViewMatchers.hasTextColor(R.color.highlightedNavMenuItem))) + } + } + @Test - fun testNavigationDrawerTestActivity_withAdminProfile_openNavDrawer_adminControlsIsDisplayed() { + fun testNavDrawer_withAdminProfile_openNavDrawer_adminControlsIsDisplayed() { launch( createNavigationDrawerActivityIntent(internalProfileId) ).use { @@ -283,7 +465,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withAdminProfile_changeConfig_adminControlsIsDisplayed() { + fun testNavDrawer_withAdminProfile_configChange_adminControlsIsDisplayed() { launch( createNavigationDrawerActivityIntent(internalProfileId) ).use { @@ -295,7 +477,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withAdminProfile_adminMenu_opensAdminControlsActivity() { + fun testNavDrawer_withAdminProfile_adminMenu_opensAdminControlsActivity() { launch( createNavigationDrawerActivityIntent( internalProfileId @@ -310,7 +492,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_withUserProfile_adminControlsAreNotDisplayed() { + fun testNavDrawer_withUserProfile_adminControlsAreNotDisplayed() { launch( createNavigationDrawerActivityIntent( internalProfileId1 @@ -325,7 +507,7 @@ class NavigationDrawerActivityTest { // TODO(#1806): Enable this once lowfi implementation is done. @Test @Ignore("My Downloads is removed until we have full download support.") - fun testNavigationDrawerTestActivity_myDownloadsMenu_myDownloadsFragmentIsDisplayed() { + fun testNavDrawer_myDownloadsMenu_myDownloadsFragmentIsDisplayed() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_my_downloads)).perform(click()) @@ -334,7 +516,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_switchProfileMenu_showsExitToProfileChooserDialog() { + fun testNavDrawer_switchProfileMenu_exitToProfileChooserDialogIsDisplayed() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_switch_profile)).perform(click()) @@ -345,7 +527,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_switchProfileMenu_clickExit_opensProfileChooserActivity() { + fun testNavDrawer_switchProfileMenu_clickExit_opensProfileChooserActivity() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_switch_profile)).perform(click()) @@ -361,7 +543,7 @@ class NavigationDrawerActivityTest { @RunOn(TestPlatform.ESPRESSO) @Test - fun testNavigationDrawerTestActivity_openNavDrawerAndClose_navDrawerIsClosed() { + fun testNavDrawer_openNavDrawerAndClose_navDrawerIsClosed() { launch(NavigationDrawerTestActivity::class.java).use { testCoroutineDispatchers.runCurrent() it.openNavigationDrawer() @@ -372,7 +554,7 @@ class NavigationDrawerActivityTest { @RunOn(TestPlatform.ESPRESSO) @Test - fun testNavigationDrawerTestActivity_selectSwitchProfileMenu_clickCancel_navDrawerIsClosed() { + fun testNavDrawer_selectSwitchProfileMenu_clickCancel_navDrawerIsClosed() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_switch_profile)).perform(click()) @@ -388,7 +570,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_selectSwitchProfile_changeConfig_dialogIsVisible() { + fun testNavDrawer_selectSwitchProfile_configChange_dialogIsVisible() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_switch_profile)).perform(click()) @@ -401,7 +583,7 @@ class NavigationDrawerActivityTest { } @Test - fun testNavigationDrawerTestActivity_openNavDrawer_selectHelpMenu_opensHelpActivity() { + fun testNavDrawer_openNavDrawer_selectHelpMenu_opensHelpActivity() { launch(NavigationDrawerTestActivity::class.java).use { it.openNavigationDrawer() onView(withText(R.string.menu_help)).perform(click()) @@ -490,6 +672,17 @@ class NavigationDrawerActivityTest { return view.getParent() } + private fun checkNavigationViewItemStatus(item: NavigationDrawerItem) = + object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("NavigationViewItem is checked") + } + + override fun matchesSafely(view: View): Boolean { + return (view as NavigationView).menu.getItem(item.ordinal).isChecked + } + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. // TODO(#1675): Add NetworkModule once data module is migrated off of Moshi. @Singleton diff --git a/model/BUILD.bazel b/model/BUILD.bazel index 397f5bbcd50..63227df3877 100644 --- a/model/BUILD.bazel +++ b/model/BUILD.bazel @@ -39,6 +39,16 @@ load("@rules_java//java:defs.bzl", "java_lite_proto_library") # ... # ) +proto_library( + name = "arguments_proto", + srcs = ["src/main/proto/arguments.proto"], +) + +java_lite_proto_library( + name = "arguments_java_proto_lite", + deps = [":arguments_proto"], +) + proto_library( name = "event_logger_proto", srcs = ["src/main/proto/oppia_logger.proto"], @@ -192,6 +202,7 @@ android_library( name = "model", visibility = ["//visibility:public"], exports = [ + ":arguments_java_proto_lite", ":event_logger_java_proto_lite", ":exploration_java_proto_lite", ":interaction_object_java_proto_lite", diff --git a/model/src/main/proto/arguments.proto b/model/src/main/proto/arguments.proto new file mode 100644 index 00000000000..027df9b8ea5 --- /dev/null +++ b/model/src/main/proto/arguments.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package model; + +option java_package = "org.oppia.android.app.model"; +option java_multiple_files = true; + +// The fragment arguments passed to instances of ExitProfileDialogFragment. +message ExitProfileDialogArguments { + // Whether the last checked navigation drawer menu item needs to be restored(highlighted) or + // not after cancelling the Exit Profile Dialog. + bool restore_last_checked_menu_item = 1; + + oneof admin_controls_or_nav_drawer_items { + // Whether the request for switching/exiting profile was made from Administrator Controls + // or not. + bool is_administrator_controls_selected = 2; + + // The value of the menu item from the Navigation Drawer that was checked before + // the Exit Profile Dialog appears. + LastCheckedMenuItem last_checked_menu_item = 3; + } +} + +enum LastCheckedMenuItem { + HOME_MENU_ITEM_UNSPECIFIED = 0; + OPTIONS_MENU_ITEM = 1; + HELP_MENU_ITEM = 2; + DOWNLOADS_MENU_ITEM = 3; + SWITCH_PROFILE_ITEM = 4; +}