mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Add a first PromoVideoTest
This commit is contained in:
@@ -14,7 +14,10 @@ import androidx.test.runner.lifecycle.ActivityLifecycleMonitor;
|
||||
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
|
||||
import androidx.test.runner.lifecycle.Stage;
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
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.util.HumanReadables.describe;
|
||||
import static androidx.test.espresso.util.TreeIterables.breadthFirstViewTraversal;
|
||||
import static java.lang.System.currentTimeMillis;
|
||||
@@ -25,6 +28,10 @@ public class ViewActions {
|
||||
private final static long TIMEOUT_MS = SECONDS.toMillis(10);
|
||||
private final static long WAIT_MS = 50;
|
||||
|
||||
public static void waitFor(final Matcher<View> viewMatcher) {
|
||||
onView(isRoot()).perform(waitUntilMatches(hasDescendant(viewMatcher)));
|
||||
}
|
||||
|
||||
public static ViewAction waitUntilMatches(Matcher<View> viewMatcher) {
|
||||
return waitUntilMatches(viewMatcher, TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@@ -31,4 +31,6 @@ public interface BriarUiTestComponent extends AndroidComponent {
|
||||
|
||||
void inject(SettingsActivityScreenshotTest test);
|
||||
|
||||
void inject(PromoVideoTest test);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
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.splash.SplashScreenActivity;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
import androidx.test.uiautomator.UiObject;
|
||||
import androidx.test.uiautomator.UiSelector;
|
||||
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
|
||||
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 androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static java.lang.Thread.sleep;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.briar.android.OverlayTapViewAction.visualClick;
|
||||
import static org.briarproject.briar.android.ViewActions.waitFor;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class PromoVideoTest extends ScreenshotTest {
|
||||
|
||||
// we can leave debug to true (to speed up CI)
|
||||
// and only set it to false when doing recordings
|
||||
private static final boolean debug = true;
|
||||
|
||||
private static final int DELAY_SMALL = debug ? 0 : 4_000;
|
||||
private static final int DELAY_MEDIUM = debug ? 0 : 7_500;
|
||||
private static final int DELAY_LONG = debug ? 0 : 10_000;
|
||||
|
||||
@Rule
|
||||
public ActivityScenarioRule<SplashScreenActivity> testRule =
|
||||
new ActivityScenarioRule<>(SplashScreenActivity.class);
|
||||
|
||||
@Inject
|
||||
protected ContactManager contactManager;
|
||||
|
||||
private OverlayView overlayView;
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
component.inject(this);
|
||||
accountManager.deleteAccount();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAccountAddContact() throws Throwable {
|
||||
if (!debug) {
|
||||
// Using this breaks emulator CI tests for some reason.
|
||||
// Only use it for filming for now until we have time to debug this.
|
||||
overlayView = OverlayView.attach(getApplicationContext());
|
||||
}
|
||||
|
||||
// Splash screen shows logo
|
||||
onView(withId(R.id.logoView))
|
||||
.perform(waitUntilMatches(isDisplayed()));
|
||||
|
||||
int duration = getApplicationContext().getResources()
|
||||
.getInteger(R.integer.splashScreenDuration);
|
||||
sleep(Math.max(DELAY_LONG, duration));
|
||||
|
||||
// Enter username
|
||||
onView(withText(R.string.setup_title))
|
||||
.perform(waitUntilMatches(isDisplayed()));
|
||||
sleep(DELAY_SMALL);
|
||||
onView(withId(R.id.nickname_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(replaceText(USERNAME));
|
||||
closeKeyboard(withId(R.id.nickname_entry));
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
doClick(withId(R.id.next));
|
||||
|
||||
sleep(DELAY_MEDIUM);
|
||||
|
||||
// Enter password
|
||||
doClick(withId(R.id.password_entry), 1000);
|
||||
onView(withId(R.id.password_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(replaceText(PASSWORD));
|
||||
sleep(DELAY_SMALL);
|
||||
doClick(withId(R.id.password_confirm), 1000);
|
||||
onView(withId(R.id.password_confirm))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(replaceText(PASSWORD));
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
// click next or create account
|
||||
doClick(withId(R.id.next));
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
// White-list Doze if needed
|
||||
if (needsDozeWhitelisting(getApplicationContext())) {
|
||||
doClick(withText(R.string.setup_doze_button));
|
||||
UiDevice device = UiDevice.getInstance(getInstrumentation());
|
||||
UiObject allowButton = device.findObject(
|
||||
new UiSelector().className("android.widget.Button")
|
||||
.index(1));
|
||||
allowButton.click();
|
||||
doClick(withId(R.id.next));
|
||||
}
|
||||
|
||||
lifecycleManager.waitForStartup();
|
||||
assertTrue(accountManager.hasDatabaseKey());
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
waitFor(allOf(withId(R.id.speedDial), isDisplayed()));
|
||||
|
||||
// clicking the FAB doesn't work, so we click its inner FAB as well
|
||||
onView(withId(R.id.speedDial))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
doClick(withId(R.id.fab_main)); // this is inside R.id.speedDial
|
||||
sleep(DELAY_MEDIUM);
|
||||
|
||||
// click adding contact at a distance menu item
|
||||
doClick(withText(R.string.add_contact_remotely_title));
|
||||
sleep(DELAY_LONG);
|
||||
|
||||
// enter briar:// link
|
||||
String link =
|
||||
"briar://ab54fpik6sjyetzjhlwto2fv7tspibx2uhpdnei4tdidkvjpbphvy";
|
||||
doClick(withId(R.id.pasteButton));
|
||||
onView(withId(R.id.linkInput))
|
||||
.perform(waitUntilMatches(isDisplayed()))
|
||||
.perform(replaceText(link));
|
||||
sleep(DELAY_MEDIUM);
|
||||
|
||||
doClick(withId(R.id.addButton));
|
||||
sleep(DELAY_MEDIUM);
|
||||
|
||||
// enter contact alias
|
||||
String contactName = getApplicationContext()
|
||||
.getString(R.string.screenshot_bob);
|
||||
doClick(withId(R.id.contactNameInput), 1000);
|
||||
onView(withId(R.id.contactNameInput))
|
||||
.perform(waitUntilMatches(isDisplayed()))
|
||||
.perform(replaceText(contactName));
|
||||
sleep(DELAY_SMALL);
|
||||
closeKeyboard(withId(R.id.contactNameInput));
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
// add pending contact
|
||||
doClick(withId(R.id.addButton));
|
||||
sleep(DELAY_LONG);
|
||||
|
||||
// wait for pending contact list activity to be shown
|
||||
waitFor(allOf(withText(R.string.pending_contact_requests),
|
||||
isDisplayed()));
|
||||
|
||||
// remove pending contact
|
||||
for (Pair<PendingContact, PendingContactState> p : contactManager
|
||||
.getPendingContacts()) {
|
||||
contactManager.removePendingContact(p.getFirst().getId());
|
||||
}
|
||||
// add contact and make them appear online
|
||||
Contact bob = testDataCreator.addContact(contactName, false, true);
|
||||
sleep(DELAY_SMALL);
|
||||
connectionRegistry.registerIncomingConnection(bob.getId(), ID, () -> {
|
||||
});
|
||||
|
||||
// wait for contact list to be shown
|
||||
waitFor(allOf(withText(R.string.contact_list_button), isDisplayed()));
|
||||
|
||||
// click on new contact
|
||||
doItemClick(withId(R.id.recyclerView), 0);
|
||||
|
||||
sleep(DELAY_MEDIUM);
|
||||
|
||||
// bring up keyboard
|
||||
doClick(withId(R.id.input_text), DELAY_SMALL);
|
||||
|
||||
String msg1 = getApplicationContext()
|
||||
.getString(R.string.screenshot_message_1);
|
||||
onView(withId(R.id.input_text))
|
||||
.perform(waitUntilMatches(isEnabled()))
|
||||
.perform(replaceText(msg1));
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
doClick(withId(R.id.compositeSendButton));
|
||||
|
||||
sleep(DELAY_SMALL);
|
||||
|
||||
// send emoji
|
||||
doClick(withId(R.id.emoji_toggle), DELAY_SMALL);
|
||||
onView(withId(R.id.input_text))
|
||||
.perform(replaceText("\uD83D\uDE0E"));
|
||||
sleep(DELAY_SMALL);
|
||||
doClick(withId(R.id.compositeSendButton));
|
||||
|
||||
// close keyboard
|
||||
closeKeyboard(withId(R.id.compositeSendButton));
|
||||
|
||||
sleep(DELAY_LONG);
|
||||
}
|
||||
|
||||
private void doClick(final Matcher<View> viewMatcher, long sleepMs)
|
||||
throws InterruptedException {
|
||||
doClick(viewMatcher);
|
||||
if (!debug) sleep(sleepMs);
|
||||
}
|
||||
|
||||
private void doClick(final Matcher<View> viewMatcher)
|
||||
throws InterruptedException {
|
||||
if (!debug) {
|
||||
onView(viewMatcher)
|
||||
.perform(waitUntilMatches(isDisplayed()))
|
||||
.perform(visualClick(overlayView));
|
||||
sleep(500);
|
||||
}
|
||||
onView(viewMatcher)
|
||||
.perform(waitUntilMatches(allOf(isDisplayed(), isEnabled())))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
private void doItemClick(final Matcher<View> viewMatcher, int pos)
|
||||
throws InterruptedException {
|
||||
if (!debug) {
|
||||
onView(viewMatcher).perform(
|
||||
actionOnItemAtPosition(pos, visualClick(overlayView)));
|
||||
sleep(500);
|
||||
}
|
||||
onView(viewMatcher).perform(
|
||||
actionOnItemAtPosition(pos, click()));
|
||||
}
|
||||
|
||||
private void closeKeyboard(final Matcher<View> viewMatcher)
|
||||
throws InterruptedException {
|
||||
if (!debug) sleep(750);
|
||||
onView(viewMatcher).perform(closeSoftKeyboard());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logoView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
||||
Reference in New Issue
Block a user