Added UI test cases for these scenarios to avoid future bugs like these.

This commit is contained in:
MohitMaliFtechiz 2025-08-19 18:42:07 +05:30
parent 2e36a7f788
commit 5b68238e96
4 changed files with 127 additions and 21 deletions

View File

@ -46,11 +46,13 @@ import org.junit.Before
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.utils.LanguageUtils.Companion.handleLocaleChange
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.main.KiwixMainActivity
import org.kiwix.kiwixmobile.page.bookmarks.bookmarks
import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
@ -115,6 +117,56 @@ class KiwixReaderFragmentTest : BaseActivityTest() {
}
}
@Test
fun testTabsRestoredAfterNavigatingLeftDrawerScreens() {
activityScenario.onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(KiwixDestination.Library.route)
}
composeTestRule.waitForIdle()
val zimFile = getLocalZIMFile()
openKiwixReaderFragmentWithFile(zimFile)
reader {
checkZimFileLoadedSuccessful(composeTestRule)
// open a new tab
openSearchWithQuery("Android", zimFile)
openAndroidArticleInNewTab(composeTestRule)
checkZimFileLoadedSuccessful(composeTestRule)
// open bookmark screen.
bookmarks {
openBookmarkScreen(kiwixMainActivity as CoreMainActivity, composeTestRule)
assertBookMarksDisplayed(composeTestRule)
}
composeTestRule.waitForIdle()
pressBack()
assertTabsRestored(composeTestRule)
}
}
@Test
fun testTabsRestoredWhenNavigatingToOtherScreenViaBottomAppBar() {
activityScenario.onActivity {
kiwixMainActivity = it
kiwixMainActivity.navigate(KiwixDestination.Library.route)
}
composeTestRule.waitForIdle()
val zimFile = getLocalZIMFile()
openKiwixReaderFragmentWithFile(zimFile)
reader {
checkZimFileLoadedSuccessful(composeTestRule)
// open a new tab
openSearchWithQuery("Android", zimFile)
openAndroidArticleInNewTab(composeTestRule)
checkZimFileLoadedSuccessful(composeTestRule)
// open local library screen.
openLocalLibraryScreenViaBottomAppBar(composeTestRule)
composeTestRule.waitForIdle()
// press back to come back to reader screen.
pressBack()
assertTabsRestored(composeTestRule)
}
}
@Test
fun testTabClosedDialog() {
activityScenario.onActivity {
@ -122,26 +174,7 @@ class KiwixReaderFragmentTest : BaseActivityTest() {
kiwixMainActivity.navigate(KiwixDestination.Library.route)
}
composeTestRule.waitForIdle()
val loadFileStream =
KiwixReaderFragmentTest::class.java.classLoader.getResourceAsStream("testzim.zim")
val zimFile =
File(
context.getExternalFilesDirs(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)
}
}
}
openKiwixReaderFragmentWithFile(zimFile)
openKiwixReaderFragmentWithFile(getLocalZIMFile())
composeTestRule.waitForIdle()
reader {
checkZimFileLoadedSuccessful(composeTestRule)
@ -263,6 +296,43 @@ class KiwixReaderFragmentTest : BaseActivityTest() {
}
}
private fun getLocalZIMFile(): File {
val loadFileStream =
KiwixReaderFragmentTest::class.java.classLoader.getResourceAsStream("testzim.zim")
val zimFile =
File(
context.getExternalFilesDirs(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
}
private fun openSearchWithQuery(query: String = "", zimFile: File) {
UiThreadStatement.runOnUiThread {
if (zimFile.canRead()) {
kiwixMainActivity.openSearch(searchString = query)
} else {
throw RuntimeException(
"File $zimFile is not readable." +
" Original File $zimFile is readable = ${zimFile.canRead()}" +
" Size ${zimFile.length()}"
)
}
}
}
private fun openKiwixReaderFragmentWithFile(zimFile: File) {
UiThreadStatement.runOnUiThread {
val navOptions = NavOptions.Builder()

View File

@ -35,6 +35,9 @@ import org.kiwix.kiwixmobile.core.main.reader.CLOSE_ALL_TABS_BUTTON_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.reader.READER_SCREEN_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.reader.TAB_MENU_ITEM_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.reader.TAB_TITLE_TESTING_TAG
import org.kiwix.kiwixmobile.core.search.OPEN_ITEM_IN_NEW_TAB_ICON_TESTING_TAG
import org.kiwix.kiwixmobile.main.BOTTOM_NAV_LIBRARY_ITEM_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.reader.TABS_SIZE_TEXT_TESTING_TAG
import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView
import org.kiwix.kiwixmobile.testutils.TestUtils.waitUntilTimeout
@ -115,4 +118,31 @@ class ReaderRobot : BaseRobot() {
)
})
}
fun openAndroidArticleInNewTab(composeTestRule: ComposeContentTestRule) {
testFlakyView({
composeTestRule.apply {
waitForIdle()
onAllNodesWithTag(OPEN_ITEM_IN_NEW_TAB_ICON_TESTING_TAG)[0].performClick()
}
})
}
fun assertTabsRestored(composeTestRule: ComposeContentTestRule) {
testFlakyView({
composeTestRule.apply {
waitForIdle()
onNodeWithTag(TABS_SIZE_TEXT_TESTING_TAG, useUnmergedTree = true).assertTextEquals("2")
}
})
}
fun openLocalLibraryScreenViaBottomAppBar(composeTestRule: ComposeContentTestRule) {
testFlakyView({
composeTestRule.apply {
waitForIdle()
onNodeWithTag(BOTTOM_NAV_LIBRARY_ITEM_TESTING_TAG).performClick()
}
})
}
}

View File

@ -35,6 +35,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import org.kiwix.kiwixmobile.core.R
@ -57,6 +58,7 @@ const val TAKE_NOTE_MENU_ITEM_TESTING_TAG = "takeNoteMenuItemTestingTag"
const val FULL_SCREEN_MENU_ITEM_TESTING_TAG = "fullScreenMenuItemTestingTag"
const val RANDOM_ARTICLE_MENU_ITEM_TESTING_TAG = "randomArticleMenuItemTestingTag"
const val TAB_MENU_ITEM_TESTING_TAG = "tabMenuItemTestingTag"
const val TABS_SIZE_TEXT_TESTING_TAG = "tabsSizeTextTestingTag"
@Stable
class ReaderMenuState(
@ -227,7 +229,8 @@ class ReaderMenuState(
fontWeight = FontWeight.Bold,
fontSize = TAB_SWITCHER_TEXT_SIZE,
maxLines = 1,
overflow = TextOverflow.Ellipsis
overflow = TextOverflow.Ellipsis,
modifier = Modifier.testTag(TABS_SIZE_TEXT_TESTING_TAG)
)
}
}

View File

@ -50,6 +50,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
@ -73,6 +74,7 @@ const val SEARCH_FIELD_TESTING_TAG = "searchFieldTestingTag"
const val NO_SEARCH_RESULT_TESTING_TAG = "noSearchResultTestingTag"
const val FIND_IN_PAGE_TESTING_TAG = "findInPageTestingTag"
const val SEARCH_ITEM_TESTING_TAG = "searchItemTestingTag"
const val OPEN_ITEM_IN_NEW_TAB_ICON_TESTING_TAG = "openItemInNewTagIconTestingTag"
const val LOADING_ITEMS_BEFORE = 3
@OptIn(ExperimentalMaterial3Api::class)
@ -232,6 +234,7 @@ private fun SearchListItem(
IconButton(
onClick = { onNewTabIconClick(searchListItem) },
modifier = Modifier.testTag(OPEN_ITEM_IN_NEW_TAB_ICON_TESTING_TAG)
) {
Icon(
painter = painterResource(id = R.drawable.ic_open_in_new_24dp),