Commit f0e2d528 authored by Torsten Grote's avatar Torsten Grote

Create Screenshot of Conversation for Manual

parent 097d14b9
......@@ -3,6 +3,7 @@ locales ['en-US']
use_tests_in_classes([
'org.briarproject.briar.android.login.SetupActivityScreenshotTest',
'org.briarproject.briar.android.settings.SettingsActivityScreenshotTest',
'org.briarproject.briar.android.contact.ConversationActivityScreenshotTest',
])
app_apk_path "build/outputs/apk/screenshot/debug/briar-android-screenshot-debug.apk"
tests_apk_path "build/outputs/apk/androidTest/screenshot/debug/briar-android-screenshot-debug-androidTest.apk"
......
......@@ -4,4 +4,8 @@ adb shell am broadcast -a com.android.systemui.demo -e command enter
adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false
adb shell am broadcast -a com.android.systemui.demo -e command battery -e level 100
adb shell am broadcast -a com.android.systemui.demo -e command network -e wifi show
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1337
\ No newline at end of file
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1337
# workaround for Android Pie hidden API Espresso bug
adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1
......@@ -12,4 +12,4 @@
-keep class junit.** { *; }
-dontwarn junit.**
-dontwarn org.briarproject.briar.android.BriarTestComponentApplication
\ No newline at end of file
-dontwarn org.briarproject.briar.android.**
......@@ -4,6 +4,7 @@ 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.contact.ConversationActivityScreenshotTest;
import org.briarproject.briar.android.login.SetupActivityScreenshotTest;
import org.briarproject.briar.android.navdrawer.NavDrawerActivityTest;
import org.briarproject.briar.android.settings.SettingsActivityScreenshotTest;
......@@ -22,6 +23,7 @@ import dagger.Component;
})
public interface BriarUiTestComponent extends AndroidComponent {
void inject(ConversationActivityScreenshotTest test);
void inject(SetupActivityScreenshotTest test);
void inject(NavDrawerActivityTest test);
void inject(SettingsActivityScreenshotTest test);
......
package org.briarproject.briar.android.contact;
import android.content.Context;
import android.content.Intent;
import android.support.test.runner.AndroidJUnit4;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.R;
import org.briarproject.briar.android.BriarUiTestComponent;
import org.briarproject.briar.android.test.ScreenshotTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
import static org.briarproject.briar.android.test.ViewActions.waitUntilMatches;
import static org.hamcrest.Matchers.allOf;
@RunWith(AndroidJUnit4.class)
public class ConversationActivityScreenshotTest extends ScreenshotTest {
@Rule
public CleanAccountTestRule<ConversationActivity> testRule =
new CleanAccountTestRule<>(ConversationActivity.class,
this::createTestData);
@Override
protected void inject(BriarUiTestComponent component) {
component.inject(this);
}
@Test
public void messaging() {
Context targetContext = getInstrumentation().getTargetContext();
Intent intent = new Intent(targetContext, ConversationActivity.class);
intent.putExtra(CONTACT_ID, 1);
testRule.launchActivity(intent);
onView(withId(R.id.conversationView)).perform(waitUntilMatches(
allOf(withText(R.string.screenshot_message_3), isDisplayed())));
screenshot("manual_messaging");
}
private void createTestData() {
try {
createTestDataExceptions();
} catch (DbException | FormatException e) {
throw new AssertionError(e);
}
}
private void createTestDataExceptions()
throws DbException, FormatException {
String bobName =
getTargetContext().getString(R.string.screenshot_bob);
Contact bob = testDataCreator.addContact(bobName);
String bobHi = getTargetContext()
.getString(R.string.screenshot_message_1);
long bobTime = getMinutesAgo(2);
testDataCreator.addPrivateMessage(bob, bobHi, bobTime, true);
String aliceHi = getTargetContext()
.getString(R.string.screenshot_message_2);
long aliceTime = getMinutesAgo(1);
testDataCreator.addPrivateMessage(bob, aliceHi, aliceTime, false);
String bobHi2 = getTargetContext()
.getString(R.string.screenshot_message_3);
long bobTime2 = getMinutesAgo(0);
testDataCreator.addPrivateMessage(bob, bobHi2, bobTime2, true);
connectionRegistry.registerConnection(bob.getId(), ID, true);
}
}
package org.briarproject.briar.android.test;
import android.app.Activity;
import android.content.Intent;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.util.Log;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.android.BriarService;
import org.briarproject.briar.android.BriarTestComponentApplication;
import org.briarproject.briar.android.BriarUiTestComponent;
import org.briarproject.briar.api.test.TestDataCreator;
import org.junit.ClassRule;
import javax.annotation.Nullable;
import javax.inject.Inject;
import tools.fastlane.screengrab.Screengrab;
......@@ -31,6 +38,12 @@ public abstract class ScreenshotTest {
protected AccountManager accountManager;
@Inject
protected LifecycleManager lifecycleManager;
@Inject
protected TestDataCreator testDataCreator;
@Inject
protected ConnectionRegistry connectionRegistry;
@Inject
protected Clock clock;
public ScreenshotTest() {
super();
......@@ -55,11 +68,30 @@ public abstract class ScreenshotTest {
}
}
protected long getMinutesAgo(int minutes) {
return clock.currentTimeMillis() - minutes * 60 * 1000;
}
@NotNullByDefault
protected class CleanAccountTestRule<A extends Activity>
extends IntentsTestRule<A> {
@Nullable
private final Runnable runnable;
public CleanAccountTestRule(Class<A> activityClass) {
super(activityClass);
this.runnable = null;
}
/**
* Use this if you need to run code before launching the activity.
* Note: You need to use {@link #launchActivity(Intent)} yourself
* to start the activity.
*/
public CleanAccountTestRule(Class<A> activityClass, Runnable runnable) {
super(activityClass, false, false);
this.runnable = runnable;
}
@Override
......@@ -67,6 +99,17 @@ public abstract class ScreenshotTest {
super.beforeActivityLaunched();
accountManager.deleteAccount();
accountManager.createAccount(USERNAME, PASSWORD);
if (runnable != null) {
Intent serviceIntent =
new Intent(getTargetContext(), BriarService.class);
getTargetContext().startService(serviceIntent);
try {
lifecycleManager.waitForStartup();
} catch (InterruptedException e) {
throw new AssertionError(e);
}
runnable.run();
}
}
}
......
......@@ -478,4 +478,20 @@
<string name="lock_is_locked">Briar is locked</string>
<string name="lock_tap_to_unlock">Tap to unlock</string>
<!-- Screenshots -->
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
<string name="screenshot_alice">Alice</string>
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
<string name="screenshot_bob">Bob</string>
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
<string name="screenshot_carol">Carol</string>
<!-- This is a message to be used in screenshots. Please use the same translation for Bob! -->
<string name="screenshot_message_1">Hi Bob!</string>
<!-- This is a message to be used in screenshots. Please use the same translation for Alice! -->
<string name="screenshot_message_2">Hi Alice! Thanks for telling me about Briar!</string>
<!-- This is a message to be used in screenshots. -->
<string name="screenshot_message_3">No problem, hope you like it 😀</string>
</resources>
package org.briarproject.briar.api.test;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface TestDataCreator {
/**
* Create fake test data on the DatabaseExecutor
* Create fake test data on the IoExecutor
*
* @param numContacts Number of contacts to create. Must be >= 1
* @param numPrivateMsgs Number of private messages to create for each
......@@ -18,4 +22,11 @@ public interface TestDataCreator {
void createTestData(int numContacts, int numPrivateMsgs, int numBlogPosts,
int numForums, int numForumPosts);
@IoExecutor
Contact addContact(String name) throws DbException;
@IoExecutor
void addPrivateMessage(Contact contact, String body, long time,
boolean local) throws DbException, FormatException;
}
......@@ -2,6 +2,7 @@ package org.briarproject.briar.test;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
......@@ -13,15 +14,18 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothConstants;
import org.briarproject.bramble.api.plugin.LanTcpConstants;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
......@@ -30,10 +34,12 @@ import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPost;
import org.briarproject.briar.api.blog.BlogPostFactory;
import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.forum.Forum;
import org.briarproject.briar.api.forum.ForumManager;
import org.briarproject.briar.api.forum.ForumPost;
import org.briarproject.briar.api.forum.ForumSharingManager;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
......@@ -59,6 +65,7 @@ import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.test.TestData.AUTHOR_NAMES;
import static org.briarproject.briar.test.TestData.GROUP_NAMES;
@NotNullByDefault
public class TestDataCreatorImpl implements TestDataCreator {
private final Logger LOG =
......@@ -75,6 +82,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
private final DatabaseComponent db;
private final IdentityManager identityManager;
private final ContactManager contactManager;
private final ContactGroupFactory contactGroupFactory;
private final TransportPropertyManager transportPropertyManager;
private final MessagingManager messagingManager;
private final BlogManager blogManager;
......@@ -93,6 +101,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
BlogPostFactory blogPostFactory, CryptoComponent cryptoComponent,
DatabaseComponent db, IdentityManager identityManager,
ContactManager contactManager,
ContactGroupFactory contactGroupFactory,
TransportPropertyManager transportPropertyManager,
MessagingManager messagingManager, BlogManager blogManager,
ForumManager forumManager, @IoExecutor Executor ioExecutor) {
......@@ -106,6 +115,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
this.db = db;
this.identityManager = identityManager;
this.contactManager = contactManager;
this.contactGroupFactory = contactGroupFactory;
this.transportPropertyManager = transportPropertyManager;
this.messagingManager = messagingManager;
this.blogManager = blogManager;
......@@ -146,17 +156,17 @@ public class TestDataCreatorImpl implements TestDataCreator {
List<Contact> contacts = new ArrayList<>(numContacts);
LocalAuthor localAuthor = identityManager.getLocalAuthor();
for (int i = 0; i < numContacts; i++) {
Contact contact = addRandomContact(localAuthor);
LocalAuthor author = getRandomAuthor();
Contact contact = addContact(localAuthor.getId(), author);
contacts.add(contact);
}
return contacts;
}
private Contact addRandomContact(LocalAuthor localAuthor)
private Contact addContact(AuthorId localAuthorId, LocalAuthor author)
throws DbException {
// prepare to add contact
LocalAuthor author = getRandomAuthor();
SecretKey secretKey = getSecretKey();
long timestamp = clock.currentTimeMillis();
boolean verified = random.nextBoolean();
......@@ -169,10 +179,11 @@ public class TestDataCreatorImpl implements TestDataCreator {
Transaction txn = db.startTransaction(false);
try {
ContactId contactId = contactManager
.addContact(txn, author, localAuthor.getId(), secretKey,
.addContact(txn, author, localAuthorId, secretKey,
timestamp, true, verified, true);
transportPropertyManager.addRemoteProperties(txn, contactId, props);
contact = db.getContact(txn, contactId);
fakeClientVisibilities(txn, contact);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
......@@ -186,14 +197,27 @@ public class TestDataCreatorImpl implements TestDataCreator {
return contact;
}
private LocalAuthor getRandomAuthor() {
int i = random.nextInt(AUTHOR_NAMES.length);
String authorName = AUTHOR_NAMES[i];
@Override
public Contact addContact(String name) throws DbException {
// load localAuthor from DB, because cache doesn't get refreshed
// when Espresso tests run within one lifecycle
Transaction txn = db.startTransaction(false);
LocalAuthor localAuthor = db.getLocalAuthors(txn).iterator().next();
db.endTransaction(txn);
return addContact(localAuthor.getId(), getAuthor(name));
}
private LocalAuthor getAuthor(String name) {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
return authorFactory.createLocalAuthor(authorName, publicKey,
privateKey);
return authorFactory.createLocalAuthor(name, publicKey, privateKey);
}
private LocalAuthor getRandomAuthor() {
int i = random.nextInt(AUTHOR_NAMES.length);
String authorName = AUTHOR_NAMES[i];
return getAuthor(authorName);
}
private SecretKey getSecretKey() {
......@@ -285,7 +309,8 @@ public class TestDataCreatorImpl implements TestDataCreator {
Group group = messagingManager.getContactGroup(contact);
for (int i = 0; i < numPrivateMsgs; i++) {
try {
createPrivateMessage(group.getId(), i);
createRandomPrivateMessage(contact.getId(), group.getId(),
i);
} catch (FormatException e) {
throw new RuntimeException(e);
}
......@@ -297,23 +322,30 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
}
private void createPrivateMessage(GroupId groupId, int num)
throws DbException, FormatException {
private void createRandomPrivateMessage(ContactId contactId,
GroupId groupId, int num) throws DbException, FormatException {
long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
String body = getRandomText();
boolean local = random.nextBoolean();
createPrivateMessage(contactId, groupId, body, timestamp, local);
}
private void createPrivateMessage(ContactId contactId, GroupId groupId,
String body, long timestamp, boolean local)
throws DbException, FormatException {
PrivateMessage m = privateMessageFactory
.createPrivateMessage(groupId, timestamp, body);
boolean local = random.nextBoolean();
BdfDictionary meta = new BdfDictionary();
meta.put("timestamp", timestamp);
meta.put("local", local);
meta.put("read", local); // all local messages are read
Transaction txn = db.startTransaction(false);
try {
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
if (local) messageTracker.trackOutgoingMessage(txn, m.getMessage());
if (local) {
messageTracker.trackOutgoingMessage(txn, m.getMessage());
db.receiveMessage(txn, contactId, m.getMessage());
}
else messageTracker.trackIncomingMessage(txn, m.getMessage());
db.commitTransaction(txn);
} finally {
......@@ -321,6 +353,14 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
}
@Override
public void addPrivateMessage(Contact contact, String body, long time,
boolean local) throws DbException, FormatException {
Group group = messagingManager.getContactGroup(contact);
createPrivateMessage(contact.getId(), group.getId(), body, time,
local);
}
private void createBlogPosts(List<Contact> contacts, int numBlogPosts)
throws DbException {
for (int i = 0; i < numBlogPosts; i++) {
......@@ -399,6 +439,23 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
}
private void fakeClientVisibilities(Transaction txn, Contact contact)
throws DbException {
fakeClientVisibilities(txn, contact, MessagingManager.CLIENT_ID,
MessagingManager.MAJOR_VERSION);
fakeClientVisibilities(txn, contact, ForumSharingManager.CLIENT_ID,
ForumSharingManager.MAJOR_VERSION);
fakeClientVisibilities(txn, contact, BlogSharingManager.CLIENT_ID,
BlogSharingManager.MAJOR_VERSION);
}
private void fakeClientVisibilities(Transaction txn, Contact contact,
ClientId clientId, int majorVersion) throws DbException {
Group group = contactGroupFactory
.createContactGroup(clientId, majorVersion, contact);
db.setGroupVisibility(txn, contact.getId(), group.getId(), SHARED);
}
private String getRandomText() {
int minLength = 3 + random.nextInt(500);
int maxWordLength = 15;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment