From 51bd9e79082dd355d5465bb979902bce90ea2ab6 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 1 Aug 2025 00:57:03 +0530 Subject: [PATCH] Fixed: NavController adding multiple instances of the same fragment in backStack with causing issues when navigating. * Refactored the `DarkModeViewPainterTest` with compose UI. * Refactored the `CopyMoveFileHandlerTest` according to compose UI. * Refactored the test cases to get the fragments in test cases according to compose based navigation. * Refactored the `SearchFragmentTestForCustomApp` test case. --- .../kiwixmobile/download/DownloadTest.kt | 4 +- .../localLibrary/CopyMoveFileHandlerTest.kt | 46 +++++------ .../main/DarkModeViewPainterTest.kt | 70 ++++++++++------- .../main/TopLevelDestinationRobot.kt | 65 ++++++++++++---- .../main/TopLevelDestinationTest.kt | 12 +-- .../page/bookmarks/BookmarksRobot.kt | 30 +++++--- .../page/bookmarks/LibkiwixBookmarkTest.kt | 77 ++++++++++--------- .../page/history/NavigationHistoryRobot.kt | 26 +++++-- .../shortcuts/GetContentShortcutTest.kt | 12 +-- .../kiwixmobile/utils/StandardActions.kt | 3 - .../org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt | 37 +++++---- .../kiwixmobile/core/main/CoreMainActivity.kt | 4 + .../kiwixmobile/core/main/MainDrawerMenu.kt | 3 + .../core/main/reader/ReaderScreen.kt | 28 +++++-- core/src/main/res/values/ids.xml | 18 +++-- .../search/SearchFragmentTestForCustomApp.kt | 36 ++++----- .../kiwixmobile/custom/search/SearchRobot.kt | 40 +++++----- .../kiwixmobile/custom/testutils/TestUtils.kt | 2 +- .../kiwixmobile/custom/main/CustomNavGraph.kt | 27 ++++--- 19 files changed, 317 insertions(+), 223 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/download/DownloadTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/download/DownloadTest.kt index 997f8b57a..49edea82d 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/download/DownloadTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/download/DownloadTest.kt @@ -193,7 +193,7 @@ class DownloadTest : BaseActivityTest() { downloadRobot { // change the application language topLevel { - clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { clickLanguagePreference(composeTestRule) assertLanguagePrefDialogDisplayed(composeTestRule) selectDeviceDefaultLanguage(composeTestRule) @@ -214,7 +214,7 @@ class DownloadTest : BaseActivityTest() { stopDownloadIfAlreadyStarted(composeTestRule) // select the default device language to perform other test cases. topLevel { - clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { clickLanguagePreference(composeTestRule) assertLanguagePrefDialogDisplayed(composeTestRule) selectDeviceDefaultLanguage(composeTestRule) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/CopyMoveFileHandlerTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/CopyMoveFileHandlerTest.kt index 127637f30..ef2bb5d06 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/CopyMoveFileHandlerTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/CopyMoveFileHandlerTest.kt @@ -39,7 +39,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest -import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.core.extensions.deleteFile import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.settings.StorageCalculator @@ -50,6 +49,7 @@ import org.kiwix.kiwixmobile.core.utils.TestingUtils.RETRY_RULE_ORDER import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower import org.kiwix.kiwixmobile.main.KiwixMainActivity import org.kiwix.kiwixmobile.nav.destination.library.CopyMoveFileHandler +import org.kiwix.kiwixmobile.nav.destination.library.local.LocalLibraryFragment import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout @@ -201,33 +201,29 @@ class CopyMoveFileHandlerTest : BaseActivityTest() { } private fun showMoveFileToPublicDirectoryDialog() { - // TODO refactore this with compose based navController. - // kiwixMainActivity.lifecycleScope.launch { - // val navHostFragment: NavHostFragment = - // kiwixMainActivity.navController - // .findFragmentById(R.id.nav_host_fragment) as NavHostFragment - // val localLibraryFragment = - // navHostFragment.childFragmentManager.fragments[0] as LocalLibraryFragment - // localLibraryFragment.copyMoveFileHandler?.showMoveFileToPublicDirectoryDialog( - // Uri.fromFile(selectedFile), - // DocumentFile.fromFile(selectedFile), - // fragmentManager = localLibraryFragment.parentFragmentManager - // ) - // } + kiwixMainActivity.lifecycleScope.launch { + val localLibraryFragment = + kiwixMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() + localLibraryFragment?.copyMoveFileHandler?.showMoveFileToPublicDirectoryDialog( + Uri.fromFile(selectedFile), + DocumentFile.fromFile(selectedFile), + fragmentManager = localLibraryFragment.parentFragmentManager + ) + } } private fun tryOpeningInvalidZimFiles(uri: Uri) { - // TODO refactore this with compose based navController. - // UiThreadStatement.runOnUiThread { - // val navHostFragment: NavHostFragment = - // kiwixMainActivity.supportFragmentManager - // .findFragmentById(R.id.nav_host_fragment) as NavHostFragment - // val localLibraryFragment = - // navHostFragment.childFragmentManager.fragments[0] as LocalLibraryFragment - // localLibraryFragment.handleSelectedFileUri( - // uri, - // ) - // } + UiThreadStatement.runOnUiThread { + val localLibraryFragment = + kiwixMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() + localLibraryFragment?.handleSelectedFileUri( + uri, + ) + } } private fun getSelectedFile(): File { diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/DarkModeViewPainterTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/DarkModeViewPainterTest.kt index 0e7849a08..4216b348b 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/DarkModeViewPainterTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/DarkModeViewPainterTest.kt @@ -19,6 +19,8 @@ package org.kiwix.kiwixmobile.main import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick import androidx.core.content.edit import androidx.core.net.toUri import androidx.lifecycle.Lifecycle @@ -27,7 +29,6 @@ import androidx.preference.PreferenceManager import androidx.test.core.app.ActivityScenario import androidx.test.espresso.accessibility.AccessibilityChecks import androidx.test.espresso.matcher.ViewMatchers.withContentDescription -import androidx.test.internal.runner.junit4.statement.UiThreadStatement import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheck @@ -42,13 +43,17 @@ import org.junit.Rule import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.ui.components.NAVIGATION_ICON_TESTING_TAG import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TestingUtils.COMPOSE_TEST_RULE_ORDER import org.kiwix.kiwixmobile.core.utils.TestingUtils.RETRY_RULE_ORDER +import org.kiwix.kiwixmobile.nav.destination.reader.KiwixReaderFragment import org.kiwix.kiwixmobile.settings.settingsRobo import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.TestUtils +import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST +import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout import org.kiwix.kiwixmobile.ui.KiwixDestination import java.io.File import java.io.FileOutputStream @@ -85,6 +90,7 @@ class DarkModeViewPainterTest : BaseActivityTest() { ActivityScenario.launch(KiwixMainActivity::class.java).apply { moveToState(Lifecycle.State.RESUMED) onActivity { + kiwixMainActivity = it LanguageUtils.handleLocaleChange( it, "en", @@ -111,6 +117,7 @@ class DarkModeViewPainterTest : BaseActivityTest() { @Test fun testDarkMode() { + composeTestRule.waitForIdle() toggleDarkMode(true) openZimFileInReader() verifyDarkMode(true) @@ -122,13 +129,19 @@ class DarkModeViewPainterTest : BaseActivityTest() { private fun openZimFileInReader() { activityScenario.onActivity { kiwixMainActivity = it - kiwixMainActivity.navigate(KiwixDestination.Library.route) + } + composeTestRule.apply { + waitUntilTimeout() + onNodeWithTag(NAVIGATION_ICON_TESTING_TAG).performClick() + waitUntilTimeout() + onNodeWithTag(BOTTOM_NAV_LIBRARY_ITEM_TESTING_TAG).performClick() + waitUntilTimeout() } loadZimFileInReader() } private fun toggleDarkMode(enable: Boolean) { - darkModeViewPainter { openSettings(kiwixMainActivity as CoreMainActivity) } + darkModeViewPainter { openSettings(kiwixMainActivity as CoreMainActivity, composeTestRule) } settingsRobo { clickNightModePreference(composeTestRule) } darkModeViewPainter { if (enable) { @@ -136,33 +149,33 @@ class DarkModeViewPainterTest : BaseActivityTest() { } else { enableTheLightMode(composeTestRule) } - pressBack() } } private fun verifyDarkMode(isEnabled: Boolean) { - // TODO refactor this with compose based navController. - // UiThreadStatement.runOnUiThread { - // val navHostFragment: NavHostFragment = - // kiwixMainActivity.supportFragmentManager - // .findFragmentById(R.id.nav_host_fragment) as NavHostFragment - // val kiwixReaderFragment = - // navHostFragment.childFragmentManager.fragments[0] as KiwixReaderFragment - // val currentWebView = kiwixReaderFragment.getCurrentWebView() - // currentWebView?.let { - // darkModeViewPainter { - // if (isEnabled) { - // assertNightModeEnabled(it) - // } else { - // assertLightModeEnabled(it) - // } - // } - // } ?: run { - // throw RuntimeException( - // "Could not check the dark mode enable or not because zim file is not loaded in the reader" - // ) - // } - // } + var kiwixReaderFragment: KiwixReaderFragment? = null + composeTestRule.waitForIdle() + composeTestRule.waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + kiwixReaderFragment = + kiwixMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() + kiwixReaderFragment?.getCurrentWebView() != null + } + val currentWebView = kiwixReaderFragment?.getCurrentWebView() + currentWebView?.let { + darkModeViewPainter { + if (isEnabled) { + assertNightModeEnabled(it) + } else { + assertLightModeEnabled(it) + } + } + } ?: run { + throw RuntimeException( + "Could not check the dark mode enable or not because zim file is not loaded in the reader" + ) + } } private fun loadZimFileInReader() { @@ -185,7 +198,10 @@ class DarkModeViewPainterTest : BaseActivityTest() { } } } - UiThreadStatement.runOnUiThread { + activityScenario.onActivity { + kiwixMainActivity = it + } + composeTestRule.runOnIdle { val navOptions = NavOptions.Builder() .setPopUpTo(KiwixDestination.Reader.route, false) .build() diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationRobot.kt index 7e8e62713..67f32e86f 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationRobot.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationRobot.kt @@ -20,15 +20,16 @@ package org.kiwix.kiwixmobile.main import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.matcher.ViewMatchers.withText import applyWithViewHierarchyPrinting import com.adevinta.android.barista.interaction.BaristaSleepInteractions import org.kiwix.kiwixmobile.BaseRobot -import org.kiwix.kiwixmobile.Findable.StringId.TextId -import org.kiwix.kiwixmobile.core.R.string import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_BOOKMARK_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_HELP_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_HISTORY_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_SETTINGS_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_SUPPORT_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_ZIM_HOST_ITEM_TESTING_TAG import org.kiwix.kiwixmobile.help.HelpRobot import org.kiwix.kiwixmobile.help.help import org.kiwix.kiwixmobile.nav.destination.library.LibraryRobot @@ -99,47 +100,79 @@ class TopLevelDestinationRobot : BaseRobot() { fun clickBookmarksOnNavDrawer( coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, func: BookmarksRobot.() -> Unit ) { inNavDrawer(coreMainActivity = coreMainActivity) { - testFlakyView({ onView(withText(string.bookmarks)).perform(click()) }) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_BOOKMARK_ITEM_TESTING_TAG).performClick() + }) bookmarks(func) pressBack() } } - fun clickHistoryOnSideNav(coreMainActivity: CoreMainActivity, func: HistoryRobot.() -> Unit) { + fun clickHistoryOnSideNav( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, + func: HistoryRobot.() -> Unit + ) { inNavDrawer(coreMainActivity) { - clickOn(TextId(string.history)) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_HISTORY_ITEM_TESTING_TAG).performClick() + }) history(func) pressBack() } } - fun clickHostBooksOnSideNav(coreMainActivity: CoreMainActivity, func: ZimHostRobot.() -> Unit) { + fun clickHostBooksOnSideNav( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, + func: ZimHostRobot.() -> Unit + ) { inNavDrawer(coreMainActivity) { - clickOn(TextId(string.menu_wifi_hotspot)) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_ZIM_HOST_ITEM_TESTING_TAG).performClick() + }) zimHost(func) } } - fun clickSettingsOnSideNav(coreMainActivity: CoreMainActivity, func: SettingsRobot.() -> Unit) { + fun clickSettingsOnSideNav( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, + func: SettingsRobot.() -> Unit + ) { inNavDrawer(coreMainActivity) { - clickOn(TextId(string.menu_settings)) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_SETTINGS_ITEM_TESTING_TAG).performClick() + }) settingsRobo(func) } } - fun clickHelpOnSideNav(coreMainActivity: CoreMainActivity, func: HelpRobot.() -> Unit) { + fun clickHelpOnSideNav( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, + func: HelpRobot.() -> Unit + ) { inNavDrawer(coreMainActivity) { - clickOn(TextId(string.menu_help)) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_HELP_ITEM_TESTING_TAG).performClick() + }) help(func) } } - fun clickSupportKiwixOnSideNav(coreMainActivity: CoreMainActivity) { + fun clickSupportKiwixOnSideNav( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule, + ) { inNavDrawer(coreMainActivity) { - clickOn(TextId(string.menu_support_kiwix)) + testFlakyView({ + composeTestRule.onNodeWithTag(LEFT_DRAWER_SUPPORT_ITEM_TESTING_TAG).performClick() + }) } } } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationTest.kt index a34f01ced..c92d5e1ea 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/main/TopLevelDestinationTest.kt @@ -126,26 +126,26 @@ class TopLevelDestinationTest : BaseActivityTest() { assertReceiveFileTitleVisible(composeTestRule) } } - clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity) { + clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertBookMarksDisplayed(composeTestRule) clickOnTrashIcon(composeTestRule) assertDeleteBookmarksDialogDisplayed(composeTestRule) } - clickHistoryOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHistoryOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertHistoryDisplayed(composeTestRule) clickOnTrashIcon(composeTestRule) assertDeleteHistoryDialogDisplayed(composeTestRule) } - clickHostBooksOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHostBooksOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertMenuWifiHotspotDisplayed(composeTestRule) } - clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertMenuSettingsDisplayed(composeTestRule) } - clickHelpOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHelpOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertToolbarDisplayed(composeTestRule) } - clickSupportKiwixOnSideNav(kiwixMainActivity as CoreMainActivity) + clickSupportKiwixOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) pressBack() } if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/BookmarksRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/BookmarksRobot.kt index 5dd1bb180..e0dea6f4a 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/BookmarksRobot.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/BookmarksRobot.kt @@ -24,20 +24,18 @@ import androidx.compose.ui.test.isDisplayed import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.ComposeTestRule import androidx.compose.ui.test.longClick -import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollToNode import androidx.compose.ui.test.performTouchInput -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.matcher.ViewMatchers.withText import applyWithViewHierarchyPrinting import com.adevinta.android.barista.interaction.BaristaSleepInteractions import org.kiwix.kiwixmobile.BaseRobot import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_BOOKMARK_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.reader.READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG import org.kiwix.kiwixmobile.core.page.DELETE_MENU_ICON_TESTING_TAG import org.kiwix.kiwixmobile.core.page.NO_ITEMS_TEXT_TESTING_TAG import org.kiwix.kiwixmobile.core.page.PAGE_LIST_TEST_TAG @@ -47,6 +45,7 @@ import org.kiwix.kiwixmobile.core.utils.dialog.ALERT_DIALOG_CONFIRM_BUTTON_TESTI import org.kiwix.kiwixmobile.core.utils.dialog.ALERT_DIALOG_TITLE_TEXT_TESTING_TAG import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS +import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout import org.kiwix.kiwixmobile.utils.StandardActions.openDrawer @@ -104,8 +103,11 @@ class BookmarksRobot : BaseRobot() { fun clickOnSaveBookmarkImage(composeTestRule: ComposeContentTestRule) { composeTestRule.apply { - waitUntilTimeout() - onNodeWithContentDescription(context.getString(R.string.bookmarks)) + waitForIdle() + waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG).isDisplayed() + } + onNodeWithTag(READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG) .performClick() } } @@ -115,9 +117,13 @@ class BookmarksRobot : BaseRobot() { timeout: Long = TEST_PAUSE_MS.toLong() ) { composeTestRule.apply { + waitForIdle() // wait for disappearing the snack-bar after removing the bookmark waitUntilTimeout(timeout) - onNodeWithContentDescription(context.getString(R.string.bookmarks)) + waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG).isDisplayed() + } + onNodeWithTag(READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG) .performTouchInput { longClick() } @@ -144,10 +150,16 @@ class BookmarksRobot : BaseRobot() { BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong()) } - fun openBookmarkScreen(coreMainActivity: CoreMainActivity) { + fun openBookmarkScreen( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule + ) { testFlakyView({ openDrawer(coreMainActivity) - onView(withText(R.string.bookmarks)).perform(click()) + composeTestRule.apply { + waitUntilTimeout() + onNodeWithTag(LEFT_DRAWER_BOOKMARK_ITEM_TESTING_TAG).performClick() + } }) } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt index e6c14d6a3..4d50b9511 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt @@ -33,6 +33,7 @@ import com.google.android.apps.common.testing.accessibility.framework.Accessibil import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews import com.google.android.apps.common.testing.accessibility.framework.checks.SpeakableTextPresentCheck import com.google.android.apps.common.testing.accessibility.framework.checks.TouchTargetSizeCheck +import kotlinx.coroutines.runBlocking import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.anyOf import org.junit.Before @@ -40,6 +41,8 @@ import org.junit.Rule import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.reader.CoreReaderFragment +import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TestingUtils.COMPOSE_TEST_RULE_ORDER @@ -51,6 +54,8 @@ import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout import org.kiwix.kiwixmobile.ui.KiwixDestination +import org.kiwix.libkiwix.Book +import org.kiwix.libkiwix.Bookmark import java.io.File import java.io.FileOutputStream import java.io.OutputStream @@ -134,7 +139,7 @@ class LibkiwixBookmarkTest : BaseActivityTest() { pressBack() // Test saving bookmark clickOnSaveBookmarkImage(composeTestRule) - openBookmarkScreen(kiwixMainActivity as CoreMainActivity) + openBookmarkScreen(kiwixMainActivity as CoreMainActivity, composeTestRule) assertBookmarkSaved(composeTestRule) pressBack() // Test removing bookmark @@ -154,7 +159,7 @@ class LibkiwixBookmarkTest : BaseActivityTest() { kiwixMainActivity = it } topLevel { - clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity) { + clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertBookmarkSaved(composeTestRule) } } @@ -184,41 +189,39 @@ class LibkiwixBookmarkTest : BaseActivityTest() { pressBack() } composeTestRule.waitUntilTimeout() - // TODO refactor this wih compose based navController. - // val navHostFragment: NavHostFragment = - // kiwixMainActivity.supportFragmentManager - // .findFragmentById(R.id.nav_host_fragment) as NavHostFragment - // val coreReaderFragment = navHostFragment.childFragmentManager.fragments[0] as CoreReaderFragment - // val libKiwixBook = - // Book().apply { - // update(coreReaderFragment.zimReaderContainer?.zimFileReader?.jniKiwixReader) - // } - // val bookmarkList = arrayListOf() - // for (i in 1..500) { - // val bookmark = - // Bookmark().apply { - // bookId = coreReaderFragment.zimReaderContainer?.zimFileReader?.id - // title = "bookmark$i" - // url = "http://kiwix.org/demoBookmark$i" - // bookTitle = libKiwixBook.title - // } - // val libkiwixItem = - // LibkiwixBookmarkItem( - // bookmark, - // coreReaderFragment.zimReaderContainer?.zimFileReader?.favicon, - // coreReaderFragment.zimReaderContainer?.zimFileReader?.zimReaderSource - // ) - // runBlocking { - // coreReaderFragment.libkiwixBookmarks?.saveBookmark(libkiwixItem).also { - // bookmarkList.add(libkiwixItem) - // } - // } - // } - // bookmarks { - // // test all the saved bookmarks are showing on the bookmarks screen - // openBookmarkScreen() - // testAllBookmarkShowing(bookmarkList, composeTestRule) - // } + val coreReaderFragment = kiwixMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() + val libKiwixBook = + Book().apply { + update(coreReaderFragment?.zimReaderContainer?.zimFileReader?.jniKiwixReader) + } + val bookmarkList = arrayListOf() + for (i in 1..500) { + val bookmark = + Bookmark().apply { + bookId = coreReaderFragment?.zimReaderContainer?.zimFileReader?.id + title = "bookmark$i" + url = "http://kiwix.org/demoBookmark$i" + bookTitle = libKiwixBook.title + } + val libkiwixItem = + LibkiwixBookmarkItem( + bookmark, + coreReaderFragment?.zimReaderContainer?.zimFileReader?.favicon, + coreReaderFragment?.zimReaderContainer?.zimFileReader?.zimReaderSource + ) + runBlocking { + coreReaderFragment?.libkiwixBookmarks?.saveBookmark(libkiwixItem).also { + bookmarkList.add(libkiwixItem) + } + } + } + bookmarks { + // test all the saved bookmarks are showing on the bookmarks screen + openBookmarkScreen(kiwixMainActivity as CoreMainActivity, composeTestRule) + testAllBookmarkShowing(bookmarkList, composeTestRule) + } } private fun getZimFile(): File { diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/history/NavigationHistoryRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/history/NavigationHistoryRobot.kt index de062da18..107556bfb 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/history/NavigationHistoryRobot.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/history/NavigationHistoryRobot.kt @@ -19,9 +19,9 @@ package org.kiwix.kiwixmobile.page.history import android.util.Log import androidx.compose.ui.test.assertTextEquals +import androidx.compose.ui.test.isDisplayed import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.longClick -import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput @@ -34,6 +34,8 @@ import com.adevinta.android.barista.interaction.BaristaSleepInteractions import junit.framework.AssertionFailedError import org.kiwix.kiwixmobile.BaseRobot import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.main.reader.READER_BOTTOM_BAR_NEXT_SCREEN_BUTTON_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.reader.READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG import org.kiwix.kiwixmobile.core.main.reader.READER_SCREEN_TESTING_TAG import org.kiwix.kiwixmobile.core.main.reader.TAB_SWITCHER_VIEW_TESTING_TAG import org.kiwix.kiwixmobile.core.page.DELETE_MENU_ICON_TESTING_TAG @@ -41,6 +43,7 @@ import org.kiwix.kiwixmobile.core.ui.components.TOOLBAR_TITLE_TESTING_TAG import org.kiwix.kiwixmobile.core.utils.dialog.ALERT_DIALOG_TITLE_TEXT_TESTING_TAG import org.kiwix.kiwixmobile.main.BOTTOM_NAV_READER_ITEM_TESTING_TAG import org.kiwix.kiwixmobile.testutils.TestUtils +import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout @@ -99,9 +102,12 @@ class NavigationHistoryRobot : BaseRobot() { fun longClickOnBackwardButton(composeTestRule: ComposeContentTestRule) { composeTestRule.apply { - waitUntilTimeout() + waitForIdle() + waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG).isDisplayed() + } testFlakyView({ - onNodeWithContentDescription(context.getString(R.string.go_to_previous_page)) + onNodeWithTag(READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG) .performTouchInput { longClick() } }) } @@ -109,9 +115,12 @@ class NavigationHistoryRobot : BaseRobot() { fun longClickOnForwardButton(composeTestRule: ComposeContentTestRule) { composeTestRule.apply { - waitUntilTimeout() + waitForIdle() + waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_NEXT_SCREEN_BUTTON_TESTING_TAG).isDisplayed() + } testFlakyView({ - onNodeWithContentDescription(context.getString(R.string.go_to_next_page)) + onNodeWithTag(READER_BOTTOM_BAR_NEXT_SCREEN_BUTTON_TESTING_TAG) .performTouchInput { longClick() } }) } @@ -135,8 +144,11 @@ class NavigationHistoryRobot : BaseRobot() { fun clickOnBackwardButton(composeTestRule: ComposeContentTestRule) { composeTestRule.apply { - waitUntilTimeout() - onNodeWithContentDescription(context.getString(R.string.go_to_previous_page)) + waitForIdle() + waitUntil(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG).isDisplayed() + } + onNodeWithTag(READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG) .performClick() } } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/shortcuts/GetContentShortcutTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/shortcuts/GetContentShortcutTest.kt index 16f199a86..1c35b1b05 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/shortcuts/GetContentShortcutTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/shortcuts/GetContentShortcutTest.kt @@ -142,26 +142,26 @@ class GetContentShortcutTest { assertReceiveFileTitleVisible(composeTestRule) } } - clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity) { + clickBookmarksOnNavDrawer(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertBookMarksDisplayed(composeTestRule) clickOnTrashIcon(composeTestRule) assertDeleteBookmarksDialogDisplayed(composeTestRule) } - clickHistoryOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHistoryOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertHistoryDisplayed(composeTestRule) clickOnTrashIcon(composeTestRule) assertDeleteHistoryDialogDisplayed(composeTestRule) } - clickHostBooksOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHostBooksOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertMenuWifiHotspotDisplayed(composeTestRule) } - clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickSettingsOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { assertMenuSettingsDisplayed(composeTestRule) } - clickHelpOnSideNav(kiwixMainActivity as CoreMainActivity) { + clickHelpOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) { HelpRobot().assertToolbarDisplayed(composeTestRule) } - clickSupportKiwixOnSideNav(kiwixMainActivity as CoreMainActivity) + clickSupportKiwixOnSideNav(kiwixMainActivity as CoreMainActivity, composeTestRule) pressBack() } } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/utils/StandardActions.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/utils/StandardActions.kt index 9db28dc64..e0b2a9c26 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/utils/StandardActions.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/utils/StandardActions.kt @@ -24,7 +24,6 @@ import androidx.test.espresso.Espresso import androidx.test.espresso.action.ViewActions import androidx.test.espresso.matcher.ViewMatchers import com.adevinta.android.barista.interaction.BaristaDialogInteractions -import com.adevinta.android.barista.interaction.BaristaSleepInteractions import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_SETTINGS_ITEM_TESTING_TAG import org.kiwix.kiwixmobile.core.utils.files.Log @@ -43,12 +42,10 @@ object StandardActions { } fun openDrawer(coreMainActivity: CoreMainActivity) { - BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS.toLong()) coreMainActivity.openNavigationDrawer() } fun closeDrawer(coreMainActivity: CoreMainActivity) { - BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS.toLong()) coreMainActivity.closeNavigationDrawer() } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt index 47f4c217e..75ddd674d 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt @@ -20,7 +20,6 @@ package org.kiwix.kiwixmobile.ui import android.net.Uri import android.os.Bundle -import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api @@ -40,6 +39,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument import androidx.navigation.navDeepLink +import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.main.BOOKMARK_FRAGMENT import org.kiwix.kiwixmobile.core.main.DOWNLOAD_FRAGMENT import org.kiwix.kiwixmobile.core.main.FIND_IN_PAGE_SEARCH_STRING @@ -121,7 +121,7 @@ fun KiwixNavGraph( val shouldOpenInNewTab = backStackEntry.arguments?.getBoolean(SHOULD_OPEN_IN_NEW_TAB) ?: false val searchItemTitle = backStackEntry.arguments?.getString(SEARCH_ITEM_TITLE_KEY).orEmpty() - FragmentContainer { + FragmentContainer(R.id.readerFragmentContainer) { KiwixReaderFragment().apply { arguments = Bundle().apply { putString(ZIM_FILE_URI_KEY, zimFileUri) @@ -144,7 +144,7 @@ fun KiwixNavGraph( ) { backStackEntry -> val zimFileUri = backStackEntry.arguments?.getString(ZIM_FILE_URI_KEY).orEmpty() - FragmentContainer { + FragmentContainer(R.id.localLibraryFragmentContainer) { LocalLibraryFragment().apply { arguments = Bundle().apply { putString(ZIM_FILE_URI_KEY, zimFileUri) @@ -153,32 +153,32 @@ fun KiwixNavGraph( } } composable(KiwixDestination.Downloads.route) { - FragmentContainer { + FragmentContainer(R.id.downloadFragmentContainer) { OnlineLibraryFragment() } } composable(KiwixDestination.Bookmarks.route) { - FragmentContainer { + FragmentContainer(R.id.bookmarksFragmentContainer) { BookmarksFragment() } } composable(KiwixDestination.Notes.route) { - FragmentContainer { + FragmentContainer(R.id.notesFragmentContainer) { NotesFragment() } } composable(KiwixDestination.Intro.route) { - FragmentContainer { + FragmentContainer(R.id.introFragmentContainer) { IntroFragment() } } composable(KiwixDestination.History.route) { - FragmentContainer { + FragmentContainer(R.id.historyFragmentContainer) { HistoryFragment() } } composable(KiwixDestination.Language.route) { - FragmentContainer { + FragmentContainer(R.id.languageFragmentContainer) { LanguageFragment() } } @@ -186,17 +186,17 @@ fun KiwixNavGraph( KiwixDestination.ZimHost.route, deepLinks = listOf(navDeepLink { uriPattern = ZIM_HOST_NAV_DEEP_LINK }) ) { - FragmentContainer { + FragmentContainer(R.id.zimHostFragmentContainer) { ZimHostFragment() } } composable(KiwixDestination.Help.route) { - FragmentContainer { + FragmentContainer(R.id.helpFragmentContainer) { KiwixHelpFragment() } } composable(KiwixDestination.Settings.route) { - FragmentContainer { + FragmentContainer(R.id.settingsFragmentContainer) { KiwixSettingsFragment() } } @@ -221,7 +221,7 @@ fun KiwixNavGraph( val isOpenedFromTabSwitcher = backStackEntry.arguments?.getBoolean(TAG_FROM_TAB_SWITCHER) ?: false val isVoice = backStackEntry.arguments?.getBoolean(EXTRA_IS_WIDGET_VOICE) ?: false - FragmentContainer { + FragmentContainer(R.id.searchFragmentContainer) { SearchFragment().apply { arguments = Bundle().apply { putString(NAV_ARG_SEARCH_STRING, searchString) @@ -247,7 +247,7 @@ fun KiwixNavGraph( Uri.decode(it).toUri() } - FragmentContainer { + FragmentContainer(R.id.localFileTransferFragmentContainer) { LocalFileTransferFragment().apply { arguments = Bundle().apply { putParcelableArray( @@ -264,24 +264,23 @@ fun KiwixNavGraph( @OptIn(ExperimentalMaterial3Api::class) @Composable fun FragmentContainer( + fragmentId: Int, fragmentProvider: () -> Fragment ) { val context = LocalContext.current val fragmentManager = remember { (context as AppCompatActivity).supportFragmentManager } - val viewId = remember { View.generateViewId() } + val fragment = remember { fragmentProvider() } AndroidView( modifier = Modifier.fillMaxSize(), factory = { ctx -> FragmentContainerView(ctx).apply { - id = viewId + id = fragmentId doOnAttach { fragmentManager.commit { - if (fragmentManager.findFragmentById(viewId) == null) { - add(viewId, fragmentProvider()) - } + replace(fragmentId, fragment) } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index 636e647b9..a4416c75c 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -89,8 +89,12 @@ const val HELP_FRAGMENT = "helpFragment" const val SETTINGS_FRAGMENT = "settingsFragment" const val SEARCH_FRAGMENT = "searchFragment" const val LOCAL_FILE_TRANSFER_FRAGMENT = "localFileTransferFragment" + +// Zim host deep link for opening the ZimHost fragment from notification. const val ZIM_HOST_DEEP_LINK_SCHEME = "kiwix" const val ZIM_HOST_NAV_DEEP_LINK = "$ZIM_HOST_DEEP_LINK_SCHEME://zimhost" + +// Left drawer items testing tag. const val LEFT_DRAWER_BOOKMARK_ITEM_TESTING_TAG = "leftDrawerBookmarkItemTestingTag" const val LEFT_DRAWER_HISTORY_ITEM_TESTING_TAG = "leftDrawerHistoryItemTestingTag" const val LEFT_DRAWER_NOTES_ITEM_TESTING_TAG = "leftDrawerNotesItemTestingTag" diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainDrawerMenu.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainDrawerMenu.kt index ca9511fe3..1cc39dbe6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainDrawerMenu.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainDrawerMenu.kt @@ -35,6 +35,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.ui.components.ONE import org.kiwix.kiwixmobile.core.ui.models.IconItem @@ -105,5 +107,6 @@ private fun DrawerMenuItemView(item: DrawerMenuItem) { modifier = Modifier .fillMaxWidth() .clickable { item.onClick.invoke() } + .semantics { testTag = item.testingTag } ) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/ReaderScreen.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/ReaderScreen.kt index af6e483df..d01fc6753 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/ReaderScreen.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/ReaderScreen.kt @@ -167,6 +167,14 @@ const val TAB_SWITCHER_VIEW_TESTING_TAG = "tabSwitcherViewTestingTag" const val READER_SCREEN_TESTING_TAG = "readerScreenTestingTag" const val CLOSE_ALL_TABS_BUTTON_TESTING_TAG = "closeAllTabsButtonTestingTag" const val TAB_TITLE_TESTING_TAG = "tabTitleTestingTag" +const val READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG = "readerBottomBarBookmarkButtonTestingTag" +const val READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG = + "readerBottomBarPreviousScreenButtonTestingTag" +const val READER_BOTTOM_BAR_NEXT_SCREEN_BUTTON_TESTING_TAG = + "readerBottomBarNextScreenButtonTestingTag" +const val READER_BOTTOM_BAR_HOME_BUTTON_TESTING_TAG = "readerBottomBarHomeButtonTestingTag" +const val READER_BOTTOM_BAR_TABLE_CONTENT_BUTTON_TESTING_TAG = + "readerBottomBarTableContentButtonTestingTag" @OptIn(ExperimentalMaterial3Api::class) @Suppress("ComposableLambdaParameterNaming", "LongMethod") @@ -666,7 +674,8 @@ private fun BottomAppBarOfReaderScreen( onClick = bookmarkButtonItem.first, onLongClick = bookmarkButtonItem.second, buttonIcon = bookmarkButtonItem.third, - contentDescription = stringResource(R.string.bookmarks) + contentDescription = stringResource(R.string.bookmarks), + testingTag = READER_BOTTOM_BAR_BOOKMARK_BUTTON_TESTING_TAG ) // Back Icon(for going to previous page) BottomAppBarButtonIcon( @@ -674,13 +683,15 @@ private fun BottomAppBarOfReaderScreen( onLongClick = previousPageButtonItem.second, buttonIcon = Drawable(R.drawable.ic_keyboard_arrow_left_24dp), shouldEnable = previousPageButtonItem.third, - contentDescription = stringResource(R.string.go_to_previous_page) + contentDescription = stringResource(R.string.go_to_previous_page), + testingTag = READER_BOTTOM_BAR_PREVIOUS_SCREEN_BUTTON_TESTING_TAG ) // Home Icon(to open the home page of ZIM file) BottomAppBarButtonIcon( onClick = onHomeButtonClick, buttonIcon = Drawable(R.drawable.action_home), - contentDescription = stringResource(R.string.menu_home) + contentDescription = stringResource(R.string.menu_home), + testingTag = READER_BOTTOM_BAR_HOME_BUTTON_TESTING_TAG ) // Forward Icon(for going to next page) BottomAppBarButtonIcon( @@ -688,14 +699,16 @@ private fun BottomAppBarOfReaderScreen( onLongClick = nextPageButtonItem.second, buttonIcon = Drawable(R.drawable.ic_keyboard_arrow_right_24dp), shouldEnable = nextPageButtonItem.third, - contentDescription = stringResource(R.string.go_to_next_page) + contentDescription = stringResource(R.string.go_to_next_page), + testingTag = READER_BOTTOM_BAR_NEXT_SCREEN_BUTTON_TESTING_TAG ) // Toggle Icon(to open the table of content in right side bar) BottomAppBarButtonIcon( shouldEnable = tocButtonItem.first, onClick = tocButtonItem.second, buttonIcon = Drawable(R.drawable.ic_toc_24dp), - contentDescription = stringResource(R.string.table_of_contents) + contentDescription = stringResource(R.string.table_of_contents), + testingTag = READER_BOTTOM_BAR_TABLE_CONTENT_BUTTON_TESTING_TAG ) } } @@ -707,7 +720,8 @@ private fun BottomAppBarButtonIcon( onLongClick: (() -> Unit)? = null, buttonIcon: IconItem, shouldEnable: Boolean = true, - contentDescription: String + contentDescription: String, + testingTag: String ) { Box( modifier = Modifier @@ -717,7 +731,7 @@ private fun BottomAppBarButtonIcon( onClick = onClick, onLongClick = onLongClick, enabled = shouldEnable - ), + ).testTag(testingTag), contentAlignment = Alignment.Center ) { Icon( diff --git a/core/src/main/res/values/ids.xml b/core/src/main/res/values/ids.xml index 7e2de03d3..9cfbe68af 100644 --- a/core/src/main/res/values/ids.xml +++ b/core/src/main/res/values/ids.xml @@ -1,8 +1,16 @@ - - - - - + + + + + + + + + + + + + diff --git a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt index a2de0b06d..8799f9d89 100644 --- a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt +++ b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt @@ -24,7 +24,6 @@ import android.content.res.AssetFileDescriptor import androidx.compose.ui.test.junit4.createComposeRule import androidx.core.content.edit import androidx.lifecycle.Lifecycle -import androidx.navigation.fragment.NavHostFragment import androidx.preference.PreferenceManager import androidx.test.core.app.ActivityScenario import androidx.test.espresso.Espresso.pressBack @@ -48,6 +47,7 @@ import org.kiwix.kiwixmobile.core.di.modules.CALL_TIMEOUT import org.kiwix.kiwixmobile.core.di.modules.CONNECTION_TIMEOUT import org.kiwix.kiwixmobile.core.di.modules.READ_TIMEOUT import org.kiwix.kiwixmobile.core.di.modules.USER_AGENT +import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.search.SearchFragment import org.kiwix.kiwixmobile.core.search.viewmodel.Action @@ -236,34 +236,31 @@ class SearchFragmentTestForCustomApp { openSearchWithQuery(searchTerms[0]) // wait for searchFragment become visible on screen. delay(2000) - val navHostFragment: NavHostFragment = - customMainActivity.supportFragmentManager - .findFragmentById( - customMainActivity.activityCustomMainBinding.customNavController.id - ) as NavHostFragment - val searchFragment = navHostFragment.childFragmentManager.fragments[0] as SearchFragment + val searchFragment = customMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() for (i in 1..100) { // This will execute the render method 100 times frequently. val searchTerm = searchTerms[i % searchTerms.size] - searchFragment.searchViewModel.actions.trySend(Action.Filter(searchTerm)).isSuccess + searchFragment?.searchViewModel?.actions?.trySend(Action.Filter(searchTerm))?.isSuccess } for (i in 1..100) { // this will execute the render method 100 times with 100MS delay. delay(100) val searchTerm = searchTerms[i % searchTerms.size] - searchFragment.searchViewModel.actions.trySend(Action.Filter(searchTerm)).isSuccess + searchFragment?.searchViewModel?.actions?.trySend(Action.Filter(searchTerm))?.isSuccess } for (i in 1..100) { // this will execute the render method 100 times with 200MS delay. delay(200) val searchTerm = searchTerms[i % searchTerms.size] - searchFragment.searchViewModel.actions.trySend(Action.Filter(searchTerm)).isSuccess + searchFragment?.searchViewModel?.actions?.trySend(Action.Filter(searchTerm))?.isSuccess } for (i in 1..100) { // this will execute the render method 100 times with 200MS delay. delay(300) val searchTerm = searchTerms[i % searchTerms.size] - searchFragment.searchViewModel.actions.trySend(Action.Filter(searchTerm)).isSuccess + searchFragment?.searchViewModel?.actions?.trySend(Action.Filter(searchTerm))?.isSuccess } } @@ -293,12 +290,12 @@ class SearchFragmentTestForCustomApp { openZimFileInReader(zimFile = downloadingZimFile) search { // click on home button to load the main page of ZIM file. - clickOnHomeButton(composeTestRule, customMainActivity) + clickOnHomeButton(composeTestRule) // click on an article to load the other page. clickOnAFoolForYouArticle() assertAFoolForYouArticleLoaded() // open note screen. - openNoteFragment() + openNoteFragment(customMainActivity as CoreMainActivity, composeTestRule) pressBack() // after came back check the previously loaded article is still showing or not. assertAFoolForYouArticleLoaded() @@ -316,21 +313,18 @@ class SearchFragmentTestForCustomApp { zimFile: File? = null ) { UiThreadStatement.runOnUiThread { - val navHostFragment: NavHostFragment = - customMainActivity.supportFragmentManager - .findFragmentById( - customMainActivity.activityCustomMainBinding.customNavController.id - ) as NavHostFragment val customReaderFragment = - navHostFragment.childFragmentManager.fragments[0] as CustomReaderFragment + customMainActivity.supportFragmentManager.fragments + .filterIsInstance() + .firstOrNull() runBlocking { assetFileDescriptor?.let { - customReaderFragment.openZimFile( + customReaderFragment?.openZimFile( ZimReaderSource(assetFileDescriptorList = listOf(assetFileDescriptor)), true ) } ?: run { - customReaderFragment.openZimFile( + customReaderFragment?.openZimFile( ZimReaderSource(zimFile), true ) diff --git a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchRobot.kt b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchRobot.kt index 46f23ef4e..3e74e9e93 100644 --- a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchRobot.kt +++ b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchRobot.kt @@ -21,17 +21,13 @@ package org.kiwix.kiwixmobile.custom.search import android.view.KeyEvent import androidx.compose.ui.test.assert import androidx.compose.ui.test.hasText +import androidx.compose.ui.test.isDisplayed import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.onAllNodesWithTag -import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextClearance import androidx.compose.ui.test.performTextInput -import androidx.core.view.GravityCompat -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.web.assertion.WebViewAssertions.webMatches import androidx.test.espresso.web.sugar.Web import androidx.test.espresso.web.sugar.Web.onWebView @@ -41,17 +37,17 @@ import androidx.test.espresso.web.webdriver.DriverAtoms.getText import androidx.test.espresso.web.webdriver.DriverAtoms.webClick import androidx.test.espresso.web.webdriver.Locator import androidx.test.uiautomator.UiDevice -import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawerWithGravity import com.adevinta.android.barista.interaction.BaristaSleepInteractions import org.hamcrest.CoreMatchers.containsString -import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.LEFT_DRAWER_NOTES_ITEM_TESTING_TAG +import org.kiwix.kiwixmobile.core.main.reader.READER_BOTTOM_BAR_HOME_BUTTON_TESTING_TAG import org.kiwix.kiwixmobile.core.page.SEARCH_ICON_TESTING_TAG import org.kiwix.kiwixmobile.core.search.SEARCH_FIELD_TESTING_TAG import org.kiwix.kiwixmobile.core.search.SEARCH_ITEM_TESTING_TAG -import org.kiwix.kiwixmobile.custom.R.id -import org.kiwix.kiwixmobile.custom.main.CustomMainActivity import org.kiwix.kiwixmobile.custom.testutils.TestUtils import org.kiwix.kiwixmobile.custom.testutils.TestUtils.TEST_PAUSE_MS +import org.kiwix.kiwixmobile.custom.testutils.TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST import org.kiwix.kiwixmobile.custom.testutils.TestUtils.testFlakyView import org.kiwix.kiwixmobile.custom.testutils.TestUtils.waitUntilTimeout @@ -146,12 +142,13 @@ class SearchRobot { }) } - fun clickOnHomeButton( - composeTestRule: ComposeContentTestRule, - customMainActivity: CustomMainActivity - ) { + fun clickOnHomeButton(composeTestRule: ComposeContentTestRule) { composeTestRule.apply { - onNodeWithContentDescription(customMainActivity.getString(R.string.menu_home)) + waitForIdle() + waitUntil(TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong()) { + onNodeWithTag(READER_BOTTOM_BAR_HOME_BUTTON_TESTING_TAG).isDisplayed() + } + onNodeWithTag(READER_BOTTOM_BAR_HOME_BUTTON_TESTING_TAG) .performClick() } } @@ -182,9 +179,16 @@ class SearchRobot { }) } - fun openNoteFragment() { - BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS.toLong()) - openDrawerWithGravity(id.custom_drawer_container, GravityCompat.START) - testFlakyView({ onView(withText(R.string.pref_notes)).perform(click()) }) + fun openNoteFragment( + coreMainActivity: CoreMainActivity, + composeTestRule: ComposeContentTestRule + ) { + coreMainActivity.openNavigationDrawer() + testFlakyView({ + composeTestRule.apply { + waitUntilTimeout() + onNodeWithTag(LEFT_DRAWER_NOTES_ITEM_TESTING_TAG).performClick() + } + }) } } diff --git a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/testutils/TestUtils.kt b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/testutils/TestUtils.kt index 671d823d3..bbfc05d6c 100644 --- a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/testutils/TestUtils.kt +++ b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/testutils/TestUtils.kt @@ -33,7 +33,7 @@ import java.util.TimerTask object TestUtils { private const val TAG = "TESTUTILS" - const val TEST_PAUSE_MS_FOR_SEARCH_TEST = 1000 + const val TEST_PAUSE_MS_FOR_SEARCH_TEST = 10000 const val TEST_PAUSE_MS = 3000 @JvmStatic diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomNavGraph.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomNavGraph.kt index 09dbc48d5..297bebfe6 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomNavGraph.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomNavGraph.kt @@ -20,7 +20,6 @@ package org.kiwix.kiwixmobile.custom.main import android.net.Uri import android.os.Bundle -import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api @@ -38,6 +37,7 @@ import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument +import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.main.BOOKMARK_FRAGMENT import org.kiwix.kiwixmobile.core.main.DOWNLOAD_FRAGMENT import org.kiwix.kiwixmobile.core.main.FIND_IN_PAGE_SEARCH_STRING @@ -95,7 +95,7 @@ fun CustomNavGraph( val pageUrl = backStackEntry.arguments?.getString(PAGE_URL_KEY).orEmpty() val shouldOpenInNewTab = backStackEntry.arguments?.getBoolean(SHOULD_OPEN_IN_NEW_TAB) ?: false - FragmentContainer { + FragmentContainer(R.id.readerFragmentContainer) { CustomReaderFragment().apply { arguments = Bundle().apply { putString(FIND_IN_PAGE_SEARCH_STRING, findInPageSearchString) @@ -106,32 +106,32 @@ fun CustomNavGraph( } } composable(CustomDestination.History.route) { - FragmentContainer { + FragmentContainer(R.id.historyFragmentContainer) { HistoryFragment() } } composable(CustomDestination.Notes.route) { - FragmentContainer { + FragmentContainer(R.id.notesFragmentContainer) { NotesFragment() } } composable(CustomDestination.Bookmarks.route) { - FragmentContainer { + FragmentContainer(R.id.bookmarksFragmentContainer) { BookmarksFragment() } } composable(CustomDestination.Help.route) { - FragmentContainer { + FragmentContainer(R.id.helpFragmentContainer) { CustomHelpFragment() } } composable(CustomDestination.Settings.route) { - FragmentContainer { + FragmentContainer(R.id.settingsFragmentContainer) { CustomSettingsFragment() } } composable(CustomDestination.Downloads.route) { - FragmentContainer { + FragmentContainer(R.id.downloadFragmentContainer) { CustomDownloadFragment() } } @@ -156,7 +156,7 @@ fun CustomNavGraph( val isOpenedFromTabSwitcher = backStackEntry.arguments?.getBoolean(TAG_FROM_TAB_SWITCHER) ?: false val isVoice = backStackEntry.arguments?.getBoolean(EXTRA_IS_WIDGET_VOICE) ?: false - FragmentContainer { + FragmentContainer(R.id.searchFragmentContainer) { SearchFragment().apply { arguments = Bundle().apply { putString(NAV_ARG_SEARCH_STRING, searchString) @@ -172,24 +172,23 @@ fun CustomNavGraph( @OptIn(ExperimentalMaterial3Api::class) @Composable fun FragmentContainer( + fragmentId: Int, fragmentProvider: () -> Fragment ) { val context = LocalContext.current val fragmentManager = remember { (context as AppCompatActivity).supportFragmentManager } - val viewId = remember { View.generateViewId() } + val fragment = remember { fragmentProvider() } AndroidView( modifier = Modifier.fillMaxSize(), factory = { ctx -> FragmentContainerView(ctx).apply { - id = viewId + id = fragmentId doOnAttach { fragmentManager.commit { - if (fragmentManager.findFragmentById(viewId) == null) { - add(viewId, fragmentProvider()) - } + replace(fragmentId, fragment) } } }