diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/BaseRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/BaseRobot.kt index 2735fb0e1..889c3e9a6 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/BaseRobot.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/BaseRobot.kt @@ -54,6 +54,10 @@ abstract class BaseRobot( uiDevice.pressBack() } + internal fun pressHome() { + uiDevice.pressHome() + } + protected fun isVisible(findable: Findable, timeout: Long = VERY_LONG_WAIT) = waitFor(findable, timeout) ?: throw RuntimeException(findable.errorMessage(this)) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt new file mode 100644 index 000000000..3f054a0f0 --- /dev/null +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetRobot.kt @@ -0,0 +1,136 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.widgets + +import android.graphics.Point +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +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 applyWithViewHierarchyPrinting +import org.hamcrest.core.AllOf.allOf +import org.kiwix.kiwixmobile.BaseRobot +import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.main.KiwixMainActivity +import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView + +fun searchWidget(func: SearchWidgetRobot.() -> Unit) = + SearchWidgetRobot().applyWithViewHierarchyPrinting(func) + +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 + + uiDevice.swipe( + widgetBounds.centerX(), + widgetBounds.centerY(), + center.x, + 100, + 150 + ) + + uiDevice.waitForIdle() + } catch (ignore: Exception) { + // nothing to do since widget is not added + } + } + + fun addWidgetToHomeScreen(uiDevice: 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() + } + + fun assertSearchWidgetAddedToHomeScreen(uiDevice: UiDevice) { + uiDevice.findObject(By.text("Search Kiwix")) + } + + 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 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() + } +} diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt new file mode 100644 index 000000000..33e32c41d --- /dev/null +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/widgets/SearchWidgetTest.kt @@ -0,0 +1,110 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.widgets + +import android.os.Build +import androidx.lifecycle.Lifecycle +import androidx.test.core.app.ActivityScenario +import androidx.test.espresso.accessibility.AccessibilityChecks +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheck +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews +import com.google.android.apps.common.testing.accessibility.framework.checks.TouchTargetSizeCheck +import org.hamcrest.Matchers.allOf +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.kiwix.kiwixmobile.BaseActivityTest +import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil +import org.kiwix.kiwixmobile.main.KiwixMainActivity +import org.kiwix.kiwixmobile.testutils.RetryRule +import org.kiwix.kiwixmobile.testutils.TestUtils + +class SearchWidgetTest : BaseActivityTest() { + + @Rule + @JvmField + var retryRule = RetryRule() + private lateinit var kiwixMainActivity: KiwixMainActivity + private lateinit var uiDevice: UiDevice + + init { + AccessibilityChecks.enable().apply { + setRunChecksFromRootView(true) + setSuppressingResultMatcher( + allOf( + matchesCheck(TouchTargetSizeCheck::class.java), + matchesViews(withContentDescription("More options")) + ) + ) + } + } + + @Before + override fun waitForIdle() { + uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + if (TestUtils.isSystemUINotRespondingDialogVisible(this)) { + TestUtils.closeSystemDialogs(context, this) + } + waitForIdle() + } + context.let { + SharedPreferenceUtil(it).apply { + setIntroShown() + putPrefWifiOnly(false) + setIsPlayStoreBuildType(true) + prefIsTest = true + putPrefLanguage("en") + lastDonationPopupShownInMilliSeconds = System.currentTimeMillis() + } + } + activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply { + moveToState(Lifecycle.State.RESUMED) + } + } + + @Test + fun testSearchWidget() { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) { + activityScenario.onActivity { + kiwixMainActivity = it + } + searchWidget { + pressHome() + removeWidgetIfAlreadyAdded(uiDevice) + addWidgetToHomeScreen(uiDevice) + assertSearchWidgetAddedToHomeScreen(uiDevice) + clickOnBookmarkIcon(uiDevice, kiwixMainActivity) + assertBookmarkScreenVisible() + pressBack() + pressHome() + clickOnMicIcon(uiDevice, kiwixMainActivity) + assertSearchScreenVisible() + pressBack() + pressHome() + clickOnSearchText(uiDevice, kiwixMainActivity) + assertSearchScreenVisible() + pressHome() + removeWidgetIfAlreadyAdded(uiDevice) + } + } + } +}