diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index b6a253871..13fcd1969 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -37,7 +37,7 @@ android {
buildConfigField "Long", "BuildTimestamp",
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
testInstrumentationRunner 'org.briarproject.briar.android.BriarTestRunner'
- testInstrumentationRunnerArguments disableAnalytics: 'true', clearPackageData: 'true'
+ testInstrumentationRunnerArguments disableAnalytics: 'true'
}
buildTypes {
diff --git a/briar-android/src/androidTest/java/org/briarproject/briar/android/UiTest.java b/briar-android/src/androidTest/java/org/briarproject/briar/android/UiTest.java
index 63691223d..5c78c3043 100644
--- a/briar-android/src/androidTest/java/org/briarproject/briar/android/UiTest.java
+++ b/briar-android/src/androidTest/java/org/briarproject/briar/android/UiTest.java
@@ -4,10 +4,8 @@ import android.app.Activity;
import android.content.Intent;
import org.briarproject.bramble.api.account.AccountManager;
-import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.briar.R;
import org.junit.ClassRule;
@@ -16,9 +14,8 @@ import javax.inject.Inject;
import androidx.test.espresso.intent.rule.IntentsTestRule;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN;
-import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
@SuppressWarnings("WeakerAccess")
@@ -46,6 +43,12 @@ public abstract class UiTest {
protected abstract void inject(BriarUiTestComponent component);
+ protected void startActivity(Class extends Activity> clazz) {
+ Intent i = new Intent(getApplicationContext(), clazz);
+ i.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+
@NotNullByDefault
protected class CleanAccountTestRule
extends IntentsTestRule {
@@ -57,18 +60,14 @@ public abstract class UiTest {
@Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
- // Android Test Orchestrator already clears existing accounts
+ accountManager.deleteAccount();
accountManager.createAccount(USERNAME, PASSWORD);
Intent serviceIntent =
new Intent(getApplicationContext(), BriarService.class);
getApplicationContext().startService(serviceIntent);
try {
lifecycleManager.waitForStartup();
- // do not show doze white-listing dialog
- Settings settings = new Settings();
- settings.putBoolean(DOZE_ASK_AGAIN, false);
- settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
- } catch (InterruptedException | DbException e) {
+ } catch (InterruptedException e) {
throw new AssertionError(e);
}
}
diff --git a/briar-android/src/androidTest/java/org/briarproject/briar/android/ViewActions.java b/briar-android/src/androidTest/java/org/briarproject/briar/android/ViewActions.java
index a1d631e81..1154272ca 100644
--- a/briar-android/src/androidTest/java/org/briarproject/briar/android/ViewActions.java
+++ b/briar-android/src/androidTest/java/org/briarproject/briar/android/ViewActions.java
@@ -1,6 +1,7 @@
package org.briarproject.briar.android;
import android.app.Activity;
+import android.util.Log;
import android.view.View;
import org.hamcrest.Matcher;
@@ -20,6 +21,7 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.util.HumanReadables.describe;
import static androidx.test.espresso.util.TreeIterables.breadthFirstViewTraversal;
+import static androidx.test.runner.lifecycle.Stage.RESUMED;
import static java.lang.System.currentTimeMillis;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -32,13 +34,22 @@ public class ViewActions {
onView(isRoot()).perform(waitUntilMatches(hasDescendant(viewMatcher)));
}
+ public static void waitFor(final Class extends Activity> clazz) {
+ onView(isRoot()).perform(waitForActivity(clazz, RESUMED, TIMEOUT_MS));
+ }
+
+ public static void waitFor(final Class extends Activity> clazz,
+ long timeout) {
+ onView(isRoot()).perform(waitForActivity(clazz, RESUMED, timeout));
+ }
+
public static ViewAction waitUntilMatches(Matcher viewMatcher) {
return waitUntilMatches(viewMatcher, TIMEOUT_MS);
}
private static ViewAction waitUntilMatches(Matcher viewMatcher,
long timeout) {
- return new CustomViewAction() {
+ return new CustomViewAction(timeout) {
@Override
protected boolean exitConditionTrue(View view) {
for (View child : breadthFirstViewTraversal(view)) {
@@ -55,24 +66,43 @@ public class ViewActions {
};
}
- public static ViewAction waitForActivity(Activity activity, Stage stage) {
+ public static ViewAction waitForActivity(Class extends Activity> clazz,
+ Stage stage, long timeout) {
return new CustomViewAction() {
@Override
protected boolean exitConditionTrue(View view) {
+ boolean found = false;
ActivityLifecycleMonitor lifecycleMonitor =
ActivityLifecycleMonitorRegistry.getInstance();
- return lifecycleMonitor.getLifecycleStageOf(activity) == stage;
+ for (Activity a : lifecycleMonitor
+ .getActivitiesInStage(stage)) {
+ Log.e("TEST", a.getClass().getSimpleName() +
+ " is in state " + stage);
+ if (a.getClass().equals(clazz)) found = true;
+ }
+ return found;
}
@Override
public String getDescription() {
- return "Wait for activity " + activity.getClass().getName() +
- " to resume within " + TIMEOUT_MS + " milliseconds.";
+ return "Wait for activity " + clazz.getName() + " in stage " +
+ stage.name() + " within " + timeout +
+ " milliseconds.";
}
};
}
private static abstract class CustomViewAction implements ViewAction {
+ private final long timeout;
+
+ public CustomViewAction() {
+ this(TIMEOUT_MS);
+ }
+
+ public CustomViewAction(long timeout) {
+ this.timeout = timeout;
+ }
+
@Override
public Matcher getConstraints() {
return isDisplayed();
@@ -81,7 +111,7 @@ public class ViewActions {
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
- long endTime = currentTimeMillis() + TIMEOUT_MS;
+ long endTime = currentTimeMillis() + timeout;
do {
if (exitConditionTrue(view)) return;
uiController.loopMainThreadForAtLeast(WAIT_MS);
diff --git a/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/BriarUiTestComponent.java b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/BriarUiTestComponent.java
index e8c81393f..f4b7a6dee 100644
--- a/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/BriarUiTestComponent.java
+++ b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/BriarUiTestComponent.java
@@ -4,6 +4,8 @@ import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.briar.BriarCoreModule;
+import org.briarproject.briar.android.account.SignInTestCreateAccount;
+import org.briarproject.briar.android.account.SignInTestSignIn;
import org.briarproject.briar.android.attachment.AttachmentModule;
import org.briarproject.briar.android.attachment.media.MediaModule;
import org.briarproject.briar.android.navdrawer.NavDrawerActivityTest;
@@ -26,4 +28,8 @@ public interface BriarUiTestComponent extends AndroidComponent {
void inject(NavDrawerActivityTest test);
+ void inject(SignInTestCreateAccount test);
+
+ void inject(SignInTestSignIn test);
+
}
diff --git a/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestCreateAccount.java b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestCreateAccount.java
new file mode 100644
index 000000000..a66583428
--- /dev/null
+++ b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestCreateAccount.java
@@ -0,0 +1,65 @@
+package org.briarproject.briar.android.account;
+
+import android.view.Gravity;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.BriarUiTestComponent;
+import org.briarproject.briar.android.UiTest;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
+import org.briarproject.briar.android.splash.SplashScreenActivity;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.espresso.contrib.DrawerActions;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.DrawerMatchers.isClosed;
+import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.briarproject.briar.android.ViewActions.waitFor;
+import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
+import static org.hamcrest.Matchers.endsWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SignInTestCreateAccount extends UiTest {
+
+ @Override
+ protected void inject(BriarUiTestComponent component) {
+ component.inject(this);
+ }
+
+ @Test
+ public void createAccount() throws Exception {
+ accountManager.deleteAccount();
+ accountManager.createAccount(USERNAME, PASSWORD);
+
+ startActivity(SplashScreenActivity.class);
+ lifecycleManager.waitForStartup();
+ waitFor(NavDrawerActivity.class);
+
+ // open nav drawer
+ onView(withId(R.id.drawer_layout))
+ .check(matches(isClosed(Gravity.START)))
+ .perform(DrawerActions.open());
+
+ // click onboarding away (once shown)
+ onView(isRoot()).perform(waitUntilMatches(hasDescendant(
+ withClassName(endsWith("PromptView")))));
+ onView(withClassName(endsWith("PromptView")))
+ .perform(click());
+
+ // sign-out manually
+ onView(withText(R.string.sign_out_button))
+ .check(matches(isDisplayed()))
+ .perform(click());
+ lifecycleManager.waitForShutdown();
+ }
+
+}
diff --git a/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestSignIn.java b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestSignIn.java
new file mode 100644
index 000000000..30bb9aaad
--- /dev/null
+++ b/briar-android/src/androidTestOfficial/java/org/briarproject/briar/android/account/SignInTestSignIn.java
@@ -0,0 +1,59 @@
+package org.briarproject.briar.android.account;
+
+import android.view.Gravity;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.BriarUiTestComponent;
+import org.briarproject.briar.android.UiTest;
+import org.briarproject.briar.android.login.StartupActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
+import org.briarproject.briar.android.splash.SplashScreenActivity;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.replaceText;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.DrawerMatchers.isClosed;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static org.briarproject.briar.android.ViewActions.waitFor;
+import static org.hamcrest.CoreMatchers.allOf;
+
+/**
+ * This relies on class sorting to run after {@link SignInTestCreateAccount}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SignInTestSignIn extends UiTest {
+
+ @Override
+ protected void inject(BriarUiTestComponent component) {
+ component.inject(this);
+ }
+
+ @Test
+ public void signIn() throws Exception {
+ startActivity(SplashScreenActivity.class);
+
+ waitFor(StartupActivity.class);
+
+ // enter password
+ onView(withId(R.id.edit_password))
+ .check(matches(isDisplayed()))
+ .perform(replaceText(PASSWORD));
+ onView(withId(R.id.btn_sign_in))
+ .check(matches(allOf(isDisplayed(), isEnabled())))
+ .perform(click());
+
+ lifecycleManager.waitForStartup();
+ waitFor(NavDrawerActivity.class);
+
+ // ensure nav drawer is visible
+ onView(withId(R.id.drawer_layout))
+ .check(matches(isClosed(Gravity.START)));
+ }
+}
diff --git a/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/PromoVideoTest.java b/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/PromoVideoTest.java
index 87b69cb4a..0c8034a7f 100644
--- a/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/PromoVideoTest.java
+++ b/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/PromoVideoTest.java
@@ -8,6 +8,9 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.briar.R;
+import org.briarproject.briar.android.account.SetupActivity;
+import org.briarproject.briar.android.contact.add.remote.PendingContactListActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.hamcrest.Matcher;
import org.junit.Rule;
@@ -66,6 +69,7 @@ public class PromoVideoTest extends ScreenshotTest {
@Override
protected void inject(BriarUiTestComponent component) {
component.inject(this);
+ accountManager.deleteAccount();
}
@Test
@@ -80,9 +84,8 @@ public class PromoVideoTest extends ScreenshotTest {
onView(withId(R.id.logoView))
.perform(waitUntilMatches(isDisplayed()));
- int duration = getApplicationContext().getResources()
- .getInteger(R.integer.splashScreenDuration);
- sleep(Math.max(DELAY_LONG, duration));
+ if (debug) waitFor(SetupActivity.class, 25_000);
+ sleep(DELAY_LONG);
// Enter username
onView(withText(R.string.setup_title))
@@ -132,7 +135,8 @@ public class PromoVideoTest extends ScreenshotTest {
sleep(DELAY_SMALL);
- waitFor(allOf(withId(R.id.speedDial), isDisplayed()));
+ // wait for contact list to be shown
+ if (debug) waitFor(NavDrawerActivity.class);
// clicking the FAB doesn't work, so we click its inner FAB as well
onView(withId(R.id.speedDial))
@@ -173,8 +177,11 @@ public class PromoVideoTest extends ScreenshotTest {
sleep(DELAY_LONG);
// wait for pending contact list activity to be shown
- waitFor(allOf(withText(R.string.pending_contact_requests),
- isDisplayed()));
+ if (debug) {
+ waitFor(PendingContactListActivity.class);
+ waitFor(allOf(withText(R.string.pending_contact_requests),
+ isDisplayed()));
+ }
// remove pending contact
for (Pair p : contactManager
@@ -187,8 +194,14 @@ public class PromoVideoTest extends ScreenshotTest {
connectionRegistry.registerIncomingConnection(bob.getId(), ID, () -> {
});
+ sleep(DELAY_LONG);
+
// wait for contact list to be shown
- waitFor(allOf(withText(R.string.contact_list_button), isDisplayed()));
+ if (debug) {
+ waitFor(NavDrawerActivity.class);
+ waitFor(allOf(withText(R.string.contact_list_button),
+ isDisplayed()));
+ }
// click on new contact
doItemClick(withId(R.id.recyclerView), 0);
diff --git a/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/SetupDataTest.java b/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/SetupDataTest.java
index 4faaf99f1..b0d3f6a4d 100644
--- a/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/SetupDataTest.java
+++ b/briar-android/src/androidTestScreenshot/java/org/briarproject/briar/android/SetupDataTest.java
@@ -42,6 +42,7 @@ public class SetupDataTest extends ScreenshotTest {
@Override
protected void inject(BriarUiTestComponent component) {
component.inject(this);
+ accountManager.deleteAccount();
}
@Test