mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 06:42:21 -04:00
Merge pull request #4080 from kiwix/Fixes#4073
Fixed: SearchWidgetTest is flaky in CI.
This commit is contained in:
commit
3e30741ebe
@ -28,13 +28,16 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
|||||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import androidx.test.uiautomator.By
|
import androidx.test.uiautomator.By
|
||||||
import androidx.test.uiautomator.UiDevice
|
import androidx.test.uiautomator.UiDevice
|
||||||
|
import androidx.test.uiautomator.UiObjectNotFoundException
|
||||||
import applyWithViewHierarchyPrinting
|
import applyWithViewHierarchyPrinting
|
||||||
import com.adevinta.android.barista.interaction.BaristaSleepInteractions
|
import com.adevinta.android.barista.interaction.BaristaSleepInteractions
|
||||||
import org.hamcrest.core.AllOf.allOf
|
import org.hamcrest.core.AllOf.allOf
|
||||||
import org.kiwix.kiwixmobile.BaseRobot
|
import org.kiwix.kiwixmobile.BaseRobot
|
||||||
|
import org.kiwix.kiwixmobile.Findable.Text
|
||||||
|
import org.kiwix.kiwixmobile.SHORT_WAIT
|
||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||||
import org.kiwix.kiwixmobile.testutils.TestUtils
|
import org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST
|
||||||
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView
|
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView
|
||||||
|
|
||||||
fun searchWidget(func: SearchWidgetRobot.() -> Unit) =
|
fun searchWidget(func: SearchWidgetRobot.() -> Unit) =
|
||||||
@ -45,83 +48,81 @@ class SearchWidgetRobot : BaseRobot() {
|
|||||||
fun removeWidgetIfAlreadyAdded(uiDevice: UiDevice) {
|
fun removeWidgetIfAlreadyAdded(uiDevice: UiDevice) {
|
||||||
try {
|
try {
|
||||||
val widget = uiDevice.findObject(By.text("Search Kiwix"))
|
val widget = uiDevice.findObject(By.text("Search Kiwix"))
|
||||||
widget.click(1000L)
|
val removeTarget = Point(uiDevice.displayWidth / 2, uiDevice.displayHeight / 10)
|
||||||
uiDevice.waitForIdle()
|
|
||||||
val center = getScreenCenter(uiDevice)
|
|
||||||
val widgetBounds = widget.visibleBounds
|
|
||||||
|
|
||||||
uiDevice.swipe(
|
widget.drag(removeTarget)
|
||||||
widgetBounds.centerX(),
|
|
||||||
widgetBounds.centerY(),
|
|
||||||
center.x,
|
|
||||||
100,
|
|
||||||
150
|
|
||||||
)
|
|
||||||
|
|
||||||
uiDevice.waitForIdle()
|
uiDevice.waitForIdle()
|
||||||
} catch (ignore: Exception) {
|
} catch (ignore: Exception) {
|
||||||
// nothing to do since widget is not added
|
// nothing to do since widget is not added
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addWidgetToHomeScreen(uiDevice: UiDevice) {
|
|
||||||
try {
|
|
||||||
if (uiDevice.findObject(By.text("Search Kiwix")).text == "Search Kiwix") {
|
|
||||||
// since search widget is already exist we does not require to add it again.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch (ignore: Exception) {
|
|
||||||
// widget does not exist.
|
|
||||||
Log.e(
|
Log.e(
|
||||||
"SEARCH_WIDGET",
|
"SEARCH_WIDGET_TEST",
|
||||||
"Could not find the Search widget. Probably it does not exist"
|
"Could not find the Search widget. It likely does not exist."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val center = getScreenCenter(uiDevice)
|
|
||||||
longPressInCenterOfScreen(uiDevice, center)
|
|
||||||
clickOnWidgetsText(uiDevice)
|
|
||||||
var widget = uiDevice.findObject(By.text("Kiwix"))
|
|
||||||
var maxSwipes = 30
|
|
||||||
while (widget == null && maxSwipes > 0) {
|
|
||||||
uiDevice.swipe(center.x, center.y, center.x, 0, 200)
|
|
||||||
uiDevice.waitForIdle()
|
|
||||||
widget = uiDevice.findObject(By.text("Kiwix"))
|
|
||||||
maxSwipes--
|
|
||||||
}
|
|
||||||
uiDevice.swipe(center.x, center.y, center.x, 0, 200)
|
|
||||||
val b = widget.visibleBounds
|
|
||||||
val c = Point(b.left + 150, b.bottom + 150)
|
|
||||||
val dest = Point(c.x + 250, c.y + 250)
|
|
||||||
uiDevice.swipe(arrayOf(c, c, dest), 150)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clickOnWidgetsText(uiDevice: UiDevice) {
|
fun assertAddWidgetToHomeScreenVisible(): Boolean =
|
||||||
try {
|
try {
|
||||||
// Different according to the devices
|
isVisible(Text("Add automatically"))
|
||||||
uiDevice.findObject(By.text("Widgets")).click()
|
true
|
||||||
} catch (ignore: Exception) {
|
} catch (ignore: Exception) {
|
||||||
uiDevice.findObject(By.text("WIDGETS")).click()
|
false
|
||||||
}
|
}
|
||||||
uiDevice.waitForIdle()
|
|
||||||
|
fun addWidgetToHomeScreenFromWidgetWindow() {
|
||||||
|
testFlakyView({ clickOn(Text("Add automatically")) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertSearchWidgetAddedToHomeScreen(uiDevice: UiDevice) {
|
fun findSearchWidget(uiDevice: UiDevice) {
|
||||||
uiDevice.findObject(By.text("Search Kiwix"))
|
try {
|
||||||
|
assertSearchWidgetAddedToHomeScreen(2)
|
||||||
|
} catch (ignore: RuntimeException) {
|
||||||
|
// the search widget is not on the home screen, swipe right because
|
||||||
|
// the widget has been added to next window
|
||||||
|
swipeRightToOpenNextWindow(uiDevice)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun longPressInCenterOfScreen(uiDevice: UiDevice, center: Point) {
|
private fun swipeRightToOpenNextWindow(uiDevice: UiDevice) {
|
||||||
uiDevice.swipe(arrayOf(center, center), 150)
|
val displayWidth = uiDevice.displayWidth
|
||||||
|
val displayHeight = uiDevice.displayHeight
|
||||||
|
|
||||||
|
val startX = (displayWidth * 0.9).toInt()
|
||||||
|
val endX = (displayWidth * 0.1).toInt()
|
||||||
|
val centerY = displayHeight / 2
|
||||||
|
|
||||||
|
uiDevice.swipe(startX, centerY, endX, centerY, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getScreenCenter(device: UiDevice): Point {
|
fun assertSearchWidgetAddedToHomeScreen(retryCount: Int = 5) {
|
||||||
val size = device.displaySizeDp
|
testFlakyView({ isVisible(Text("Search Kiwix"), SHORT_WAIT) }, retryCount)
|
||||||
return Point(size.x / 2, size.y / 2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickOnBookmarkIcon(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) {
|
fun clickOnMicIcon(
|
||||||
uiDevice.findObject(
|
uiDevice: UiDevice,
|
||||||
By.res("${kiwixMainActivity.packageName}:id/search_widget_star")
|
kiwixMainActivity: KiwixMainActivity
|
||||||
).click()
|
) {
|
||||||
|
clickOnElementById(uiDevice, kiwixMainActivity, "search_widget_mic")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeIfGoogleSearchVisible() {
|
||||||
|
try {
|
||||||
|
pauseForBetterTestPerformance()
|
||||||
|
testFlakyView({ isVisible(Text("Google")) })
|
||||||
|
pressBack()
|
||||||
|
Log.e("SEARCH_WIDGET_TEST", "Closed the Google speak dialog")
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
// do nothing since the Google speak is not recognized in this emulator.
|
||||||
|
Log.e("SEARCH_WIDGET_TEST", "Could not close the Google speak dialog.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clickOnBookmarkIcon(
|
||||||
|
uiDevice: UiDevice,
|
||||||
|
kiwixMainActivity: KiwixMainActivity
|
||||||
|
) {
|
||||||
|
clickOnElementById(uiDevice, kiwixMainActivity, "search_widget_star")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertBookmarkScreenVisible() {
|
fun assertBookmarkScreenVisible() {
|
||||||
@ -131,37 +132,41 @@ class SearchWidgetRobot : BaseRobot() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickOnMicIcon(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) {
|
|
||||||
uiDevice.findObject(
|
|
||||||
By.res("${kiwixMainActivity.packageName}:id/search_widget_mic")
|
|
||||||
).click()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun closeIfGoogleSearchVisible(uiDevice: UiDevice) {
|
|
||||||
try {
|
|
||||||
pauseForBetterTestPerformance()
|
|
||||||
testFlakyView({ uiDevice.findObject(By.text("Google")) })
|
|
||||||
pressBack()
|
|
||||||
Log.e("SEARCH_WIDGET_TEST", "Closed the Google speak dialog")
|
|
||||||
} catch (ignore: Exception) {
|
|
||||||
// do nothing since the Google speak is not recognized in this emulator.
|
|
||||||
Log.e("SEARCH_WIDGET_TEST", "Could not close the Google speak dialog.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun assertSearchScreenVisible() {
|
fun assertSearchScreenVisible() {
|
||||||
testFlakyView({
|
testFlakyView({
|
||||||
onView(withText(R.string.menu_search_in_text)).check(matches(isDisplayed()))
|
onView(withText(R.string.menu_search_in_text)).check(matches(isDisplayed()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickOnSearchText(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) {
|
fun clickOnSearchText(
|
||||||
uiDevice.findObject(
|
uiDevice: UiDevice,
|
||||||
By.res("${kiwixMainActivity.packageName}:id/search_widget_text")
|
kiwixMainActivity: KiwixMainActivity
|
||||||
).click()
|
) {
|
||||||
|
clickOnElementById(uiDevice, kiwixMainActivity, "search_widget_text")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clickOnElementById(
|
||||||
|
uiDevice: UiDevice,
|
||||||
|
kiwixMainActivity: KiwixMainActivity,
|
||||||
|
elementId: String,
|
||||||
|
retryCount: Int = 20
|
||||||
|
) {
|
||||||
|
var attempts = 0
|
||||||
|
while (attempts < retryCount) {
|
||||||
|
try {
|
||||||
|
uiDevice.findObject(
|
||||||
|
By.res("${kiwixMainActivity.packageName}:id/$elementId")
|
||||||
|
).click()
|
||||||
|
return
|
||||||
|
} catch (e: UiObjectNotFoundException) {
|
||||||
|
attempts++
|
||||||
|
Log.e("SEARCH_WIDGET_TEST", "Attempt $attempts: Failed to click on $elementId")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw RuntimeException("Could not find $elementId after $retryCount attempts")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pauseForBetterTestPerformance() {
|
private fun pauseForBetterTestPerformance() {
|
||||||
BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong())
|
BaristaSleepInteractions.sleep(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,11 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.widgets
|
package org.kiwix.kiwixmobile.widgets
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.content.ComponentName
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.RemoteViews
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.test.core.app.ActivityScenario
|
import androidx.test.core.app.ActivityScenario
|
||||||
import androidx.test.espresso.accessibility.AccessibilityChecks
|
import androidx.test.espresso.accessibility.AccessibilityChecks
|
||||||
@ -33,8 +37,10 @@ import org.junit.Before
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.kiwix.kiwixmobile.BaseActivityTest
|
import org.kiwix.kiwixmobile.BaseActivityTest
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||||
|
import org.kiwix.kiwixmobile.main.KiwixSearchWidget
|
||||||
import org.kiwix.kiwixmobile.testutils.RetryRule
|
import org.kiwix.kiwixmobile.testutils.RetryRule
|
||||||
import org.kiwix.kiwixmobile.testutils.TestUtils
|
import org.kiwix.kiwixmobile.testutils.TestUtils
|
||||||
|
|
||||||
@ -89,22 +95,44 @@ class SearchWidgetTest : BaseActivityTest() {
|
|||||||
}
|
}
|
||||||
searchWidget {
|
searchWidget {
|
||||||
pressHome()
|
pressHome()
|
||||||
addWidgetToHomeScreen(uiDevice)
|
uiDevice.waitForIdle()
|
||||||
assertSearchWidgetAddedToHomeScreen(uiDevice)
|
if (addWidgetToHomeScreen()) {
|
||||||
clickOnBookmarkIcon(uiDevice, kiwixMainActivity)
|
if (assertAddWidgetToHomeScreenVisible()) {
|
||||||
assertBookmarkScreenVisible()
|
addWidgetToHomeScreenFromWidgetWindow()
|
||||||
pressBack()
|
assertSearchWidgetAddedToHomeScreen()
|
||||||
pressHome()
|
clickOnBookmarkIcon(uiDevice, kiwixMainActivity)
|
||||||
clickOnMicIcon(uiDevice, kiwixMainActivity)
|
assertBookmarkScreenVisible()
|
||||||
closeIfGoogleSearchVisible(uiDevice)
|
pressBack()
|
||||||
assertSearchScreenVisible()
|
pressHome()
|
||||||
pressBack()
|
findSearchWidget(uiDevice)
|
||||||
pressHome()
|
clickOnMicIcon(uiDevice, kiwixMainActivity)
|
||||||
clickOnSearchText(uiDevice, kiwixMainActivity)
|
closeIfGoogleSearchVisible()
|
||||||
assertSearchScreenVisible()
|
assertSearchScreenVisible()
|
||||||
pressHome()
|
pressBack()
|
||||||
removeWidgetIfAlreadyAdded(uiDevice)
|
pressHome()
|
||||||
|
findSearchWidget(uiDevice)
|
||||||
|
clickOnSearchText(uiDevice, kiwixMainActivity)
|
||||||
|
assertSearchScreenVisible()
|
||||||
|
pressHome()
|
||||||
|
removeWidgetIfAlreadyAdded(uiDevice)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addWidgetToHomeScreen(): Boolean {
|
||||||
|
val mAppWidgetManager: AppWidgetManager? =
|
||||||
|
context.getSystemService(AppWidgetManager::class.java)
|
||||||
|
val myProvider = ComponentName(context, KiwixSearchWidget::class.java)
|
||||||
|
return if (mAppWidgetManager?.isRequestPinAppWidgetSupported == true) {
|
||||||
|
val remoteViews =
|
||||||
|
RemoteViews(context.packageName, R.layout.kiwix_search_widget)
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putParcelable(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW, remoteViews)
|
||||||
|
mAppWidgetManager.requestPinAppWidget(myProvider, bundle, null)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user