Add very basic onboarding and sharing test (#2031)

* Start creating onboarding test

* Start adding sharing test

* Create very basic sharing test
This commit is contained in:
Hocuri 2021-10-04 15:58:07 +02:00 committed by GitHub
parent 1b6965e43e
commit a2ffa4cd5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 333 additions and 39 deletions

View file

@ -0,0 +1,161 @@
package com.b44t.messenger;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.test.espresso.NoMatchingViewException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.ViewInteraction;
import androidx.test.espresso.util.TreeIterables;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import org.hamcrest.Matcher;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.AccountManager;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.typeText;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withHint;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
class TestUtils {
private static int createdAccountId = 0;
private static boolean resetEnterSends = false;
public static void cleanupCreatedAccount(Context context) {
DcAccounts accounts = DcHelper.getAccounts(context);
if (createdAccountId != 0) {
accounts.removeAccount(createdAccountId);
createdAccountId = 0;
}
}
public static void cleanup() {
Context context = getInstrumentation().getTargetContext();
cleanupCreatedAccount(context);
if (resetEnterSends) {
Prefs.setEnterSendsEnabled(getInstrumentation().getTargetContext(), false);
}
}
public static void createOfflineAccount() {
Context context = getInstrumentation().getTargetContext();
cleanupCreatedAccount(context);
createdAccountId = AccountManager.getInstance().beginAccountCreation(context);
DcContext c = DcHelper.getContext(context);
c.setConfig("configured_addr", "alice@example.org");
c.setConfig("configured_mail_pw", "abcd");
c.setConfig("configured", "1");
}
@NonNull
static ActivityScenarioRule<ConversationListActivity> getOfflineActivityRule() {
Intent intent =
Intent.makeMainActivity(
new ComponentName(getInstrumentation().getTargetContext(), ConversationListActivity.class));
TestUtils.createOfflineAccount();
return new ActivityScenarioRule<>(intent);
}
/**
* Perform action of waiting for a certain view within a single root view
*
* @param matcher Generic Matcher used to find our view
*/
static ViewAction searchFor(Matcher<View> matcher) {
return new ViewAction() {
public Matcher<View> getConstraints() {
return isRoot();
}
public String getDescription() {
return "searching for view $matcher in the root view";
}
public void perform(UiController uiController, View view) {
Iterable<View> childViews = TreeIterables.breadthFirstViewTraversal(view);
// Look for the match in the tree of childviews
for (View it : childViews) {
if (matcher.matches(it)) {
// found the view
return;
}
}
throw new NoMatchingViewException.Builder()
.withRootView(view)
.withViewMatcher(matcher)
.build();
}
};
}
/**
* Perform action of implicitly waiting for a certain view.
* This differs from EspressoExtensions.searchFor in that,
* upon failure to locate an element, it will fetch a new root view
* in which to traverse searching for our @param match
*
* @param viewMatcher ViewMatcher used to find our view
*/
public static ViewInteraction waitForView(
Matcher<View> viewMatcher,
int waitMillis,
int waitMillisPerTry
) {
// Derive the max tries
int maxTries = (int) (waitMillis / waitMillisPerTry);
int tries = 0;
for (int i = 0; i < maxTries; i++)
try {
// Track the amount of times we've tried
tries++;
// Search the root for the view
onView(isRoot()).perform(searchFor(viewMatcher));
// If we're here, we found our view. Now return it
return onView(viewMatcher);
} catch (Exception e) {
if (tries == maxTries) {
throw e;
}
Util.sleep(waitMillisPerTry);
}
throw new RuntimeException("Error finding a view matching $viewMatcher");
}
/**
* Normally, you would do
* onView(withId(R.id.send_button)).perform(click());
* to send the draft message. However, in order to change the send button to the attach button
* while there is no draft, the send button is made invisible and the attach button is made
* visible instead. This confuses the test framework.<br/><br/>
*
* So, this is a workaround for pressing the send button.
*/
public static void pressSend() {
if (!Prefs.isEnterSendsEnabled(getInstrumentation().getTargetContext())) {
resetEnterSends = true;
Prefs.setEnterSendsEnabled(getInstrumentation().getTargetContext(), true);
}
onView(withHint(R.string.chat_input_placeholder)).perform(typeText("\n"));
}
}