Skip to content

Commit

Permalink
Merge pull request #3979 from kiwix/Fixes#3941
Browse files Browse the repository at this point in the history
Added the file picker in play store variant for move or copy the zim files in application's public directory
  • Loading branch information
kelson42 committed Sep 5, 2024
2 parents 992ebc9 + e5d7b2a commit 32d36d7
Show file tree
Hide file tree
Showing 16 changed files with 1,323 additions and 28 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ play {

dependencies {
androidTestImplementation(Libs.leakcanary_android_instrumentation)
testImplementation(Libs.kotlinx_coroutines_test)
}
task("generateVersionCodeAndName") {
val file = File("VERSION_INFO")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Kiwix Android
* Copyright (c) 2024 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.kiwix.kiwixmobile.localLibrary

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.espresso.web.sugar.Web
import androidx.test.espresso.web.webdriver.DriverAtoms
import androidx.test.espresso.web.webdriver.Locator
import applyWithViewHierarchyPrinting
import com.adevinta.android.barista.interaction.BaristaSleepInteractions
import junit.framework.AssertionFailedError
import org.kiwix.kiwixmobile.BaseRobot
import org.kiwix.kiwixmobile.Findable
import org.kiwix.kiwixmobile.Findable.StringId.TextId
import org.kiwix.kiwixmobile.R.id
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView

fun copyMoveFileHandler(func: CopyMoveFileHandlerRobot.() -> Unit) =
CopyMoveFileHandlerRobot().applyWithViewHierarchyPrinting(func)

class CopyMoveFileHandlerRobot : BaseRobot() {

fun assertCopyMovePermissionDialogDisplayed() {
isVisible(TextId(R.string.move_files_permission_dialog_title))
}

fun assertCopyMoveDialogDisplayed() {
isVisible(TextId(R.string.copy_move_files_dialog_description))
}

fun clickOnCopy() {
testFlakyView({
onView(withText(R.string.copy)).perform(click())
})
}

fun clickOnMove() {
testFlakyView({
onView(withText(R.string.move)).perform(click())
})
}

fun assertZimFileCopiedAndShowingIntoTheReader() {
pauseForBetterTestPerformance()
isVisible(Findable.ViewId(id.readerFragment))
testFlakyView({
Web.onWebView()
.withElement(
DriverAtoms.findElement(
Locator.XPATH,
"//*[contains(text(), 'Android_(operating_system)')]"
)
)
})
}

fun assertZimFileAddedInTheLocalLibrary() {
try {
onView(ViewMatchers.withId(id.file_management_no_files)).check(
ViewAssertions.matches(
ViewMatchers.isDisplayed()
)
)
throw RuntimeException("ZimFile not added in the local library")
} catch (e: AssertionFailedError) {
// do nothing zim file is added in the local library
}
}

fun pauseForBetterTestPerformance() {
BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
/*
* Kiwix Android
* Copyright (c) 2024 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.kiwix.kiwixmobile.localLibrary

import android.net.Uri
import android.os.Build
import androidx.core.content.ContextCompat
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.internal.runner.junit4.statement.UiThreadStatement
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Assert
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
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
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.LocalLibraryFragment
import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.zimManager.Fat32Checker
import org.kiwix.kiwixmobile.zimManager.FileWritingFileSystemChecker
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream

class CopyMoveFileHandlerTest : BaseActivityTest() {
@Rule
@JvmField
var retryRule = RetryRule()

private lateinit var sharedPreferenceUtil: SharedPreferenceUtil
private lateinit var kiwixMainActivity: KiwixMainActivity
private lateinit var selectedFile: File
private lateinit var destinationFile: File
private lateinit var parentFile: File

@Before
override fun waitForIdle() {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply {
if (TestUtils.isSystemUINotRespondingDialogVisible(this)) {
TestUtils.closeSystemDialogs(context, this)
}
waitForIdle()
}
PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false)
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
putBoolean(SharedPreferenceUtil.PREF_PLAY_STORE_RESTRICTION, false)
putString(SharedPreferenceUtil.PREF_LANG, "en")
}
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
sharedPreferenceUtil = SharedPreferenceUtil(context)
onActivity {
LanguageUtils.handleLocaleChange(
it,
"en",
sharedPreferenceUtil
)
parentFile = File(sharedPreferenceUtil.prefStorage)
}
}
}

@Test
fun testCopyingZimFileIntoPublicStorage() {
deleteAllFilesInDirectory(parentFile)
// Test the scenario in playStore build on Android 11 and above.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
selectedFile = getSelectedFile()
activityScenario.onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment)
}
copyMoveFileHandler(CopyMoveFileHandlerRobot::pauseForBetterTestPerformance)
// test with first launch
sharedPreferenceUtil.copyMoveZimFilePermissionDialog = false
showMoveFileToPublicDirectoryDialog()
// should show the permission dialog.
copyMoveFileHandler {
assertCopyMovePermissionDialogDisplayed()
clickOnCopy()
assertZimFileCopiedAndShowingIntoTheReader()
}
assertZimFileAddedInTheLocalLibrary()

// Test with second launch, this time permission dialog should not show.
// delete the parent directory so that all the previous file will be deleted.
deleteAllFilesInDirectory(parentFile)
showMoveFileToPublicDirectoryDialog()
// should show the copyMove dialog.
copyMoveFileHandler {
assertCopyMoveDialogDisplayed()
clickOnCopy()
assertZimFileCopiedAndShowingIntoTheReader()
}
assertZimFileAddedInTheLocalLibrary()
deleteAllFilesInDirectory(parentFile)
}
}

@Test
fun testMovingZimFileIntoPublicDirectory() {
deleteAllFilesInDirectory(parentFile)
// Test the scenario in playStore build on Android 11 and above.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
selectedFile = getSelectedFile()
activityScenario.onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment)
}
copyMoveFileHandler(CopyMoveFileHandlerRobot::pauseForBetterTestPerformance)
// test with first launch
sharedPreferenceUtil.copyMoveZimFilePermissionDialog = false
showMoveFileToPublicDirectoryDialog()
// should show the permission dialog.
copyMoveFileHandler {
assertCopyMovePermissionDialogDisplayed()
clickOnMove()
assertZimFileCopiedAndShowingIntoTheReader()
}
assertZimFileAddedInTheLocalLibrary()
// Test with second launch, this time permission dialog should not show.
// delete the parent directory so that all the previous file will be deleted.
deleteAllFilesInDirectory(parentFile)
selectedFile = getSelectedFile()
showMoveFileToPublicDirectoryDialog()
// should show the copyMove dialog.
copyMoveFileHandler {
assertCopyMoveDialogDisplayed()
clickOnMove()
assertZimFileCopiedAndShowingIntoTheReader()
}
assertZimFileAddedInTheLocalLibrary()
assertSelectedZimFileIsDeletedFromTheStorage(selectedFile)
deleteAllFilesInDirectory(parentFile)
}
}

private fun assertSelectedZimFileIsDeletedFromTheStorage(selectedZimFile: File) {
if (selectedZimFile.isFileExist()) {
throw RuntimeException("Selected zim file is not deleted from the storage")
}
}

private fun assertZimFileAddedInTheLocalLibrary() {
UiThreadStatement.runOnUiThread {
kiwixMainActivity.navigate(R.id.libraryFragment)
}
copyMoveFileHandler(CopyMoveFileHandlerRobot::assertZimFileAddedInTheLocalLibrary)
}

private fun showMoveFileToPublicDirectoryDialog() {
UiThreadStatement.runOnUiThread {
val navHostFragment: NavHostFragment =
kiwixMainActivity.supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val localLibraryFragment =
navHostFragment.childFragmentManager.fragments[0] as LocalLibraryFragment
localLibraryFragment.copyMoveFileHandler?.showMoveFileToPublicDirectoryDialog(
Uri.fromFile(selectedFile),
selectedFile
)
}
}

private fun getSelectedFile(): File {
val loadFileStream =
CopyMoveFileHandlerTest::class.java.classLoader.getResourceAsStream("testzim.zim")
val zimFile = File(
ContextCompat.getExternalFilesDirs(context, null)[0],
"testzim.zim"
)
if (zimFile.exists()) zimFile.delete()
zimFile.createNewFile()
loadFileStream.use { inputStream ->
val outputStream: OutputStream = FileOutputStream(zimFile)
outputStream.use { it ->
val buffer = ByteArray(inputStream.available())
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) {
it.write(buffer, 0, length)
}
}
}
return zimFile
}

@Test
fun testGetDestinationFile() {
activityScenario.onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment)
}
val selectedFileName = "testCopyMove.zim"
deleteAllFilesInDirectory(parentFile)
val copyMoveFileHandler = CopyMoveFileHandler(
kiwixMainActivity,
sharedPreferenceUtil,
AlertDialogShower(kiwixMainActivity),
StorageCalculator(sharedPreferenceUtil),
Fat32Checker(sharedPreferenceUtil, listOf(FileWritingFileSystemChecker()))
)
// test fileName when there is already a file available with same name.
// it should return different name
selectedFile = File(parentFile, selectedFileName).apply {
if (!isFileExist()) createNewFile()
}
copyMoveFileHandler.setSelectedFileAndUri(null, selectedFile)
destinationFile = copyMoveFileHandler.getDestinationFile()
Assert.assertNotEquals(
destinationFile.name,
selectedFile.name
)
Assert.assertEquals(
destinationFile.name,
"testCopyMove_1.zim"
)
deleteBothPreviousFiles()

// test when there is no zim file available in the storage it should return the same fileName
selectedFile = File(parentFile, selectedFileName)
copyMoveFileHandler.setSelectedFileAndUri(null, selectedFile)
destinationFile = copyMoveFileHandler.getDestinationFile()
Assert.assertEquals(
destinationFile.name,
selectedFile.name
)
deleteBothPreviousFiles()
}

private fun deleteBothPreviousFiles() {
selectedFile.deleteFile()
destinationFile.deleteFile()
}

private fun deleteAllFilesInDirectory(directory: File) {
if (directory.isDirectory) {
directory.listFiles()?.forEach { file ->
if (file.isDirectory) {
// Recursively delete files in subdirectories
deleteAllFilesInDirectory(file)
}
file.delete()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class KiwixSettingsFragmentTest {
"en",
SharedPreferenceUtil(it).apply {
setIsPlayStoreBuildType(true)
playStoreRestrictionPermissionDialog = false
}
)
it.navigate(R.id.introFragment)
Expand Down
Loading

0 comments on commit 32d36d7

Please sign in to comment.