Fixed: The NoteFragmentTest was failing.

* Improved the setting of text in noteTextField for better maintainability.
This commit is contained in:
MohitMaliFtechiz 2025-03-11 12:44:40 +05:30
parent 4444a6f236
commit 58b32b5350
5 changed files with 53 additions and 25 deletions

View File

@ -221,7 +221,7 @@ class NoteFragmentTest : BaseActivityTest() {
clickOnSavedNote() clickOnSavedNote()
clickOnOpenNote() clickOnOpenNote()
assertNoteSaved(composeTestRule) assertNoteSaved(composeTestRule)
clickOnDeleteIcon() clickOnDeleteIcon(composeTestRule)
pressBack() pressBack()
assertNoNotesTextDisplayed() assertNoNotesTextDisplayed()
} }
@ -245,7 +245,7 @@ class NoteFragmentTest : BaseActivityTest() {
note { note {
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed(composeTestRule) assertNoteDialogDisplayed(composeTestRule)
assertNotDoesNotExist() assertNotDoesNotExist(composeTestRule)
pressBack() pressBack()
} }
} }

View File

@ -19,17 +19,17 @@
package org.kiwix.kiwixmobile.note package org.kiwix.kiwixmobile.note
import android.content.Context import android.content.Context
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.assertTextEquals import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.ComposeContentTestRule
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.performTextInput import androidx.compose.ui.test.performTextReplacement
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
@ -45,6 +45,7 @@ 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.main.ADD_NOTE_TEXT_FILED_TESTING_TAG import org.kiwix.kiwixmobile.core.main.ADD_NOTE_TEXT_FILED_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.DELETE_MENU_BUTTON_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.SAVE_MENU_BUTTON_TESTING_TAG import org.kiwix.kiwixmobile.core.main.SAVE_MENU_BUTTON_TESTING_TAG
import org.kiwix.kiwixmobile.core.ui.components.TOOLBAR_TITLE_TESTING_TAG import org.kiwix.kiwixmobile.core.ui.components.TOOLBAR_TITLE_TESTING_TAG
import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils
@ -77,21 +78,26 @@ class NoteRobot : BaseRobot() {
} }
fun assertNoteDialogDisplayed(composeTestRule: ComposeContentTestRule) { fun assertNoteDialogDisplayed(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance()
testFlakyView({ testFlakyView({
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(TOOLBAR_TITLE_TESTING_TAG) composeTestRule.onNodeWithTag(TOOLBAR_TITLE_TESTING_TAG)
.assertTextEquals(context.getString(R.string.note)) .assertTextEquals(context.getString(R.string.note))
}) })
} }
fun writeDemoNote(composeTestRule: ComposeContentTestRule) { fun writeDemoNote(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance()
testFlakyView({ testFlakyView({
composeTestRule.waitForIdle()
// Click on the TextField to focus it // Click on the TextField to focus it
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG) composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertExists("TextField not found in dialog") .assertExists("TextField not found in dialog")
.performClick() .performClick()
.performTextInput(noteText) .performTextReplacement(noteText)
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertTextContains(noteText, substring = true)
// Close the keyboard after typing // Close the keyboard after typing
closeSoftKeyboard() closeSoftKeyboard()
@ -99,8 +105,8 @@ class NoteRobot : BaseRobot() {
} }
fun saveNote(composeTestRule: ComposeContentTestRule) { fun saveNote(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance()
testFlakyView({ testFlakyView({
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(SAVE_MENU_BUTTON_TESTING_TAG) composeTestRule.onNodeWithTag(SAVE_MENU_BUTTON_TESTING_TAG)
.performClick() .performClick()
}) })
@ -130,18 +136,26 @@ class NoteRobot : BaseRobot() {
// This is flaky since it is shown in a dialog and sometimes // This is flaky since it is shown in a dialog and sometimes
// UIDevice does not found the view immediately due to rendering process. // UIDevice does not found the view immediately due to rendering process.
testFlakyView({ testFlakyView({
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG) composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertTextEquals(noteText) .assertTextEquals(noteText)
}) })
} }
fun assertNotDoesNotExist() { fun assertNotDoesNotExist(composeTestRule: ComposeContentTestRule) {
testFlakyView({ onView(withText(noteText)).check(doesNotExist()) }) testFlakyView({
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertTextContains("", ignoreCase = true)
})
} }
fun clickOnDeleteIcon() { fun clickOnDeleteIcon(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance() testFlakyView({
testFlakyView({ clickOn(ViewId(R.id.delete_note)) }) composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(DELETE_MENU_BUTTON_TESTING_TAG)
.performClick()
})
} }
fun clickOnTrashIcon() { fun clickOnTrashIcon() {

View File

@ -187,7 +187,9 @@ class AddNoteDialog : DialogFragment() {
}, },
noteText = noteText.value, noteText = noteText.value,
actionMenuItems = menuItems.value, actionMenuItems = menuItems.value,
onTextChange = { text -> enableSaveAndShareMenuButtonAndSetTextEdited(text) }, onTextChange = { textInputFiled ->
enableSaveAndShareMenuButtonAndSetTextEdited(textInputFiled)
},
isNoteFileExist = noteFileExists.value, isNoteFileExist = noteFileExists.value,
snackBarHostState = snackBarHostState snackBarHostState = snackBarHostState
) )
@ -228,13 +230,9 @@ class AddNoteDialog : DialogFragment() {
) )
) )
private fun enableSaveAndShareMenuButtonAndSetTextEdited(text: String) { private fun enableSaveAndShareMenuButtonAndSetTextEdited(textFieldValue: TextFieldValue) {
noteEdited = true noteEdited = true
noteText.value = TextFieldValue( noteText.value = textFieldValue
text = text,
// Moves cursor to end
selection = TextRange(text.length)
)
enableSaveNoteMenuItem() enableSaveNoteMenuItem()
enableShareNoteMenuItem() enableShareNoteMenuItem()
} }
@ -430,7 +428,12 @@ class AddNoteDialog : DialogFragment() {
} }
private fun restoreDeletedNote(text: String) { private fun restoreDeletedNote(text: String) {
enableSaveAndShareMenuButtonAndSetTextEdited(text) val restoreNoteTextFieldValue = TextFieldValue(
text = text,
// Moves cursor to end
selection = TextRange(text.length)
)
enableSaveAndShareMenuButtonAndSetTextEdited(restoreNoteTextFieldValue)
} }
/* String content of the note text file given at: /* String content of the note text file given at:

View File

@ -57,6 +57,7 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.MINIMUM_HEIGHT_OF_NOTE_TEXT_FILED import org.kiwix.kiwixmobile.core.utils.ComposeDimens.MINIMUM_HEIGHT_OF_NOTE_TEXT_FILED
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWENTY_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWENTY_DP
import org.kiwix.kiwixmobile.core.utils.TestingUtils.isRunningTest
const val ADD_NOTE_TEXT_FILED_TESTING_TAG = "addNoteTextFiledTestingTag" const val ADD_NOTE_TEXT_FILED_TESTING_TAG = "addNoteTextFiledTestingTag"
const val SAVE_MENU_BUTTON_TESTING_TAG = "saveMenuButtonTestingTag" const val SAVE_MENU_BUTTON_TESTING_TAG = "saveMenuButtonTestingTag"
@ -69,7 +70,7 @@ fun AddNoteDialogScreen(
articleTitle: String, articleTitle: String,
noteText: TextFieldValue, noteText: TextFieldValue,
actionMenuItems: List<ActionMenuItem>, actionMenuItems: List<ActionMenuItem>,
onTextChange: (String) -> Unit, onTextChange: (TextFieldValue) -> Unit,
isNoteFileExist: Boolean, isNoteFileExist: Boolean,
snackBarHostState: SnackbarHostState, snackBarHostState: SnackbarHostState,
navigationIcon: @Composable () -> Unit navigationIcon: @Composable () -> Unit
@ -103,7 +104,7 @@ fun AddNoteDialogScreen(
} }
LaunchedEffect(isNoteFileExist) { LaunchedEffect(isNoteFileExist) {
if (!isNoteFileExist) { if (!isNoteFileExist && !isRunningTest()) {
focusRequester.requestFocus() focusRequester.requestFocus()
focusManager.moveFocus(FocusDirection.Down) focusManager.moveFocus(FocusDirection.Down)
} }
@ -123,12 +124,12 @@ private fun ArticleTitleText(articleTitle: String) {
@Composable @Composable
private fun NoteTextField( private fun NoteTextField(
noteText: TextFieldValue, noteText: TextFieldValue,
onTextChange: (String) -> Unit, onTextChange: (TextFieldValue) -> Unit,
focusRequester: FocusRequester focusRequester: FocusRequester
) { ) {
TextField( TextField(
value = noteText, value = noteText,
onValueChange = { onTextChange(it.text) }, onValueChange = { onTextChange(it) },
maxLines = 6, maxLines = 6,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()

View File

@ -42,6 +42,16 @@ object TestingUtils {
} }
} }
@JvmStatic
fun isRunningTest(): Boolean {
return try {
Class.forName("androidx.test.espresso.Espresso")
true
} catch (_: ClassNotFoundException) {
false
}
}
@JvmStatic fun registerIdleCallback(listListener: IdleListener) { @JvmStatic fun registerIdleCallback(listListener: IdleListener) {
resources.clear() resources.clear()
callback = listListener callback = listListener