Refactored the LibkiwixBookmarkTest test according to compose UI.

This commit is contained in:
MohitMaliFtechiz 2025-04-15 13:03:28 +05:30
parent af94018285
commit 12e17e4d87
4 changed files with 91 additions and 42 deletions

View File

@ -18,25 +18,29 @@
package org.kiwix.kiwixmobile.page.bookmarks package org.kiwix.kiwixmobile.page.bookmarks
import androidx.recyclerview.widget.RecyclerView import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.ComposeTestRule
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.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import applyWithViewHierarchyPrinting import applyWithViewHierarchyPrinting
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
import com.adevinta.android.barista.interaction.BaristaSleepInteractions import com.adevinta.android.barista.interaction.BaristaSleepInteractions
import org.kiwix.kiwixmobile.BaseRobot import org.kiwix.kiwixmobile.BaseRobot
import org.kiwix.kiwixmobile.Findable.StringId.ContentDesc
import org.kiwix.kiwixmobile.Findable.StringId.TextId import org.kiwix.kiwixmobile.Findable.StringId.TextId
import org.kiwix.kiwixmobile.Findable.Text
import org.kiwix.kiwixmobile.Findable.ViewId import org.kiwix.kiwixmobile.Findable.ViewId
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
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
import org.kiwix.kiwixmobile.core.page.SWITCH_TEXT_TESTING_TAG
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView
@ -49,12 +53,20 @@ fun bookmarks(func: BookmarksRobot.() -> Unit) =
class BookmarksRobot : BaseRobot() { class BookmarksRobot : BaseRobot() {
private var retryCountForBookmarkAddedButton = 5 private var retryCountForBookmarkAddedButton = 5
fun assertBookMarksDisplayed() { fun assertBookMarksDisplayed(composeTestRule: ComposeTestRule) {
assertDisplayed(R.string.bookmarks_from_current_book) composeTestRule.apply {
waitForIdle()
onNodeWithTag(SWITCH_TEXT_TESTING_TAG)
.assertTextEquals(context.getString(R.string.bookmarks_from_current_book))
}
} }
fun clickOnTrashIcon() { fun clickOnTrashIcon(composeTestRule: ComposeTestRule) {
clickOn(ContentDesc(R.string.pref_clear_all_bookmarks_title)) composeTestRule.apply {
waitForIdle()
onNodeWithTag(DELETE_MENU_ICON_TESTING_TAG)
.performClick()
}
} }
fun assertDeleteBookmarksDialogDisplayed() { fun assertDeleteBookmarksDialogDisplayed() {
@ -66,8 +78,12 @@ class BookmarksRobot : BaseRobot() {
testFlakyView({ onView(withText("DELETE")).perform(click()) }) testFlakyView({ onView(withText("DELETE")).perform(click()) })
} }
fun assertNoBookMarkTextDisplayed() { fun assertNoBookMarkTextDisplayed(composeTestRule: ComposeTestRule) {
testFlakyView({ isVisible(TextId(R.string.no_bookmarks)) }) composeTestRule.apply {
waitForIdle()
onNodeWithTag(NO_ITEMS_TEXT_TESTING_TAG)
.assertTextEquals(context.getString(R.string.no_bookmarks))
}
} }
fun clickOnSaveBookmarkImage() { fun clickOnSaveBookmarkImage() {
@ -97,14 +113,20 @@ class BookmarksRobot : BaseRobot() {
} }
} }
fun assertBookmarkSaved() { fun assertBookmarkSaved(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance() pauseForBetterTestPerformance()
isVisible(Text("Test Zim")) composeTestRule.apply {
waitForIdle()
composeTestRule.onNodeWithText("Test Zim").assertExists()
}
} }
fun assertBookmarkRemoved() { fun assertBookmarkRemoved(composeTestRule: ComposeTestRule) {
pauseForBetterTestPerformance() pauseForBetterTestPerformance()
onView(withText("Test Zim")).check(ViewAssertions.doesNotExist()) composeTestRule.apply {
waitForIdle()
composeTestRule.onNodeWithText("Test Zim").assertDoesNotExist()
}
} }
private fun pauseForBetterTestPerformance() { private fun pauseForBetterTestPerformance() {
@ -118,13 +140,19 @@ class BookmarksRobot : BaseRobot() {
}) })
} }
fun testAllBookmarkShowing(bookmarkList: ArrayList<LibkiwixBookmarkItem>) { fun testAllBookmarkShowing(
bookmarkList.forEachIndexed { index, libkiwixBookmarkItem -> bookmarkList: ArrayList<LibkiwixBookmarkItem>,
testFlakyView({ composeTestRule: ComposeTestRule
onView(withId(R.id.recycler_view)) ) {
.perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(index)) composeTestRule.apply {
.check(matches(hasDescendant(withText(libkiwixBookmarkItem.title)))) waitForIdle()
}) bookmarkList.forEachIndexed { index, libkiwixBookmarkItem ->
testFlakyView({
composeTestRule.onNodeWithTag(PAGE_LIST_TEST_TAG)
.performScrollToNode(hasText(libkiwixBookmarkItem.title))
composeTestRule.onNodeWithText(libkiwixBookmarkItem.title).assertExists()
})
}
} }
} }
} }

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.page.bookmarks package org.kiwix.kiwixmobile.page.bookmarks
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@ -42,6 +43,7 @@ import org.kiwix.kiwixmobile.core.main.CoreReaderFragment
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil 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.core.utils.TestingUtils.RETRY_RULE_ORDER
import org.kiwix.kiwixmobile.main.KiwixMainActivity import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.main.topLevel import org.kiwix.kiwixmobile.main.topLevel
@ -59,6 +61,9 @@ class LibkiwixBookmarkTest : BaseActivityTest() {
@JvmField @JvmField
val retryRule = RetryRule() val retryRule = RetryRule()
@get:Rule(order = COMPOSE_TEST_RULE_ORDER)
val composeTestRule = createComposeRule()
private lateinit var kiwixMainActivity: KiwixMainActivity private lateinit var kiwixMainActivity: KiwixMainActivity
@Before @Before
@ -119,20 +124,20 @@ class LibkiwixBookmarkTest : BaseActivityTest() {
bookmarks { bookmarks {
// delete any bookmark if already saved to properly perform this test case. // delete any bookmark if already saved to properly perform this test case.
longClickOnSaveBookmarkImage() longClickOnSaveBookmarkImage()
clickOnTrashIcon() clickOnTrashIcon(composeTestRule)
assertDeleteBookmarksDialogDisplayed() assertDeleteBookmarksDialogDisplayed()
clickOnDeleteButton() clickOnDeleteButton()
assertNoBookMarkTextDisplayed() assertNoBookMarkTextDisplayed(composeTestRule)
pressBack() pressBack()
// Test saving bookmark // Test saving bookmark
clickOnSaveBookmarkImage() clickOnSaveBookmarkImage()
clickOnOpenSavedBookmarkButton() clickOnOpenSavedBookmarkButton()
assertBookmarkSaved() assertBookmarkSaved(composeTestRule)
pressBack() pressBack()
// Test removing bookmark // Test removing bookmark
clickOnSaveBookmarkImage() clickOnSaveBookmarkImage()
longClickOnSaveBookmarkImage() longClickOnSaveBookmarkImage()
assertBookmarkRemoved() assertBookmarkRemoved(composeTestRule)
pressBack() pressBack()
// Save the bookmark to test whether it remains saved after the application restarts or not. // Save the bookmark to test whether it remains saved after the application restarts or not.
clickOnSaveBookmarkImage() clickOnSaveBookmarkImage()
@ -142,7 +147,7 @@ class LibkiwixBookmarkTest : BaseActivityTest() {
@Test @Test
fun testBookmarkRemainsSavedOrNot() { fun testBookmarkRemainsSavedOrNot() {
topLevel { topLevel {
clickBookmarksOnNavDrawer(BookmarksRobot::assertBookmarkSaved) clickBookmarksOnNavDrawer { assertBookmarkSaved(composeTestRule) }
} }
} }
@ -160,10 +165,10 @@ class LibkiwixBookmarkTest : BaseActivityTest() {
bookmarks { bookmarks {
// delete any bookmark if already saved to properly perform this test case. // delete any bookmark if already saved to properly perform this test case.
longClickOnSaveBookmarkImage() longClickOnSaveBookmarkImage()
clickOnTrashIcon() clickOnTrashIcon(composeTestRule)
assertDeleteBookmarksDialogDisplayed() assertDeleteBookmarksDialogDisplayed()
clickOnDeleteButton() clickOnDeleteButton()
assertNoBookMarkTextDisplayed() assertNoBookMarkTextDisplayed(composeTestRule)
pressBack() pressBack()
} }
val navHostFragment: NavHostFragment = val navHostFragment: NavHostFragment =
@ -198,7 +203,7 @@ class LibkiwixBookmarkTest : BaseActivityTest() {
bookmarks { bookmarks {
// test all the saved bookmarks are showing on the bookmarks screen // test all the saved bookmarks are showing on the bookmarks screen
openBookmarkScreen() openBookmarkScreen()
testAllBookmarkShowing(bookmarkList) testAllBookmarkShowing(bookmarkList, composeTestRule)
} }
} }

View File

@ -35,6 +35,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTag
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.downloader.model.Base64String import org.kiwix.kiwixmobile.core.downloader.model.Base64String
@ -45,6 +47,8 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.PAGE_LIST_ITEM_FAVICON_SIZE import org.kiwix.kiwixmobile.core.utils.ComposeDimens.PAGE_LIST_ITEM_FAVICON_SIZE
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
const val PAGE_ITEM_TITLE_TESTING_TAG = "pageItemTitleTestingTag"
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun PageListItem( fun PageListItem(
@ -81,7 +85,9 @@ fun PageListItem(
Text( Text(
text = page.title, text = page.title,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.weight(1f), modifier = Modifier
.weight(1f)
.semantics { testTag = PAGE_ITEM_TITLE_TESTING_TAG },
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )

View File

@ -49,7 +49,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTag
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
@ -72,6 +75,10 @@ import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
import org.threeten.bp.format.DateTimeParseException import org.threeten.bp.format.DateTimeParseException
const val SWITCH_TEXT_TESTING_TAG = "switchTextTestingTag"
const val NO_ITEMS_TEXT_TESTING_TAG = "noItemsTextTestingTag"
const val PAGE_LIST_TEST_TAG = "pageListTestingTag"
@Suppress("ComposableLambdaParameterNaming") @Suppress("ComposableLambdaParameterNaming")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -109,7 +116,9 @@ fun PageScreen(
Text( Text(
text = state.noItemsString, text = state.noItemsString,
style = MaterialTheme.typography.headlineSmall, style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.align(Alignment.Center) modifier = Modifier
.align(Alignment.Center)
.semantics { testTag = NO_ITEMS_TEXT_TESTING_TAG }
) )
} else { } else {
PageList( PageList(
@ -140,7 +149,7 @@ private fun PageList(
} }
} }
LazyColumn(state = listState) { LazyColumn(state = listState, modifier = Modifier.semantics { testTag = PAGE_LIST_TEST_TAG }) {
items(state.pageState.visiblePageItems) { item -> items(state.pageState.visiblePageItems) { item ->
when (item) { when (item) {
is Page -> PageListItem(page = item, itemClickListener = itemClickListener) is Page -> PageListItem(page = item, itemClickListener = itemClickListener)
@ -171,14 +180,14 @@ private fun searchBarIfActive(
fun PageSwitchRow( fun PageSwitchRow(
state: PageFragmentScreenState state: PageFragmentScreenState
) { ) {
val switchTextColor = if (isSystemInDarkTheme()) {
AlabasterWhite
} else {
White
}
val context = LocalActivity.current as CoreMainActivity val context = LocalActivity.current as CoreMainActivity
// hide switches for custom apps, see more info here https://github.com/kiwix/kiwix-android/issues/3523 // hide switches for custom apps, see more info here https://github.com/kiwix/kiwix-android/issues/3523
if (!context.isCustomApp()) { if (!context.isCustomApp()) {
val switchTextColor = if (isSystemInDarkTheme()) {
AlabasterWhite
} else {
White
}
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -190,7 +199,8 @@ fun PageSwitchRow(
Text( Text(
state.switchString, state.switchString,
color = switchTextColor, color = switchTextColor,
style = TextStyle(fontSize = FOURTEEN_SP) style = TextStyle(fontSize = FOURTEEN_SP),
modifier = Modifier.testTag(SWITCH_TEXT_TESTING_TAG)
) )
Switch( Switch(
checked = state.switchIsChecked, checked = state.switchIsChecked,