-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eaf4e6d
commit 2b1e153
Showing
11 changed files
with
288 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env bash | ||
|
||
# assert ANDROID_HOME is set | ||
if [ -z "$ANDROID_SDK_HOME" ]; then | ||
echo "ANDROID_SDK_HOME is not set" | ||
exit 1 | ||
fi | ||
|
||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) | ||
DEVELOPMENT_DIR=$SCRIPT_DIR/.. | ||
ROOT_PROJECT_DIR=$SCRIPT_DIR/../../.. | ||
|
||
EMULATOR_DEVICE_NAME=$($ANDROID_SDK_HOME/platform-tools/adb devices | grep emulator | cut -f1) | ||
|
||
if [ -z "$EMULATOR_DEVICE_NAME" ]; then | ||
echo "Emulator device name not found" | ||
exit 1 | ||
fi | ||
|
||
ADB="$ANDROID_SDK_HOME/platform-tools/adb -s $EMULATOR_DEVICE_NAME" | ||
|
||
$ADB shell pm clear com.stevesoltys.seedvault |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/BackupRestoreTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.stevesoltys.seedvault.e2e | ||
|
||
import com.stevesoltys.seedvault.transport.backup.PackageService | ||
import org.junit.Test | ||
import org.koin.core.component.inject | ||
import java.lang.Thread.sleep | ||
|
||
class BackupRestoreTest : LargeTestBase() { | ||
|
||
private val packageService: PackageService by inject() | ||
|
||
@Test | ||
fun `back up and restore applications`() = run { | ||
launchBackupActivity() | ||
verifyCode() | ||
chooseBackupLocation() | ||
waitUntilIdle() | ||
|
||
val packagesBeforeRestore = packageService.userApps | ||
.map { it.packageName }.toSet() | ||
|
||
packagesBeforeRestore.forEach { | ||
val intent = device.targetContext.packageManager.getLaunchIntentForPackage(it) | ||
|
||
device.targetContext.startActivity(intent) | ||
waitUntilIdle() | ||
} | ||
|
||
runBackup() | ||
sleep(60000) | ||
|
||
packagesBeforeRestore.forEach { runCommand("pm uninstall $it") } | ||
|
||
launchRestoreActivity() | ||
sleep(60000) | ||
|
||
val packagesAfterRestore = packageService.userApps | ||
.map { it.packageName }.toSet() | ||
|
||
assert(packagesBeforeRestore == packagesAfterRestore) | ||
} | ||
} |
129 changes: 129 additions & 0 deletions
129
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/LargeTestBase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package com.stevesoltys.seedvault.e2e | ||
|
||
import android.view.KeyEvent.* | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.filters.LargeTest | ||
import androidx.test.platform.app.InstrumentationRegistry | ||
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase | ||
import com.stevesoltys.seedvault.e2e.screen.BackupScreen | ||
import com.stevesoltys.seedvault.e2e.screen.DocumentPickerScreen | ||
import com.stevesoltys.seedvault.e2e.screen.RecoveryCodeScreen | ||
import org.junit.Before | ||
import org.junit.runner.RunWith | ||
import org.koin.core.component.KoinComponent | ||
import java.lang.Thread.sleep | ||
|
||
@LargeTest | ||
@RunWith(AndroidJUnit4::class) | ||
abstract class LargeTestBase : TestCase(), KoinComponent { | ||
|
||
@Before | ||
fun setUp() { | ||
// reset document picker state, and delete old backups | ||
runCommand("pm clear com.google.android.documentsui") | ||
runCommand("rm -Rf /sdcard/seedvault") | ||
} | ||
|
||
protected fun launchBackupActivity() = run { | ||
runCommand("am start -n com.stevesoltys.seedvault/.settings.SettingsActivity") | ||
device.uiDevice.waitForIdle() | ||
} | ||
|
||
protected fun launchRestoreActivity() = run { | ||
runCommand("am start -n com.stevesoltys.seedvault/.restore.RestoreActivity") | ||
waitUntilIdle() | ||
} | ||
|
||
protected fun waitUntilIdle() { | ||
device.uiDevice.waitForIdle() | ||
sleep(3000) | ||
} | ||
|
||
protected fun verifyCode() = run { | ||
RecoveryCodeScreen { | ||
step("Confirm code") { | ||
confirmCodeButton.isVisible() | ||
confirmCodeButton.click() | ||
} | ||
step("Verify code") { | ||
verifyCodeButton.isVisible() | ||
verifyCodeButton.scrollTo() | ||
verifyCodeButton.click() | ||
} | ||
} | ||
} | ||
|
||
protected fun chooseBackupLocation() = run { | ||
DocumentPickerScreen { | ||
step("Click new folder button") { createNewFolderButton.click() } | ||
|
||
step("Create new folder") { | ||
waitUntilIdle() | ||
type("Seedvault") | ||
device.uiDevice.pressEnter() | ||
} | ||
|
||
step("Click use this folder button") { useThisFolderButton.click() } | ||
|
||
step("Click allow button") { | ||
waitUntilIdle() | ||
device.uiDevice.pressKeyCode(KEYCODE_TAB) | ||
device.uiDevice.pressKeyCode(KEYCODE_TAB) | ||
device.uiDevice.pressEnter() | ||
} | ||
} | ||
} | ||
|
||
protected fun runBackup() = run { | ||
launchBackupActivity() | ||
|
||
BackupScreen { | ||
waitUntilIdle() | ||
device.uiDevice.pressMenu() | ||
waitUntilIdle() | ||
backupNowButton.click() | ||
} | ||
} | ||
|
||
protected fun runCommand(command: String) { | ||
InstrumentationRegistry.getInstrumentation().uiAutomation | ||
.executeShellCommand(command) | ||
.close() | ||
} | ||
|
||
private fun type(text: String) = device.uiDevice.apply { | ||
text.lowercase().toCharArray().map { | ||
when (it) { | ||
'a' -> KEYCODE_A | ||
'b' -> KEYCODE_B | ||
'c' -> KEYCODE_C | ||
'd' -> KEYCODE_D | ||
'e' -> KEYCODE_E | ||
'f' -> KEYCODE_F | ||
'g' -> KEYCODE_G | ||
'h' -> KEYCODE_H | ||
'i' -> KEYCODE_I | ||
'j' -> KEYCODE_J | ||
'k' -> KEYCODE_K | ||
'l' -> KEYCODE_L | ||
'm' -> KEYCODE_M | ||
'n' -> KEYCODE_N | ||
'o' -> KEYCODE_O | ||
'p' -> KEYCODE_P | ||
'q' -> KEYCODE_Q | ||
'r' -> KEYCODE_R | ||
's' -> KEYCODE_S | ||
't' -> KEYCODE_T | ||
'u' -> KEYCODE_U | ||
'v' -> KEYCODE_V | ||
'w' -> KEYCODE_W | ||
'x' -> KEYCODE_X | ||
'y' -> KEYCODE_Y | ||
'z' -> KEYCODE_Z | ||
else -> throw IllegalArgumentException("Unsupported character: $it") | ||
} | ||
}.forEach { | ||
device.uiDevice.pressKeyCode(it) | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/BackupScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stevesoltys.seedvault.e2e.screen | ||
|
||
import com.kaspersky.kaspresso.screens.KScreen | ||
import com.stevesoltys.seedvault.R | ||
import com.stevesoltys.seedvault.settings.SettingsFragment | ||
import io.github.kakaocup.kakao.text.KButton | ||
|
||
object BackupScreen : KScreen<BackupScreen>() { | ||
|
||
override val layoutId: Int? = null | ||
override val viewClass: Class<*>? = null | ||
|
||
val backupNowButton = KButton { withText("Backup now") } | ||
} |
16 changes: 16 additions & 0 deletions
16
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/DocumentPickerScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.stevesoltys.seedvault.e2e.screen | ||
|
||
import com.kaspersky.components.kautomator.component.text.UiButton | ||
import com.kaspersky.components.kautomator.component.text.UiTextView | ||
import com.kaspersky.components.kautomator.screen.UiScreen | ||
|
||
private const val PACKAGE_NAME = "com.android.documentsui.picker" | ||
|
||
object DocumentPickerScreen : UiScreen<DocumentPickerScreen>() { | ||
|
||
override val packageName = PACKAGE_NAME | ||
|
||
val createNewFolderButton = UiTextView { textStartsWith("CREATE NEW FOLDER") } | ||
|
||
val useThisFolderButton = UiButton { withText("USE THIS FOLDER") } | ||
} |
15 changes: 15 additions & 0 deletions
15
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/RecoveryCodeScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.stevesoltys.seedvault.e2e.screen | ||
|
||
import com.kaspersky.kaspresso.screens.KScreen | ||
import com.stevesoltys.seedvault.R | ||
import io.github.kakaocup.kakao.text.KButton | ||
|
||
object RecoveryCodeScreen : KScreen<RecoveryCodeScreen>() { | ||
|
||
override val layoutId: Int? = null | ||
override val viewClass: Class<*>? = null | ||
|
||
val confirmCodeButton = KButton { withId(R.id.confirmCodeButton) } | ||
|
||
val verifyCodeButton = KButton { withId(R.id.doneButton) } | ||
} |
14 changes: 14 additions & 0 deletions
14
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/RestoreScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stevesoltys.seedvault.e2e.screen | ||
|
||
import com.kaspersky.kaspresso.screens.KScreen | ||
import com.stevesoltys.seedvault.R | ||
import com.stevesoltys.seedvault.settings.SettingsFragment | ||
import io.github.kakaocup.kakao.text.KButton | ||
|
||
object RestoreScreen : KScreen<RestoreScreen>() { | ||
|
||
override val layoutId: Int? = null | ||
override val viewClass: Class<*>? = null | ||
|
||
val backupNowButton = KButton { withId(R.id.action_restore) } | ||
} |
16 changes: 16 additions & 0 deletions
16
app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/SettingsScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.stevesoltys.seedvault.e2e.screen | ||
|
||
import com.kaspersky.components.kautomator.component.text.UiTextView | ||
import com.kaspersky.components.kautomator.screen.UiScreen | ||
import com.kaspersky.kaspresso.device.Device | ||
|
||
private const val PACKAGE_NAME = "com.android.settings" | ||
|
||
object SettingsScreen : UiScreen<SettingsScreen>() { | ||
|
||
override val packageName: String = PACKAGE_NAME | ||
|
||
val backupButton = UiTextView { | ||
textStartsWith("Backup") | ||
} | ||
} |