From 0b7ce5e2dc58122f02d0412e4f9ebcdcfcd6be75 Mon Sep 17 00:00:00 2001 From: Abhay Garg <54636525+prayutsu@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:30:41 +0530 Subject: [PATCH] Fix part of #3600: Add tablet UI for FAQs and Third-party Dependencies (#3671) * Create ThirdPartyActivity * Fix lints * Fix actionbar issue * Add tests * Add KDocs * Add LicenseListActivity to Manifest * Fix LicenseListFragment * Add test cases * Add LicenseTextViewerFragment * Pass index to LicenseListFragment * Fix all the bugs * Fix lints * Add tests files for all activities and fragments * Fix lints * Add viewModels to BUILD.bazel * Correct path of files in exemptions file * Add suggested changes * Add suggested changes * Remove unused imports * Correct styles in xml * Optimize layouts * fix lints * Correct layout width * Add test cases for all files * Add an extra test case * Add more test cases * revert changes in ktlint_lint_check.sh * Add suggested changes * Add marquee effect * Try setting text directly from fragment. * Add code to preserve text format * Add more test cases in LicenseTextViewerFragmentTest.kt * Add label for LicenseTextViewerActivity * Add suggested changes * Use direct import for isRoot() * Add KDocs for TestApplicationComponent in Test files * Remove unused imports * Correct imports order * Fix Kdocs check * Add suggested changes * Add suggested changes * Fix failing test cases * Add interfaces to load fragments * Remove extra Kdocs and add test files to Kdoc exemptions * Add suggested changes * Replace original dependencies name with dummy text * create helplist item viewmodel * Add support for new UIs for FAQList and ThirdPartyDependencyList in tablets * Delete unwanted files * Fix nits * Add Listeners and ViewModels to BUILD.bazel * Add test cases and add test exemptions * Correct Bug * Correct import * Fix crashing after clicking item * Add suggested changes * Correct test case * Hide Back arrow by default * Correct test case * Add TAG suffix to fragment tags * Add suggested changes * Add minHeight * Add suggested changes * Add punctuation in KDoc * Correct name in test_file_exemptions.textproto --- app/BUILD.bazel | 3 + .../oppia/android/app/help/HelpActivity.kt | 73 +++++- .../android/app/help/HelpActivityPresenter.kt | 77 ++++++- .../oppia/android/app/help/HelpFragment.kt | 19 +- .../android/app/help/HelpFragmentPresenter.kt | 7 +- .../android/app/help/HelpItemViewModel.kt | 24 +- .../android/app/help/HelpListViewModel.kt | 7 +- .../oppia/android/app/help/HelpViewModel.kt | 10 + .../app/help/LoadFaqListFragmentListener.kt | 7 + ...hirdPartyDependencyListFragmentListener.kt | 10 + .../drawable/ic_arrow_back_black_24_dp.xml | 11 + .../main/res/layout-sw600dp/help_activity.xml | 104 +++++++++ app/src/main/res/values/strings.xml | 3 + .../android/app/help/HelpFragmentTest.kt | 214 ++++++++++++++++++ scripts/assets/test_file_exemptions.textproto | 3 + 15 files changed, 552 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt create mode 100644 app/src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt create mode 100644 app/src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt create mode 100644 app/src/main/res/drawable/ic_arrow_back_black_24_dp.xml create mode 100644 app/src/main/res/layout-sw600dp/help_activity.xml diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 869a36022da..1e3d3b715f1 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -67,6 +67,8 @@ LISTENERS = [ "src/main/java/org/oppia/android/app/devoptions/RouteToMarkTopicsCompletedListener.kt", "src/main/java/org/oppia/android/app/devoptions/RouteToViewEventLogsListener.kt", "src/main/java/org/oppia/android/app/drawer/RouteToProfileProgressListener.kt", + "src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt", + "src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt", "src/main/java/org/oppia/android/app/help/RouteToFAQListListener.kt", "src/main/java/org/oppia/android/app/help/RouteToThirdPartyDependencyListListener.kt", "src/main/java/org/oppia/android/app/help/faq/RouteToFAQSingleListener.kt", @@ -200,6 +202,7 @@ VIEW_MODELS = [ "src/main/java/org/oppia/android/app/help/faq/faqItemViewModel/FAQHeaderViewModel.kt", "src/main/java/org/oppia/android/app/help/faq/faqItemViewModel/FAQItemViewModel.kt", "src/main/java/org/oppia/android/app/help/HelpItems.kt", + "src/main/java/org/oppia/android/app/help/HelpViewModel.kt", "src/main/java/org/oppia/android/app/help/thirdparty/LicenseItemViewModel.kt", "src/main/java/org/oppia/android/app/help/thirdparty/ThirdPartyDependencyItemViewModel.kt", "src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionItemViewModel.kt", diff --git a/app/src/main/java/org/oppia/android/app/help/HelpActivity.kt b/app/src/main/java/org/oppia/android/app/help/HelpActivity.kt index 96fe3257326..b95c4511307 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpActivity.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpActivity.kt @@ -3,22 +3,41 @@ package org.oppia.android.app.help import android.content.Context import android.content.Intent import android.os.Bundle +import android.widget.TextView import org.oppia.android.R import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.drawer.NAVIGATION_PROFILE_ID_ARGUMENT_KEY import org.oppia.android.app.help.faq.FAQListActivity +import org.oppia.android.app.help.faq.RouteToFAQSingleListener +import org.oppia.android.app.help.faq.faqsingle.FAQSingleActivity +import org.oppia.android.app.help.thirdparty.LicenseListActivity +import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity +import org.oppia.android.app.help.thirdparty.RouteToLicenseListListener +import org.oppia.android.app.help.thirdparty.RouteToLicenseTextListener import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity import javax.inject.Inject +private const val HELP_OPTIONS_TITLE_SAVED_KEY = "HelpActivity.help_options_title" +private const val SELECTED_FRAGMENT_SAVED_KEY = "HelpActivity.selected_fragment" +const val FAQ_LIST_FRAGMENT_TAG = "FAQListFragment.tag" +const val THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG = "ThirdPartyDependencyListFragment.tag" + /** The help page activity for FAQs and third-party dependencies. */ class HelpActivity : InjectableAppCompatActivity(), RouteToFAQListListener, - RouteToThirdPartyDependencyListListener { + RouteToFAQSingleListener, + RouteToThirdPartyDependencyListListener, + RouteToLicenseTextListener, + RouteToLicenseListListener, + LoadFaqListFragmentListener, + LoadThirdPartyDependencyListFragmentListener { @Inject lateinit var helpActivityPresenter: HelpActivityPresenter + private lateinit var selectedFragment: String + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityComponent.inject(this) @@ -26,7 +45,14 @@ class HelpActivity : BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY, /* defaultValue= */ false ) - helpActivityPresenter.handleOnCreate(isFromNavigationDrawer) + selectedFragment = + savedInstanceState?.getString(SELECTED_FRAGMENT_SAVED_KEY) ?: FAQ_LIST_FRAGMENT_TAG + val extraHelpOptionsTitle = savedInstanceState?.getString(HELP_OPTIONS_TITLE_SAVED_KEY) + helpActivityPresenter.handleOnCreate( + extraHelpOptionsTitle, + isFromNavigationDrawer, + selectedFragment + ) title = getString(R.string.menu_help) } @@ -56,4 +82,47 @@ class HelpActivity : val intent = ThirdPartyDependencyListActivity.createThirdPartyDependencyListActivityIntent(this) startActivity(intent) } + + override fun loadFaqListFragment() { + selectedFragment = FAQ_LIST_FRAGMENT_TAG + helpActivityPresenter.handleLoadFAQListFragment() + } + + override fun loadThirdPartyDependencyListFragment() { + selectedFragment = THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG + helpActivityPresenter.handleLoadThirdPartyDependencyListFragment() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + val titleTextView = findViewById(R.id.help_multipane_options_title_textview) + if (titleTextView != null) { + outState.putString(HELP_OPTIONS_TITLE_SAVED_KEY, titleTextView.text.toString()) + } + outState.putString(SELECTED_FRAGMENT_SAVED_KEY, selectedFragment) + } + + override fun onRouteToLicenseText(dependencyIndex: Int, licenseIndex: Int) { + startActivity( + LicenseTextViewerActivity.createLicenseTextViewerActivityIntent( + this, + dependencyIndex, + licenseIndex + ) + ) + } + + override fun onRouteToLicenseList(dependencyIndex: Int) { + startActivity( + LicenseListActivity + .createLicenseListActivityIntent( + context = this, + dependencyIndex = dependencyIndex + ) + ) + } + + override fun onRouteToFAQSingle(question: String, answer: String) { + startActivity(FAQSingleActivity.createFAQSingleActivityIntent(this, question, answer)) + } } diff --git a/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt index 61c92e2712f..294d8b66a6f 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt @@ -1,12 +1,17 @@ package org.oppia.android.app.help import android.view.View +import android.widget.FrameLayout +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.drawerlayout.widget.DrawerLayout +import androidx.fragment.app.Fragment import org.oppia.android.R import org.oppia.android.app.activity.ActivityScope import org.oppia.android.app.drawer.NavigationDrawerFragment +import org.oppia.android.app.help.faq.FAQListFragment +import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListFragment import javax.inject.Inject /** The presenter for [HelpActivity]. */ @@ -15,7 +20,11 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA private lateinit var navigationDrawerFragment: NavigationDrawerFragment private lateinit var toolbar: Toolbar - fun handleOnCreate(isFromNavigationDrawer: Boolean) { + fun handleOnCreate( + extraHelpOptionsTitle: String?, + isFromNavigationDrawer: Boolean, + selectedFragment: String + ) { if (isFromNavigationDrawer) { activity.setContentView(R.layout.help_activity) setUpToolbar() @@ -28,12 +37,53 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA activity.finish() } } - if (getHelpFragment() == null) { - activity.supportFragmentManager.beginTransaction().add( - R.id.help_fragment_placeholder, - HelpFragment() - ).commitNow() + val titleTextView = + activity.findViewById(R.id.options_activity_selected_options_title) + if (titleTextView != null) { + setMultipaneContainerTitle(extraHelpOptionsTitle!!) } + val isMultipane = activity.findViewById(R.id.multipane_options_container) != null + if (isMultipane) { + loadMultipaneFragment(selectedFragment) + } + val previousFragment = getHelpFragment() + if (previousFragment != null) { + activity.supportFragmentManager.beginTransaction().remove(previousFragment).commitNow() + } + activity.supportFragmentManager.beginTransaction().add( + R.id.help_fragment_placeholder, + HelpFragment.newInstance(isMultipane) + ).commitNow() + } + + /** Loads [ThirdPartyDependencyListFragment] in tablet devices. */ + fun handleLoadThirdPartyDependencyListFragment() { + setMultipaneContainerTitle( + activity.getString(R.string.third_party_dependency_list_activity_title) + ) + getMultipaneOptionsFragment()?.let { + activity.supportFragmentManager.beginTransaction().remove( + it + ).commit() + } + val thirdPartyDependencyListFragment = ThirdPartyDependencyListFragment.newInstance() + activity.supportFragmentManager.beginTransaction().add( + R.id.multipane_options_container, + thirdPartyDependencyListFragment + ).commitNow() + } + + /** Loads [FAQListFragment] in tablet devices. */ + fun handleLoadFAQListFragment() { + setMultipaneContainerTitle(activity.getString(R.string.faq_activity_title)) + getMultipaneOptionsFragment()?.let { + activity.supportFragmentManager.beginTransaction().remove(it) + .commit() + } + activity.supportFragmentManager.beginTransaction().add( + R.id.multipane_options_container, + FAQListFragment() + ).commitNow() } private fun setUpToolbar() { @@ -59,4 +109,19 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA .supportFragmentManager .findFragmentById(R.id.help_fragment_placeholder) as HelpFragment? } + + private fun loadMultipaneFragment(selectedFragment: String) { + when (selectedFragment) { + FAQ_LIST_FRAGMENT_TAG -> handleLoadFAQListFragment() + THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG -> handleLoadThirdPartyDependencyListFragment() + } + } + + private fun setMultipaneContainerTitle(title: String) { + activity.findViewById(R.id.help_multipane_options_title_textview).text = title + } + + private fun getMultipaneOptionsFragment(): Fragment? { + return activity.supportFragmentManager.findFragmentById(R.id.multipane_options_container) + } } diff --git a/app/src/main/java/org/oppia/android/app/help/HelpFragment.kt b/app/src/main/java/org/oppia/android/app/help/HelpFragment.kt index 9a8c7c52673..85ecafaa330 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpFragment.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpFragment.kt @@ -8,11 +8,24 @@ import android.view.ViewGroup import org.oppia.android.app.fragment.InjectableFragment import javax.inject.Inject +private const val IS_MULTIPANE_KEY = "HelpFragment.bool_is_multipane" + /** Fragment that contains help in the app. */ class HelpFragment : InjectableFragment() { @Inject lateinit var helpFragmentPresenter: HelpFragmentPresenter + companion object { + /** Returns instance of [HelpFragment]. */ + fun newInstance(isMultipane: Boolean): HelpFragment { + val args = Bundle() + args.putBoolean(IS_MULTIPANE_KEY, isMultipane) + val fragment = HelpFragment() + fragment.arguments = args + return fragment + } + } + override fun onAttach(context: Context) { super.onAttach(context) fragmentComponent.inject(this) @@ -23,6 +36,10 @@ class HelpFragment : InjectableFragment() { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - return helpFragmentPresenter.handleCreateView(inflater, container) + val args = checkNotNull(arguments) { + "Expected arguments to be passed to HelpFragment" + } + val isMultipane = args.getBoolean(IS_MULTIPANE_KEY) + return helpFragmentPresenter.handleCreateView(inflater, container, isMultipane) } } diff --git a/app/src/main/java/org/oppia/android/app/help/HelpFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/help/HelpFragmentPresenter.kt index a8fc0b2852e..19c07875867 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpFragmentPresenter.kt @@ -22,8 +22,13 @@ class HelpFragmentPresenter @Inject constructor( ) { private lateinit var binding: HelpFragmentBinding - fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { + fun handleCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + isMultipane: Boolean + ): View? { val viewModel = getHelpListViewModel() + viewModel.isMultipane.set(isMultipane) binding = HelpFragmentBinding.inflate( inflater, diff --git a/app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt b/app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt index 35135bd43f9..e999203b6ae 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt @@ -7,18 +7,30 @@ import org.oppia.android.app.viewmodel.ObservableViewModel /** [ObservableViewModel] for the recycler view of HelpActivity. */ class HelpItemViewModel( val activity: AppCompatActivity, - val title: String + val title: String, + val isMultipane: Boolean ) : ObservableViewModel() { fun onClick(title: String) { when (title) { activity.getString(R.string.frequently_asked_questions_FAQ) -> { - val routeToFAQListener = activity as RouteToFAQListListener - routeToFAQListener.onRouteToFAQList() + if (isMultipane) { + val loadFaqListFragmentListener = activity as LoadFaqListFragmentListener + loadFaqListFragmentListener.loadFaqListFragment() + } else { + val routeToFAQListener = activity as RouteToFAQListListener + routeToFAQListener.onRouteToFAQList() + } } activity.getString(R.string.third_party_dependency_list_activity_title) -> { - val routeToThirdPartyDependencyListListener = activity - as RouteToThirdPartyDependencyListListener - routeToThirdPartyDependencyListListener.onRouteToThirdPartyDependencyList() + if (isMultipane) { + val loadThirdPartyDependencyListFragmentListener = activity as + LoadThirdPartyDependencyListFragmentListener + loadThirdPartyDependencyListFragmentListener.loadThirdPartyDependencyListFragment() + } else { + val routeToThirdPartyDependencyListListener = activity + as RouteToThirdPartyDependencyListListener + routeToThirdPartyDependencyListListener.onRouteToThirdPartyDependencyList() + } } } } diff --git a/app/src/main/java/org/oppia/android/app/help/HelpListViewModel.kt b/app/src/main/java/org/oppia/android/app/help/HelpListViewModel.kt index 63cc02f559e..5e6561c8940 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpListViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpListViewModel.kt @@ -2,13 +2,12 @@ package org.oppia.android.app.help import androidx.appcompat.app.AppCompatActivity import org.oppia.android.R -import org.oppia.android.app.viewmodel.ObservableViewModel import javax.inject.Inject /** View model in [HelpFragment]. */ class HelpListViewModel @Inject constructor( val activity: AppCompatActivity -) : ObservableViewModel() { +) : HelpViewModel() { private val arrayList = ArrayList() val helpItemList: List by lazy { @@ -22,11 +21,11 @@ class HelpListViewModel @Inject constructor( when (item) { HelpItems.FAQ -> { category = activity.getString(R.string.frequently_asked_questions_FAQ) - helpItemViewModel = HelpItemViewModel(activity, category) + helpItemViewModel = HelpItemViewModel(activity, category, isMultipane.get()!!) } HelpItems.THIRD_PARTY -> { category = activity.getString(R.string.third_party_dependency_list_activity_title) - helpItemViewModel = HelpItemViewModel(activity, category) + helpItemViewModel = HelpItemViewModel(activity, category, isMultipane.get()!!) } } arrayList.add(helpItemViewModel) diff --git a/app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt b/app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt new file mode 100644 index 00000000000..139d31b1c2b --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt @@ -0,0 +1,10 @@ +package org.oppia.android.app.help + +import androidx.databinding.ObservableField +import org.oppia.android.app.viewmodel.ObservableViewModel + +/** Option items view model for the recyclerView in [HelpFragment]. */ +abstract class HelpViewModel : ObservableViewModel() { + /** Indicates whether the device in use has a large screen & should be multi-pane. */ + val isMultipane = ObservableField(false) +} diff --git a/app/src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt b/app/src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt new file mode 100644 index 00000000000..94747d0740a --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt @@ -0,0 +1,7 @@ +package org.oppia.android.app.help + +/** Listener for when a selection should result to [FAQListFragment] in tablet devices. */ +interface LoadFaqListFragmentListener { + /** Called when the user wants to open the list of FAQs in tablet devices. */ + fun loadFaqListFragment() +} diff --git a/app/src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt b/app/src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt new file mode 100644 index 00000000000..7da46ccedaa --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt @@ -0,0 +1,10 @@ +package org.oppia.android.app.help + +/** + * Listener for when a selection should result to [ThirdPartyDependencyListFragment] in tablet + * devices. + */ +interface LoadThirdPartyDependencyListFragmentListener { + /** Called when the user wants to open the list of third-party dependencies in tablet devices. */ + fun loadThirdPartyDependencyListFragment() +} diff --git a/app/src/main/res/drawable/ic_arrow_back_black_24_dp.xml b/app/src/main/res/drawable/ic_arrow_back_black_24_dp.xml new file mode 100644 index 00000000000..f1f75bca584 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back_black_24_dp.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout-sw600dp/help_activity.xml b/app/src/main/res/layout-sw600dp/help_activity.xml new file mode 100644 index 00000000000..2fae4580e7f --- /dev/null +++ b/app/src/main/res/layout-sw600dp/help_activity.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 18bbe006a00..7a889cab4da 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -491,4 +491,7 @@ Copyright License Viewer + + + Navigate back to %s 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 f28b4c7daeb..956fe8799bc 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 @@ -18,10 +18,12 @@ import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +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 @@ -257,6 +259,218 @@ class HelpFragmentTest { } } + @Test + fun testHelpFragment_phoneConfig_multipaneOptionsDoesNotExist() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.help_multipane_options_back_button)).check(doesNotExist()) + onView(withId(R.id.help_multipane_options_title_textview)).check(doesNotExist()) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_defaultTabletConfig_multipaneButtonIsGone() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.help_multipane_options_back_button)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)) + ) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_defaultTabletConfig_displaysMultipaneOptions() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.faq_activity_title) + ) + ) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + isCompletelyDisplayed() + ) + ) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_tabletConfigChange_displaysMultipaneOptions() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(isRoot()).perform(orientationLandscape()) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.faq_activity_title) + ) + ) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + isCompletelyDisplayed() + ) + ) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_defaultTabletConfig_displaysFAQList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.faq_fragment_recycler_view)).check(matches(isDisplayed())) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_tabletConfigChanged_displaysFAQList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(isRoot()).perform(orientationLandscape()) + onView(withId(R.id.faq_fragment_recycler_view)).check(matches(isDisplayed())) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_selectFAQs_displaysFAQList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView( + atPosition( + recyclerViewId = R.id.help_fragment_recycler_view, + position = 0 + ) + ).perform(click()) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.faq_activity_title) + ) + ) + onView(withId(R.id.faq_fragment_recycler_view)).check(matches(isDisplayed())) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_selectFAQs_tabletConfigChanged_displaysFAQList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView( + atPosition( + recyclerViewId = R.id.help_fragment_recycler_view, + position = 0 + ) + ).perform(click()) + onView(isRoot()).perform(orientationLandscape()) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.faq_activity_title) + ) + ) + onView(withId(R.id.faq_fragment_recycler_view)).check(matches(isDisplayed())) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_selectThirdPartyDeps_displaysThirdPartyDepsList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.help_fragment_recycler_view)).perform( + scrollToPosition(1) + ) + onView( + atPosition( + recyclerViewId = R.id.help_fragment_recycler_view, + position = 1 + ) + ).perform(click()) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.third_party_dependency_list_activity_title) + ) + ) + onView(withId(R.id.third_party_dependency_list_fragment_recycler_view)).check( + matches( + isDisplayed() + ) + ) + } + } + + @Test + @Config(qualifiers = "sw600dp") + fun testHelpFragment_selectThirdPartyDeps_tabletConfigChanged_displaysThirdPartyDepsList() { + launch( + createHelpActivityIntent( + internalProfileId = 0, + isFromNavigationDrawer = true + ) + ).use { + onView(withId(R.id.help_fragment_recycler_view)).perform( + scrollToPosition(1) + ) + onView( + atPosition( + recyclerViewId = R.id.help_fragment_recycler_view, + position = 1 + ) + ).perform(click()) + onView(isRoot()).perform(orientationLandscape()) + onView(withId(R.id.help_multipane_options_title_textview)).check( + matches( + withText(R.string.third_party_dependency_list_activity_title) + ) + ) + onView(withId(R.id.third_party_dependency_list_fragment_recycler_view)).check( + matches( + isDisplayed() + ) + ) + } + } + @Test fun testHelpFragment_configChanged_thirdPartyDependencyListTitleIsDisplayed() { launch( diff --git a/scripts/assets/test_file_exemptions.textproto b/scripts/assets/test_file_exemptions.textproto index 9846f6ea36c..638c1148dd5 100644 --- a/scripts/assets/test_file_exemptions.textproto +++ b/scripts/assets/test_file_exemptions.textproto @@ -101,7 +101,10 @@ exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpActivityPr exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpFragmentPresenter.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpItems.kt" +exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/HelpListViewModel.kt" +exempted_file_path: "app/src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt" +exempted_file_path: "app/src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/RouteToFAQListListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/RouteToThirdPartyDependencyListListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/help/faq/FAQListActivity.kt"