From f8f6b4c7fc0e3d8fadabc012ea1f900018dc8f76 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 15 Nov 2024 17:09:35 +0530 Subject: [PATCH] Introduced a new way to add widget on the home screen. Also, improved the clicking on widgets buttons since sometimes widget has been added to the next window due to not enough area available on home screen --- .../kiwixmobile/widgets/SearchWidgetRobot.kt | 154 +++++++++--------- .../kiwixmobile/widgets/SearchWidgetTest.kt | 56 +++++-- 2 files changed, 115 insertions(+), 95 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt index 1c2295e99..9fb9cca2d 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt @@ -28,13 +28,16 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiObjectNotFoundException import applyWithViewHierarchyPrinting import com.adevinta.android.barista.interaction.BaristaSleepInteractions import org.hamcrest.core.AllOf.allOf 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.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 fun searchWidget(func: SearchWidgetRobot.() -> Unit) = @@ -45,96 +48,51 @@ class SearchWidgetRobot : BaseRobot() { fun removeWidgetIfAlreadyAdded(uiDevice: UiDevice) { try { val widget = uiDevice.findObject(By.text("Search Kiwix")) - widget.click(1000L) - uiDevice.waitForIdle() - val center = getScreenCenter(uiDevice) - val widgetBounds = widget.visibleBounds + val removeTarget = Point(uiDevice.displayWidth / 2, uiDevice.displayHeight / 10) - uiDevice.swipe( - widgetBounds.centerX(), - widgetBounds.centerY(), - center.x, - 100, - 150 - ) + widget.drag(removeTarget) uiDevice.waitForIdle() } catch (ignore: Exception) { // nothing to do since widget is not added + Log.e("SEARCH_WIDGET", "Could not find the Search widget. It likely does not exist.") } } - fun addWidgetToHomeScreen(uiDevice: UiDevice) { + fun addWidgetToHomeScreenFromWidgetWindow() { + testFlakyView({ clickOn(Text("Add automatically")) }) + } + + fun findSearchWidget(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( - "SEARCH_WIDGET", - "Could not find the Search widget. Probably it does not exist" - ) + 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) } - 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) { - try { - // Different according to the devices - uiDevice.findObject(By.text("Widgets")).click() - } catch (ignore: Exception) { - uiDevice.findObject(By.text("WIDGETS")).click() - } - uiDevice.waitForIdle() + private fun swipeRightToOpenNextWindow(uiDevice: UiDevice) { + 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) } - fun assertSearchWidgetAddedToHomeScreen(uiDevice: UiDevice) { - uiDevice.findObject(By.text("Search Kiwix")) + fun assertSearchWidgetAddedToHomeScreen(retryCount: Int = 5) { + testFlakyView({ isVisible(Text("Search Kiwix"), SHORT_WAIT) }, retryCount) } - private fun longPressInCenterOfScreen(uiDevice: UiDevice, center: Point) { - uiDevice.swipe(arrayOf(center, center), 150) - } - - private fun getScreenCenter(device: UiDevice): Point { - val size = device.displaySizeDp - return Point(size.x / 2, size.y / 2) - } - - fun clickOnBookmarkIcon(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) { - uiDevice.findObject( - By.res("${kiwixMainActivity.packageName}:id/search_widget_star") - ).click() - } - - fun assertBookmarkScreenVisible() { - testFlakyView({ - onView(allOf(withText(R.string.bookmarks), isDescendantOfA(withId(R.id.toolbar)))) - .check(matches(isDisplayed())) - }) - } - - fun clickOnMicIcon(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) { - uiDevice.findObject( - By.res("${kiwixMainActivity.packageName}:id/search_widget_mic") - ).click() + fun clickOnMicIcon( + uiDevice: UiDevice, + kiwixMainActivity: KiwixMainActivity + ) { + clickOnElementById(uiDevice, kiwixMainActivity, "search_widget_mic") } fun closeIfGoogleSearchVisible(uiDevice: UiDevice) { @@ -149,19 +107,55 @@ class SearchWidgetRobot : BaseRobot() { } } + fun clickOnBookmarkIcon( + uiDevice: UiDevice, + kiwixMainActivity: KiwixMainActivity + ) { + clickOnElementById(uiDevice, kiwixMainActivity, "search_widget_star") + } + + fun assertBookmarkScreenVisible() { + testFlakyView({ + onView(allOf(withText(R.string.bookmarks), isDescendantOfA(withId(R.id.toolbar)))) + .check(matches(isDisplayed())) + }) + } + fun assertSearchScreenVisible() { testFlakyView({ onView(withText(R.string.menu_search_in_text)).check(matches(isDisplayed())) }) } - fun clickOnSearchText(uiDevice: UiDevice, kiwixMainActivity: KiwixMainActivity) { - uiDevice.findObject( - By.res("${kiwixMainActivity.packageName}:id/search_widget_text") - ).click() + fun clickOnSearchText( + uiDevice: UiDevice, + kiwixMainActivity: KiwixMainActivity + ) { + 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", "Attempt $attempts: Failed to click on $elementId") + } + } + throw RuntimeException("Could not find $elementId after $retryCount attempts") } private fun pauseForBetterTestPerformance() { - BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) + BaristaSleepInteractions.sleep(TEST_PAUSE_MS_FOR_DOWNLOAD_TEST.toLong()) } } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt index dffb04d36..312da19f3 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt @@ -18,7 +18,11 @@ package org.kiwix.kiwixmobile.widgets +import android.appwidget.AppWidgetManager +import android.content.ComponentName import android.os.Build +import android.os.Bundle +import android.widget.RemoteViews import androidx.lifecycle.Lifecycle import androidx.test.core.app.ActivityScenario import androidx.test.espresso.accessibility.AccessibilityChecks @@ -33,8 +37,10 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest +import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.main.KiwixMainActivity +import org.kiwix.kiwixmobile.main.KiwixSearchWidget import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.TestUtils @@ -89,22 +95,42 @@ class SearchWidgetTest : BaseActivityTest() { } searchWidget { pressHome() - addWidgetToHomeScreen(uiDevice) - assertSearchWidgetAddedToHomeScreen(uiDevice) - clickOnBookmarkIcon(uiDevice, kiwixMainActivity) - assertBookmarkScreenVisible() - pressBack() - pressHome() - clickOnMicIcon(uiDevice, kiwixMainActivity) - closeIfGoogleSearchVisible(uiDevice) - assertSearchScreenVisible() - pressBack() - pressHome() - clickOnSearchText(uiDevice, kiwixMainActivity) - assertSearchScreenVisible() - pressHome() - removeWidgetIfAlreadyAdded(uiDevice) + uiDevice.waitForIdle() + if (addWidgetToHomeScreen()) { + addWidgetToHomeScreenFromWidgetWindow() + assertSearchWidgetAddedToHomeScreen() + clickOnBookmarkIcon(uiDevice, kiwixMainActivity) + assertBookmarkScreenVisible() + pressBack() + pressHome() + findSearchWidget(uiDevice) + clickOnMicIcon(uiDevice, kiwixMainActivity) + closeIfGoogleSearchVisible(uiDevice) + assertSearchScreenVisible() + pressBack() + 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 + } + } }