Skip to content

Commit

Permalink
Merge branch 'master' into TECH-Screenshot-comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikitae57 committed Aug 16, 2024
2 parents 6065dd4 + c9edb88 commit 4ac4c14
Show file tree
Hide file tree
Showing 20 changed files with 241 additions and 17 deletions.
12 changes: 7 additions & 5 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ check_android_30_task:
skip: "changesIncludeOnly('NOTICE.txt', 'LICENSE.txt', '**.{md,html}')"

container:
image: ghcr.io/cirruslabs/flutter:latest
image: ghcr.io/cirruslabs/android-sdk:34
kvm: true
cpu: 8
memory: 24G
start_adb_server_background_script:
java -jar artifacts/adbserver-desktop.jar || true
accept_licenses_script:
echo yes | sdkmanager --licenses
install_emulator_script:
install_emulator_script: |
# x86_64 somehow affect the "call" test
sdkmanager "emulator"
sdkmanager --install "system-images;android-30;google_apis;x86"
create_avd_script: |
echo no | avdmanager create avd --force -n emulator -k "system-images;android-30;google_apis;x86"
Expand Down Expand Up @@ -74,15 +75,16 @@ check_android_33_task:
skip: "changesIncludeOnly('NOTICE.txt', 'LICENSE.txt', '**.{md,html}')"

container:
image: ghcr.io/cirruslabs/flutter:latest
image: ghcr.io/cirruslabs/android-sdk:34
kvm: true
cpu: 8
memory: 24G
start_adb_server_background_script:
java -jar artifacts/adbserver-desktop.jar || true
accept_licenses_script:
echo yes | sdkmanager --licenses
install_emulator_script:
install_emulator_script: |
sdkmanager "emulator"
sdkmanager --install "system-images;android-33;google_apis;x86_64"
create_avd_script: |
echo no | avdmanager create avd --force -n emulator -k "system-images;android-33;google_apis;x86_64"
Expand Down Expand Up @@ -138,7 +140,7 @@ check_android_21_task:
skip: "changesIncludeOnly('NOTICE.txt', 'LICENSE.txt', '**.{md,html}')"

container:
image: ghcr.io/cirruslabs/flutter:latest
image: ghcr.io/cirruslabs/android-sdk:34
kvm: true
cpu: 8
memory: 24G
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ configure<BaseExtension> {
}

defaultConfig {
minSdk = 18
minSdk = 21
targetSdk = 30
}

Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ allure = "2.4.0"
compose = "1.5.4"
composeCompiler = "1.4.8"
activityCompose = "1.4.0"
androidXTest = "1.5.0"
androidXTest = "1.6.1"
testOrchestrator = "1.4.2"
lifecycle = "2.6.2"
thirdPartyReport = "0.19.1035"
Expand Down Expand Up @@ -45,7 +45,7 @@ kotson = "com.github.salomonbrys.kotson:kotson:2.5.0"

espressoCore = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
espressoWeb = { module = "androidx.test.espresso:espresso-web", version.ref = "espresso" }
uiAutomator = "androidx.test.uiautomator:uiautomator:2.2.0"
uiAutomator = "androidx.test.uiautomator:uiautomator:2.3.0"
robolectric = "org.robolectric:robolectric:4.8.2"
kakao = { module = "io.github.kakaocup:kakao", version.ref = "kakao" }
kakaoCompose = { module = "io.github.kakaocup:compose", version.ref = "kakaoCompose" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,14 @@ interface Language {
*/
@MainThread
fun switchInApp(locale: Locale)

/**
* Changes locale for Android OS Settings.
* Under the hood grants CHANGE_CONFIGURATION permission
* (without this permission, it's impossible to change system language)
*
* @throws Throwable if something went wrong
*/
@MainThread
fun switchInSystem(locale: Locale)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import android.os.LocaleList
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.ConfigurationCompat
import androidx.core.os.LocaleListCompat
import com.kaspersky.kaspresso.docloc.SystemLanguage
import com.kaspersky.kaspresso.logger.UiTestLogger
import java.util.Locale

/**
* The implementation of [Language]
*/
class LanguageImpl(
internal class LanguageImpl(
private val logger: UiTestLogger,
private val instrumentation: Instrumentation,
private val systemLanguage: SystemLanguage,
) : Language {

override fun switchInApp(locale: Locale) {
Expand Down Expand Up @@ -45,6 +47,8 @@ class LanguageImpl(
}
}

override fun switchInSystem(locale: Locale) = systemLanguage.switch(locale)

private fun getCurrentLocale(): Locale? =
ConfigurationCompat.getLocales(instrumentation.targetContext.resources.configuration).get(0)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ interface Permissions {
ALLOW,
ALLOW_ALWAYS,
ALLOW_FOREGROUND,
ALLOW_ALL,
ALLOW_SELECTED,
DENY
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class PermissionsImpl(
Permissions.Button.ALLOW to getResIdWithPackageName("permission_allow_button"),
Permissions.Button.ALLOW_ALWAYS to getResIdWithPackageName("permission_allow_always_button"),
Permissions.Button.ALLOW_FOREGROUND to getResIdWithPackageName("permission_allow_foreground_only_button"),
Permissions.Button.ALLOW_ALL to getResIdWithPackageName("permission_allow_all_button"),
Permissions.Button.ALLOW_SELECTED to getResIdWithPackageName("permission_allow_selected_button"),
Permissions.Button.DENY to getResIdWithPackageName("permission_deny_button")
)

Expand Down Expand Up @@ -112,10 +114,11 @@ class PermissionsImpl(
*/
private fun getPermissionDialogButtonAsUiObject(button: Permissions.Button): UiObject? {
return try {
val buttonResId = buttonResNameMap[button] ?: return null
val btnSelector = UiSelector()
.clickable(true)
.checkable(false)
.resourceId(buttonResNameMap[button])
.resourceId(buttonResId)
uiDevice.findObject(btnSelector)
} catch (e: UiObjectNotFoundException) {
logger.e("There are no permissions dialog to interact with.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.kaspersky.kaspresso.device.permissions.HackPermissions
import com.kaspersky.kaspresso.logger.UiTestLogger
import java.util.Locale

class SystemLanguage(
internal class SystemLanguage(
private val context: Context,
private val logger: UiTestLogger,
private val hackPermissions: HackPermissions
Expand Down Expand Up @@ -40,7 +40,7 @@ class SystemLanguage(
Failed to change system locale due to API restrictions. To fix this execute one of the following commands.
For Android 10 (API level 29) or higher:
"adb shell settings put global hidden_api_policy 1"
For Android 9 (API level 28):
For Android 9 (API level 28):
"adb shell settings put global hidden_api_policy_pre_p_apps 1"
"adb shell settings put global hidden_api_policy_p_apps 1"
To rollback these settings execute
Expand All @@ -62,6 +62,7 @@ class SystemLanguage(
* Try to grant permission CHANGE_CONFIGURATION if the permission was not granted
* @throws DocLocException In case of a failure to grant one
*/
@Suppress("DEPRECATION")
private fun grantPermissionsIfNeed() {
val permissionStateAtTheBeginning = context.checkPermission(Manifest.permission.CHANGE_CONFIGURATION, Process.myPid(), Process.myUid())
if (permissionStateAtTheBeginning == PackageManager.PERMISSION_GRANTED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import com.kaspersky.kaspresso.device.video.VideosImpl
import com.kaspersky.kaspresso.device.video.recorder.VideoRecorderImpl
import com.kaspersky.kaspresso.device.viewhierarchy.ViewHierarchyDumper
import com.kaspersky.kaspresso.device.viewhierarchy.ViewHierarchyDumperImpl
import com.kaspersky.kaspresso.docloc.SystemLanguage
import com.kaspersky.kaspresso.failure.LoggingFailureHandler
import com.kaspersky.kaspresso.files.dirs.DefaultDirsProvider
import com.kaspersky.kaspresso.files.dirs.DirsProvider
Expand Down Expand Up @@ -761,7 +762,10 @@ data class Kaspresso(
instrumentalDependencyProviderFactory.getComponentProvider<ExploitImpl>(instrumentation),
adbServer
)
if (!::language.isInitialized) language = LanguageImpl(libLogger, instrumentation)
if (!::language.isInitialized) {
val systemLanguage = SystemLanguage(instrumentation.targetContext, testLogger, hackPermissions)
language = LanguageImpl(libLogger, instrumentation, systemLanguage)
}
if (!::logcat.isInitialized) logcat = LogcatImpl(libLogger, adbServer)

if (!::flakySafetyParams.isInitialized) flakySafetyParams = FlakySafetyParams.default()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@file:Suppress("unused")
package com.kaspersky.components.kautomator.component.common.builders

import android.os.Build
import androidx.annotation.IdRes
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.BySelector
Expand Down Expand Up @@ -315,6 +317,41 @@ class UiViewBuilder {
*/
fun withMaxDepth(max: Int) = addSelector { maxDepth(max) }

/**
* Matches the view being on the display with the provided id
*/
@RequiresApi(Build.VERSION_CODES.R)
fun withDisplayId(id: Int) = addSelector { displayId(id) }

/**
* Matches the view that has parent which fits the given matcher
*/
fun withParent(function: UiViewBuilder.() -> Unit) = addSelector { hasParent(UiViewBuilder().apply(function).build().bySelector) }

/**
* Matches the view with given hint
*
* @param text Text to match
*/
@RequiresApi(Build.VERSION_CODES.O)
fun withHint(text: String) = addSelector { hint(text) }

/**
* Matches the view with given hint
*
* @param textRes Text to match
*/
@RequiresApi(Build.VERSION_CODES.O)
fun withHint(@StringRes textRes: Int) = addSelector { hint(KString.getString(textRes)) }

/**
* Matches the view with given hint
*
* @param text Text to match
*/
@RequiresApi(Build.VERSION_CODES.O)
fun withHint(text: Pattern) = addSelector { hint(text) }

/**
* Matches the view which has child of given matcher
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.test.rule.GrantPermissionRule
import com.kaspersky.kaspressample.MainActivity
import com.kaspersky.kaspressample.screen.ChangeLocaleScreen
import com.kaspersky.kaspressample.screen.MainScreen
import com.kaspersky.kaspresso.docloc.SystemLanguage
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import org.junit.Rule
import org.junit.Test
Expand All @@ -24,20 +23,19 @@ class ChangeSystemLanguageMidTestCase : TestCase() {

@Test
fun checkLocaleChangeMidTest() = run {
val systemLanguage = SystemLanguage(device.targetContext, testLogger, device.hackPermissions)
step("Open change locale screen") {
MainScreen {
changeLocaleButton { click() }
}
}
step("Check EN locale text") {
systemLanguage.switch(Locale.ENGLISH)
device.language.switchInSystem(Locale.ENGLISH)
ChangeLocaleScreen {
text { containsText("123") }
}
}
step("Check RU locale text") {
systemLanguage.switch(Locale.forLanguageTag("RU"))
device.language.switchInSystem(Locale.forLanguageTag("RU"))
ChangeLocaleScreen {
text { containsText("321") }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.kaspersky.kaspresso.kautomatorsample.kaspresso.sanity

import android.os.Build
import androidx.test.ext.junit.rules.activityScenarioRule
import com.kaspersky.kaspresso.kautomatorsample.ComponentsActivity
import com.kaspersky.kaspresso.kautomatorsample.screen.ComponentsScreen
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import org.junit.Assume
import org.junit.Rule
import org.junit.Test

class HintMatchersTest : TestCase() {

@get:Rule
val activityRule = activityScenarioRule<ComponentsActivity>()

@Test
fun test() = run {
Assume.assumeTrue("Hint matchers are available on API 26+", Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)

ComponentsScreen {
editTextByHintResId { isDisplayed() }
editTextByHintText { isDisplayed() }
editTextByHintPattern { isDisplayed() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import com.kaspersky.components.kautomator.component.bottomnav.UiBottomNavigatio
import com.kaspersky.components.kautomator.component.check.UiCheckBox
import com.kaspersky.components.kautomator.component.chip.UiChipGroup
import com.kaspersky.components.kautomator.component.dialog.UiAlertDialog
import com.kaspersky.components.kautomator.component.edit.UiEditText
import com.kaspersky.components.kautomator.component.text.UiButton
import com.kaspersky.components.kautomator.screen.UiScreen
import com.kaspersky.kaspresso.kautomatorsample.R

object ComponentsScreen : UiScreen<ComponentsScreen>() {

Expand All @@ -16,4 +18,8 @@ object ComponentsScreen : UiScreen<ComponentsScreen>() {
val chipGroup = UiChipGroup { withId(this@ComponentsScreen.packageName, "chipGroup") }
val showDialogBtn = UiButton { withId(this@ComponentsScreen.packageName, "showDialogBtn") }
val dialog = UiAlertDialog(packageName)

val editTextByHintResId = UiEditText { withHint(R.string.hint) }
val editTextByHintText = UiEditText { withHint("Some hint") }
val editTextByHintPattern = UiEditText { withHint("Some.*".toPattern()) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.kaspersky.kaspresso.kautomatorsample.screen

import com.kaspersky.components.kautomator.component.text.UiTextView
import com.kaspersky.components.kautomator.screen.UiScreen
import com.kaspersky.kaspresso.kautomatorsample.R

object ParentSearchScreen : UiScreen<ParentSearchScreen>() {
override val packageName = "com.kaspersky.kaspresso.kautomatorsample"

val textByParentId = UiTextView {
isFocusable()
withParent { withId(R.id.container1) }
}

val textByParentChild = UiTextView {
isFocusable()
withParent {
withChild { withId(R.id.title2) }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.kaspersky.kaspresso.kautomatorsample.test

import androidx.test.ext.junit.rules.activityScenarioRule
import com.kaspersky.kaspresso.kautomatorsample.ParentSearchActivity
import com.kaspersky.kaspresso.kautomatorsample.screen.ParentSearchScreen
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import org.junit.Rule
import org.junit.Test
import com.kaspersky.kaspresso.kautomatorsample.R

class ParentSearchTest : TestCase() {
@get:Rule
val activityRule = activityScenarioRule<ParentSearchActivity>()

@Test
fun test() = run {
ParentSearchScreen {
textByParentId {
val text1 = device.targetContext.resources.getString(R.string.parent_search_value1)
hasText(text1)
}
textByParentChild {
val text2 = device.targetContext.resources.getString(R.string.parent_search_value2)
hasText(text2)
}
}
}
}
1 change: 1 addition & 0 deletions samples/kautomator-sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<activity android:name=".autoscroll.AutoScrollActivity" />
<activity android:name=".flaky.FlakyActivity" />
<activity android:name=".systemdialogs.SystemDialogsActivity" />
<activity android:name=".ParentSearchActivity" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.kaspersky.kaspresso.kautomatorsample

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class ParentSearchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_parent_search)
}
}
Loading

0 comments on commit 4ac4c14

Please sign in to comment.