Added the downloadZIMFileInBackground for testing the download when application is in background.

* Removed some unused code from project.
This commit is contained in:
MohitMaliFtechiz 2025-08-11 22:24:26 +05:30
parent 7a828617b0
commit 16ea02274b
8 changed files with 85 additions and 40 deletions

View File

@ -26,6 +26,7 @@ import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.onAllNodesWithTag import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextClearance
import androidx.compose.ui.test.performTextInput import androidx.compose.ui.test.performTextInput
import applyWithViewHierarchyPrinting import applyWithViewHierarchyPrinting
import org.kiwix.kiwixmobile.BaseRobot import org.kiwix.kiwixmobile.BaseRobot
@ -57,6 +58,7 @@ fun downloadRobot(func: DownloadRobot.() -> Unit) =
DownloadRobot().applyWithViewHierarchyPrinting(func) DownloadRobot().applyWithViewHierarchyPrinting(func)
class DownloadRobot : BaseRobot() { class DownloadRobot : BaseRobot() {
private val searchZIMFileTitle = "Zapping Sauvage"
fun clickLibraryOnBottomNav(composeTestRule: ComposeContentTestRule) { fun clickLibraryOnBottomNav(composeTestRule: ComposeContentTestRule) {
composeTestRule.apply { composeTestRule.apply {
waitUntilTimeout() waitUntilTimeout()
@ -135,6 +137,27 @@ class DownloadRobot : BaseRobot() {
} }
} }
fun searchZappingSauvageFile(composeTestRule: ComposeContentTestRule) {
testFlakyView({
composeTestRule.apply {
waitForIdle() // let the compose settle.
runCatching {
// if searchView already opened do nothing.
onNodeWithTag(ONLINE_LIBRARY_SEARCH_VIEW_CLOSE_BUTTON_TESTING_TAG).assertExists()
}.onFailure {
// if searchView is not opened then open it.
onNodeWithTag(SEARCH_ICON_TESTING_TAG).performClick()
}
waitForIdle()
onNodeWithTag(ONLINE_LIBRARY_SEARCH_VIEW_TESTING_TAG).apply {
performTextClearance()
performTextInput(searchZIMFileTitle)
}
waitUntilTimeout(TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong())
}
})
}
private fun refreshOnlineList(composeTestRule: ComposeContentTestRule) { private fun refreshOnlineList(composeTestRule: ComposeContentTestRule) {
composeTestRule.refresh() composeTestRule.refresh()
} }

View File

@ -17,6 +17,9 @@
*/ */
package org.kiwix.kiwixmobile.download package org.kiwix.kiwixmobile.download
import android.accessibilityservice.AccessibilityService
import android.content.Context
import android.content.Intent
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
@ -24,6 +27,7 @@ import androidx.core.content.edit
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.IdlingPolicies import androidx.test.espresso.IdlingPolicies
import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.accessibility.AccessibilityChecks import androidx.test.espresso.accessibility.AccessibilityChecks
@ -59,10 +63,13 @@ import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout
import org.kiwix.kiwixmobile.ui.KiwixDestination import org.kiwix.kiwixmobile.ui.KiwixDestination
import org.kiwix.kiwixmobile.utils.KiwixIdlingResource.Companion.getInstance import org.kiwix.kiwixmobile.utils.KiwixIdlingResource.Companion.getInstance
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
const val TWO_MINUTES_IN_MILLISECONDS = 2 * 60 * 1000
@LargeTest @LargeTest
class DownloadTest : BaseActivityTest() { class DownloadTest : BaseActivityTest() {
@Rule(order = RETRY_RULE_ORDER) @Rule(order = RETRY_RULE_ORDER)
@ -233,6 +240,52 @@ class DownloadTest : BaseActivityTest() {
} }
} }
@Test
fun downloadZIMFileInBackground() {
activityScenario.onActivity {
kiwixMainActivity = it
it.navigate(KiwixDestination.Library.route)
}
// delete all the ZIM files showing in the LocalLibrary
// screen to properly test the scenario.
library {
refreshList(composeTestRule)
waitUntilZimFilesRefreshing(composeTestRule)
deleteZimIfExists(composeTestRule)
}
downloadRobot {
clickDownloadOnBottomNav(composeTestRule)
waitForDataToLoad(composeTestRule = composeTestRule)
stopDownloadIfAlreadyStarted(composeTestRule)
searchZappingSauvageFile(composeTestRule)
downloadZimFile(composeTestRule)
assertDownloadStart(composeTestRule)
}
// press the home button so that application goes into background
InstrumentationRegistry.getInstrumentation().uiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_HOME
)
// wait for 2 minutes to download the ZIM file in background.
composeTestRule.waitUntilTimeout(TWO_MINUTES_IN_MILLISECONDS.toLong())
// relaunch the application.
val context = ApplicationProvider.getApplicationContext<Context>()
val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
context.startActivity(intent)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
activityScenario.onActivity {
kiwixMainActivity = it
it.navigate(KiwixDestination.Library.route)
}
library {
refreshList(composeTestRule)
waitUntilZimFilesRefreshing(composeTestRule)
downloadRobot {
checkIfZimFileDownloaded(composeTestRule)
}
}
}
@After @After
fun finish() { fun finish() {
IdlingRegistry.getInstance().unregister(getInstance()) IdlingRegistry.getInstance().unregister(getInstance())

View File

@ -144,8 +144,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
swipeRefreshItem = Pair(false, true), swipeRefreshItem = Pair(false, true),
scanningProgressItem = Pair(false, ZERO), scanningProgressItem = Pair(false, ZERO),
noFilesViewItem = Triple("", "", false), noFilesViewItem = Triple("", "", false),
actionMenuItems = listOf(), actionMenuItems = listOf()
bottomNavigationHeight = ZERO
) )
) )
@ -187,10 +186,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
setContent { setContent {
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
updateLibraryScreenState( updateLibraryScreenState(actionMenuItems = actionMenuItems())
bottomNavigationHeight = getBottomNavigationHeight(),
actionMenuItems = actionMenuItems()
)
} }
LocalLibraryScreen( LocalLibraryScreen(
listState = lazyListState, listState = lazyListState,
@ -266,8 +262,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
swipeRefreshItem: Pair<Boolean, Boolean>? = null, swipeRefreshItem: Pair<Boolean, Boolean>? = null,
scanningProgressItem: Pair<Boolean, Int>? = null, scanningProgressItem: Pair<Boolean, Int>? = null,
noFilesViewItem: Triple<String, String, Boolean>? = null, noFilesViewItem: Triple<String, String, Boolean>? = null,
actionMenuItems: List<ActionMenuItem>? = null, actionMenuItems: List<ActionMenuItem>? = null
bottomNavigationHeight: Int? = null
) { ) {
libraryScreenState.value = libraryScreenState.value.copy( libraryScreenState.value = libraryScreenState.value.copy(
fileSelectListState = fileSelectListState ?: libraryScreenState.value.fileSelectListState, fileSelectListState = fileSelectListState ?: libraryScreenState.value.fileSelectListState,
@ -276,9 +271,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
scanningProgressItem = scanningProgressItem scanningProgressItem = scanningProgressItem
?: libraryScreenState.value.scanningProgressItem, ?: libraryScreenState.value.scanningProgressItem,
noFilesViewItem = noFilesViewItem ?: libraryScreenState.value.noFilesViewItem, noFilesViewItem = noFilesViewItem ?: libraryScreenState.value.noFilesViewItem,
actionMenuItems = actionMenuItems ?: libraryScreenState.value.actionMenuItems, actionMenuItems = actionMenuItems ?: libraryScreenState.value.actionMenuItems
bottomNavigationHeight = bottomNavigationHeight
?: libraryScreenState.value.bottomNavigationHeight
) )
} }
@ -363,12 +356,6 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
} }
} }
// private fun getBottomNavigationView() =
// requireActivity().findViewById<BottomNavigationView>(R.id.bottom_nav_view)
private fun getBottomNavigationHeight() = ZERO
// getBottomNavigationView().measuredHeight
private fun filePickerButtonClick() { private fun filePickerButtonClick() {
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) { if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
showManageExternalStoragePermissionDialog() showManageExternalStoragePermissionDialog()

View File

@ -65,9 +65,5 @@ data class LocalLibraryScreenState(
/** /**
* Represents a list of action menu items available in the screen's top app bar. * Represents a list of action menu items available in the screen's top app bar.
*/ */
val actionMenuItems: List<ActionMenuItem>, val actionMenuItems: List<ActionMenuItem>
/**
* Stores the height of the bottom navigation bar in pixels.
*/
val bottomNavigationHeight: Int
) )

View File

@ -206,7 +206,9 @@ private fun BookSizeAndDateRow(item: BookItem) {
) { ) {
BookSize( BookSize(
Byte(item.book.size).humanReadable, Byte(item.book.size).humanReadable,
modifier = Modifier.weight(1f).testTag(ONLINE_BOOK_SIZE_TEXT_TESTING_TAG) modifier = Modifier
.weight(1f)
.testTag(ONLINE_BOOK_SIZE_TEXT_TESTING_TAG)
) )
BookDate(item.book.date) BookDate(item.book.date)
} }

View File

@ -58,7 +58,6 @@ import org.kiwix.kiwixmobile.core.base.BaseFragment
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
import org.kiwix.kiwixmobile.core.data.remote.KiwixService.Companion.ITEMS_PER_PAGE import org.kiwix.kiwixmobile.core.data.remote.KiwixService.Companion.ITEMS_PER_PAGE
import org.kiwix.kiwixmobile.core.downloader.Downloader import org.kiwix.kiwixmobile.core.downloader.Downloader
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.hasNotificationPermission import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.hasNotificationPermission
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isManageExternalStoragePermissionGranted import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isManageExternalStoragePermissionGranted
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate
@ -129,7 +128,6 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
isRefreshing = false, isRefreshing = false,
scanningProgressItem = Pair(false, ""), scanningProgressItem = Pair(false, ""),
noContentViewItem = Pair("", false), noContentViewItem = Pair("", false),
bottomNavigationHeight = ZERO,
onBookItemClick = { onBookItemClick(it) }, onBookItemClick = { onBookItemClick(it) },
availableSpaceCalculator = availableSpaceCalculator, availableSpaceCalculator = availableSpaceCalculator,
onRefresh = { refreshFragment(true) }, onRefresh = { refreshFragment(true) },
@ -209,12 +207,6 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
composeView = it composeView = it
} }
// private fun getBottomNavigationView() =
// requireActivity().findViewById<BottomNavigationView>(org.kiwix.kiwixmobile.R.id.bottom_nav_view)
private fun getBottomNavigationHeight() = ZERO
// getBottomNavigationView().measuredHeight
private fun onPauseResumeButtonClick(item: LibraryListItem.LibraryDownloadItem) { private fun onPauseResumeButtonClick(item: LibraryListItem.LibraryDownloadItem) {
context?.let { context -> context?.let { context ->
if (isNotConnected) { if (isNotConnected) {
@ -251,7 +243,6 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
onlineLibraryScreenState.value.update { onlineLibraryScreenState.value.update {
copy( copy(
bottomNavigationHeight = getBottomNavigationHeight(),
isSearchActive = isSearchActive, isSearchActive = isSearchActive,
scanningProgressItem = false to getString(R.string.reaching_remote_library) scanningProgressItem = false to getString(R.string.reaching_remote_library)
) )

View File

@ -30,10 +30,6 @@ data class OnlineLibraryScreenState(
* Manages the online library list state. * Manages the online library list state.
*/ */
val onlineLibraryList: List<LibraryListItem>?, val onlineLibraryList: List<LibraryListItem>?,
/**
* Stores the height of the bottom navigation bar in pixels.
*/
val bottomNavigationHeight: Int,
/** /**
* Controls the visibility and behavior of the "Pull to refresh" animation. * Controls the visibility and behavior of the "Pull to refresh" animation.
* *

View File

@ -60,7 +60,6 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
import org.kiwix.kiwixmobile.core.utils.ExternalLinkOpener import org.kiwix.kiwixmobile.core.utils.ExternalLinkOpener
import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower
import org.kiwix.kiwixmobile.core.utils.dialog.RateDialogHandler import org.kiwix.kiwixmobile.core.utils.dialog.RateDialogHandler
import org.kiwix.kiwixmobile.core.utils.files.Log
import javax.inject.Inject import javax.inject.Inject
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ -351,9 +350,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
} }
private fun activeFragments(): MutableList<Fragment> = private fun activeFragments(): MutableList<Fragment> =
supportFragmentManager.fragments.also { supportFragmentManager.fragments
Log.d("Fragments", "Found fragments: ${supportFragmentManager.fragments}")
}
fun navigate(action: NavDirections) { fun navigate(action: NavDirections) {
navController.currentDestination?.getAction(action.actionId)?.run { navController.currentDestination?.getAction(action.actionId)?.run {