mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-25 08:16:07 +00:00
Merge pull request #464 from alexbakker/ui-tests
Add initial set of UI tests
This commit is contained in:
commit
0eb338a0bf
6 changed files with 387 additions and 12 deletions
62
.travis.yml
62
.travis.yml
|
@ -1,15 +1,55 @@
|
||||||
language: android
|
language: shell
|
||||||
|
os: linux
|
||||||
|
dist: bionic
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- ANDROID_HOME=/usr/local/android-sdk
|
- TERM=dumb
|
||||||
android:
|
- ABI=x86_64
|
||||||
components:
|
- EMU_FLAVOR=default
|
||||||
- android-29
|
- ADB_INSTALL_TIMEOUT=16
|
||||||
- build-tools-29.0.2
|
- ANDROID_HOME=${HOME}/android
|
||||||
|
- ANDROID_SDK_ROOT=${ANDROID_HOME}
|
||||||
|
- TOOLS=${ANDROID_HOME}/cmdline-tools
|
||||||
|
- PATH=${ANDROID_HOME}/emulator:${TOOLS}/tools/bin:${ANDROID_HOME}/platform-tools:${PATH}
|
||||||
|
jobs:
|
||||||
|
- API=21
|
||||||
|
- API=23
|
||||||
|
#- API=25 <- inconsistent
|
||||||
|
- API=27
|
||||||
|
- API=28
|
||||||
|
#- API=29 <- emulator crashes
|
||||||
|
#- API=R EMU_FLAVOR=google_apis <- too heavy, re-enable when AOSP image is available
|
||||||
before_install:
|
before_install:
|
||||||
- mkdir -p $ANDROID_HOME/licenses
|
- mkdir -p ${ANDROID_HOME}/licenses
|
||||||
- echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > $ANDROID_HOME/licenses/android-sdk-license
|
- echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > ${ANDROID_HOME}/licenses/android-sdk-license
|
||||||
- echo "d56f5187479451eabf01fb78af6dfcb131a6481e" >> $ANDROID_HOME/licenses/android-sdk-license
|
- echo "d56f5187479451eabf01fb78af6dfcb131a6481e" >> ${ANDROID_HOME}/licenses/android-sdk-license
|
||||||
- echo "24333f8a63b6825ea9c5514f83c2829b004d1fee" >> $ANDROID_HOME/licenses/android-sdk-license
|
- echo "24333f8a63b6825ea9c5514f83c2829b004d1fee" >> ${ANDROID_HOME}/licenses/android-sdk-license
|
||||||
|
install:
|
||||||
|
- mkdir -p ${TOOLS}
|
||||||
|
- travis_retry wget https://dl.google.com/android/repository/commandlinetools-linux-6514223_latest.zip -O ${TOOLS}/tools.zip
|
||||||
|
- unzip ${TOOLS}/tools.zip -d ${TOOLS}
|
||||||
|
- yes | travis_retry sdkmanager "platform-tools" > /dev/null
|
||||||
|
- yes | travis_retry sdkmanager "tools" > /dev/null
|
||||||
|
- yes | travis_retry sdkmanager "build-tools;29.0.2" > /dev/null
|
||||||
|
- yes | travis_retry sdkmanager "platforms;android-29" > /dev/null
|
||||||
|
- yes | travis_retry sdkmanager "emulator" > /dev/null
|
||||||
|
- yes | travis_retry sdkmanager "system-images;android-$API;$EMU_FLAVOR;$ABI" > /dev/null
|
||||||
|
- travis_retry sudo apt-get -yq --no-install-suggests install qemu-kvm
|
||||||
|
before_script:
|
||||||
|
- sudo gpasswd -a $USER kvm
|
||||||
script:
|
script:
|
||||||
- ./gradlew build test
|
- ./gradlew assemble check
|
||||||
|
- echo no | avdmanager create avd --force -n test -k "system-images;android-$API;$EMU_FLAVOR;$ABI" -d "Nexus 5X" -c 128M
|
||||||
|
- sudo -E sudo -u $USER -E bash -c "${ANDROID_HOME}/emulator/emulator -verbose -avd test -gpu swiftshader_indirect -no-audio -no-boot-anim -no-snapshot -no-window -camera-back none -camera-front none -selinux permissive -memory 3072 &"
|
||||||
|
- adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
|
||||||
|
- adb shell settings put global window_animation_scale 0
|
||||||
|
- adb shell settings put global transition_animation_scale 0
|
||||||
|
- adb shell settings put global animator_duration_scale 0
|
||||||
|
- adb reboot
|
||||||
|
- adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
|
||||||
|
- adb shell input keyevent 82 &
|
||||||
|
- bash .travis/android-wait-for-launcher.sh
|
||||||
|
- adb logcat -c
|
||||||
|
- ./gradlew connectedCheck
|
||||||
|
after_failure:
|
||||||
|
- adb logcat -d
|
||||||
|
|
33
.travis/android-wait-for-launcher.sh
Executable file
33
.travis/android-wait-for-launcher.sh
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# source: https://gist.github.com/d4vidi/7862d60375b38f8970f824c4ce0ad2a9
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[Waiting for launcher to start]"
|
||||||
|
LAUNCHER_READY=
|
||||||
|
while [[ -z ${LAUNCHER_READY} ]]; do
|
||||||
|
UI_FOCUS=`adb shell dumpsys activity activities 2>/dev/null | grep -i mResumedActivity`
|
||||||
|
echo "(DEBUG) Current focus: ${UI_FOCUS}"
|
||||||
|
|
||||||
|
case $UI_FOCUS in
|
||||||
|
*"Launcher"*)
|
||||||
|
LAUNCHER_READY=true
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
echo "Waiting for window service..."
|
||||||
|
sleep 3
|
||||||
|
;;
|
||||||
|
*"Not Responding"*)
|
||||||
|
echo "Detected an ANR! Dismissing..."
|
||||||
|
adb shell input keyevent KEYCODE_DPAD_DOWN
|
||||||
|
adb shell input keyevent KEYCODE_DPAD_DOWN
|
||||||
|
adb shell input keyevent KEYCODE_ENTER
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Waiting for launcher..."
|
||||||
|
sleep 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Launcher is ready :-)"
|
|
@ -25,6 +25,9 @@ android {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
|
buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
|
||||||
buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\""
|
buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\""
|
||||||
|
|
||||||
|
testInstrumentationRunner "com.beemdevelopment.aegis.AegisTestRunner"
|
||||||
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
|
@ -123,7 +126,7 @@ dependencies {
|
||||||
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
||||||
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
|
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
|
||||||
implementation "com.google.guava:guava:${guavaVersion}-android"
|
implementation "com.google.guava:guava:${guavaVersion}-android"
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'com.google.protobuf:protobuf-javalite:3.12.1'
|
implementation 'com.google.protobuf:protobuf-javalite:3.12.1'
|
||||||
implementation 'com.google.zxing:core:3.4.0'
|
implementation 'com.google.zxing:core:3.4.0'
|
||||||
implementation "com.mikepenz:iconics-core:3.2.5"
|
implementation "com.mikepenz:iconics-core:3.2.5"
|
||||||
|
@ -134,6 +137,16 @@ dependencies {
|
||||||
implementation 'net.lingala.zip4j:zip4j:2.6.0'
|
implementation 'net.lingala.zip4j:zip4j:2.6.0'
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
||||||
|
|
||||||
|
androidTestImplementation 'androidx.test:core:1.2.0'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
|
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
|
||||||
|
androidTestImplementation 'junit:junit:4.13'
|
||||||
|
androidTestUtil 'androidx.test:orchestrator:1.2.0'
|
||||||
|
|
||||||
testImplementation "com.google.guava:guava:${guavaVersion}-jre"
|
testImplementation "com.google.guava:guava:${guavaVersion}-jre"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
|
||||||
|
|
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
|
@ -16,6 +16,8 @@
|
||||||
# public *;
|
# public *;
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
-keepclasseswithmembers public class androidx.recyclerview.widget.RecyclerView { *; }
|
||||||
|
|
||||||
-keep class com.beemdevelopment.aegis.importers.** { *; }
|
-keep class com.beemdevelopment.aegis.importers.** { *; }
|
||||||
|
|
||||||
-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
|
-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
package com.beemdevelopment.aegis;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.espresso.AmbiguousViewMatcherException;
|
||||||
|
import androidx.test.espresso.UiController;
|
||||||
|
import androidx.test.espresso.ViewAction;
|
||||||
|
import androidx.test.espresso.ViewInteraction;
|
||||||
|
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
import androidx.test.rule.ActivityTestRule;
|
||||||
|
|
||||||
|
import com.beemdevelopment.aegis.crypto.CryptoUtils;
|
||||||
|
import com.beemdevelopment.aegis.encoding.Base32;
|
||||||
|
import com.beemdevelopment.aegis.otp.HotpInfo;
|
||||||
|
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||||
|
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||||
|
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||||
|
import com.beemdevelopment.aegis.ui.MainActivity;
|
||||||
|
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||||
|
import com.beemdevelopment.aegis.vault.VaultManager;
|
||||||
|
import com.beemdevelopment.aegis.vault.slots.PasswordSlot;
|
||||||
|
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static androidx.test.espresso.Espresso.onData;
|
||||||
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
|
import static androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.clearText;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.click;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.longClick;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.pressBack;
|
||||||
|
import static androidx.test.espresso.action.ViewActions.typeText;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static junit.framework.TestCase.assertNull;
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
import static org.hamcrest.Matchers.anything;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@LargeTest
|
||||||
|
public class AegisTest {
|
||||||
|
private static final String _password = "test";
|
||||||
|
private static final String _groupName = "Test";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doOverallTest() {
|
||||||
|
ViewInteraction next = onView(withId(R.id.next));
|
||||||
|
next.perform(click());
|
||||||
|
onView(withId(R.id.rb_password)).perform(click());
|
||||||
|
next.perform(click());
|
||||||
|
onView(withId(R.id.text_password)).perform(typeText(_password), closeSoftKeyboard());
|
||||||
|
onView(withId(R.id.text_password_confirm)).perform(typeText(_password), closeSoftKeyboard());
|
||||||
|
next.perform(click());
|
||||||
|
onView(withId(R.id.done)).perform(click());
|
||||||
|
|
||||||
|
VaultManager vault = getVault();
|
||||||
|
assertTrue(vault.isEncryptionEnabled());
|
||||||
|
assertTrue(vault.getCredentials().getSlots().has(PasswordSlot.class));
|
||||||
|
|
||||||
|
List<VaultEntry> entries = Arrays.asList(
|
||||||
|
generateEntry(TotpInfo.class, "Frank", "Google"),
|
||||||
|
generateEntry(HotpInfo.class, "John", "GitHub"),
|
||||||
|
generateEntry(TotpInfo.class, "Alice", "Office 365"),
|
||||||
|
generateEntry(SteamInfo.class, "Gaben", "Steam")
|
||||||
|
);
|
||||||
|
for (VaultEntry entry : entries) {
|
||||||
|
addEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VaultEntry> realEntries = new ArrayList<>(vault.getEntries());
|
||||||
|
for (int i = 0; i < realEntries.size(); i++) {
|
||||||
|
assertTrue(realEntries.get(i).equivalates(entries.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(1, clickChildViewWithId(R.id.buttonRefresh)));
|
||||||
|
}
|
||||||
|
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||||
|
onView(withId(R.id.action_copy)).perform(click());
|
||||||
|
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(1, longClick()));
|
||||||
|
onView(withId(R.id.action_edit)).perform(click());
|
||||||
|
onView(withId(R.id.text_name)).perform(clearText(), typeText("Bob"), closeSoftKeyboard());
|
||||||
|
onView(withId(R.id.spinner_group)).perform(click());
|
||||||
|
onData(anything()).atPosition(1).perform(click());
|
||||||
|
onView(withId(R.id.text_input)).perform(typeText(_groupName), closeSoftKeyboard());
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
onView(isRoot()).perform(pressBack());
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
|
||||||
|
changeSort(R.string.sort_alphabetically_name);
|
||||||
|
changeSort(R.string.sort_alphabetically_name_reverse);
|
||||||
|
changeSort(R.string.sort_alphabetically);
|
||||||
|
changeSort(R.string.sort_alphabetically_reverse);
|
||||||
|
changeSort(R.string.sort_custom);
|
||||||
|
|
||||||
|
changeFilter(_groupName);
|
||||||
|
changeFilter(R.string.filter_ungrouped);
|
||||||
|
changeFilter(R.string.all);
|
||||||
|
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(1, longClick()));
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(3, click()));
|
||||||
|
onView(withId(R.id.action_share_qr)).perform(click());
|
||||||
|
onView(withId(R.id.btnNext)).perform(click()).perform(click()).perform(click());
|
||||||
|
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(2, longClick()));
|
||||||
|
onView(withId(R.id.action_delete)).perform(click());
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
|
||||||
|
openContextualActionModeOverflowMenu();
|
||||||
|
onView(withText(R.string.lock)).perform(click());
|
||||||
|
onView(withId(R.id.text_password)).perform(typeText(_password), closeSoftKeyboard());
|
||||||
|
onView(withId(R.id.button_decrypt)).perform(click());
|
||||||
|
vault = getVault();
|
||||||
|
|
||||||
|
openContextualActionModeOverflowMenu();
|
||||||
|
onView(withText(R.string.action_settings)).perform(click());
|
||||||
|
onView(withId(androidx.preference.R.id.recycler_view)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText(R.string.pref_encryption_title)), click()));
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
|
||||||
|
assertFalse(vault.isEncryptionEnabled());
|
||||||
|
assertNull(vault.getCredentials());
|
||||||
|
|
||||||
|
onView(withId(androidx.preference.R.id.recycler_view)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText(R.string.pref_encryption_title)), click()));
|
||||||
|
onView(withId(R.id.text_password)).perform(typeText(_password), closeSoftKeyboard());
|
||||||
|
onView(withId(R.id.text_password_confirm)).perform(typeText(_password), closeSoftKeyboard());
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
|
||||||
|
assertTrue(vault.isEncryptionEnabled());
|
||||||
|
assertTrue(vault.getCredentials().getSlots().has(PasswordSlot.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeSort(@IdRes int resId) {
|
||||||
|
onView(withId(R.id.action_sort)).perform(click());
|
||||||
|
onView(withText(resId)).perform(click());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeFilter(String text) {
|
||||||
|
openContextualActionModeOverflowMenu();
|
||||||
|
onView(withText(R.string.filter)).perform(click());
|
||||||
|
onView(withText(text)).perform(click());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeFilter(@IdRes int resId) {
|
||||||
|
changeFilter(ApplicationProvider.getApplicationContext().getString(resId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addEntry(VaultEntry entry) {
|
||||||
|
onView(withId(R.id.fab_expand_menu_button)).perform(click());
|
||||||
|
onView(withId(R.id.fab_enter)).perform(click());
|
||||||
|
|
||||||
|
onView(withId(R.id.text_name)).perform(typeText(entry.getName()), closeSoftKeyboard());
|
||||||
|
onView(withId(R.id.text_issuer)).perform(typeText(entry.getIssuer()), closeSoftKeyboard());
|
||||||
|
|
||||||
|
if (entry.getInfo().getClass() != TotpInfo.class) {
|
||||||
|
int i = entry.getInfo() instanceof HotpInfo ? 1 : 2;
|
||||||
|
try {
|
||||||
|
onView(withId(R.id.spinner_type)).perform(click());
|
||||||
|
onData(anything()).atPosition(i).perform(click());
|
||||||
|
} catch (AmbiguousViewMatcherException e) {
|
||||||
|
// for some reason, clicking twice is sometimes necessary, otherwise the test fails on the next line
|
||||||
|
onView(withId(R.id.spinner_type)).perform(click());
|
||||||
|
onData(anything()).atPosition(i).perform(click());
|
||||||
|
}
|
||||||
|
if (entry.getInfo() instanceof HotpInfo) {
|
||||||
|
onView(withId(R.id.text_counter)).perform(typeText("0"), closeSoftKeyboard());
|
||||||
|
}
|
||||||
|
if (entry.getInfo() instanceof SteamInfo) {
|
||||||
|
onView(withId(R.id.text_digits)).perform(clearText(), typeText("5"), closeSoftKeyboard());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String secret = Base32.encode(entry.getInfo().getSecret());
|
||||||
|
onView(withId(R.id.text_secret)).perform(typeText(secret), closeSoftKeyboard());
|
||||||
|
|
||||||
|
onView(withId(R.id.action_save)).perform(click());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends OtpInfo> VaultEntry generateEntry(Class<T> type, String name, String issuer) {
|
||||||
|
byte[] secret = CryptoUtils.generateRandomBytes(20);
|
||||||
|
|
||||||
|
OtpInfo info;
|
||||||
|
try {
|
||||||
|
info = type.getConstructor(byte[].class).newInstance(secret);
|
||||||
|
} catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VaultEntry(info, name, issuer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AegisApplication getApp() {
|
||||||
|
return (AegisApplication) activityRule.getActivity().getApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
private VaultManager getVault() {
|
||||||
|
return getApp().getVaultManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
// source: https://stackoverflow.com/a/30338665
|
||||||
|
private static ViewAction clickChildViewWithId(final int id) {
|
||||||
|
return new ViewAction() {
|
||||||
|
@Override
|
||||||
|
public Matcher<View> getConstraints() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Click on a child view with specified id.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view) {
|
||||||
|
View v = view.findViewById(id);
|
||||||
|
v.performClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.beemdevelopment.aegis;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.runner.AndroidJUnitRunner;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class AegisTestRunner extends AndroidJUnitRunner {
|
||||||
|
@Override
|
||||||
|
public void callApplicationOnCreate(Application app) {
|
||||||
|
Context context = app.getApplicationContext();
|
||||||
|
|
||||||
|
// clear internal storage so that there is no vault file
|
||||||
|
clearDirectory(context.getFilesDir(), false);
|
||||||
|
|
||||||
|
// clear preferences so that the intro is started from MainActivity
|
||||||
|
ApplicationProvider.getApplicationContext().getFilesDir();
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
.edit()
|
||||||
|
.clear()
|
||||||
|
.apply();
|
||||||
|
|
||||||
|
super.callApplicationOnCreate(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void clearDirectory(File dir, boolean deleteParent) {
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
clearDirectory(file, true);
|
||||||
|
} else {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteParent) {
|
||||||
|
dir.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue